schnorr 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +22 -1
- data/lib/schnorr/version.rb +1 -1
- data/lib/schnorr.rb +43 -1
- data/schnorrrb.gemspec +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 27c028f23478e028b813e4bf12bbb1bd6b9f92b75d758554c71e298b0f3a9077
|
4
|
+
data.tar.gz: 2943cdc9afc73fecc8804b6c498ef0f55a850a63b71422ecf716c0d3b496e164
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 94e5c230cbda7f0fa66a30da0f3a62d2950aaf42b34e2c0d24980f65616d0c31b5b289eac48eaf717fd3052d3ea57d8664d373bec16298c36611c38d51162804
|
7
|
+
data.tar.gz: f83ad1edee227ee190495ae58743dc461ca1e0753925ad3c01fe6d68ab92bf02b8e4d00c3043fdb1eb2f2bd568791e0f80b3615d478c6c99f66565a72090eddf
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Schnorrrb [](https://travis-ci.org/chaintope/schnorrrb) [](https://travis-ci.org/chaintope/schnorrrb) [](https://badge.fury.io/rb/schnorr) [](LICENSE)
|
2
2
|
|
3
3
|
This is a Ruby implementation of the Schnorr signature scheme over the elliptic curve.
|
4
4
|
This implementation relies on the [ecdsa gem](https://github.com/DavidEGrayson/ruby_ecdsa) for operate elliptic curves.
|
@@ -65,6 +65,27 @@ result = Schnorr.valid_sig?(message, public_key, signature)
|
|
65
65
|
sig = Schnorr::Signature.decode(signature)
|
66
66
|
```
|
67
67
|
|
68
|
+
### Batch verification
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
require 'schnorr'
|
72
|
+
|
73
|
+
pubkeys = ['03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B'].pack('H*')
|
74
|
+
pubkeys << ['02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659'].pack('H*')
|
75
|
+
...
|
76
|
+
|
77
|
+
messages = ['5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C'].pack('H*')
|
78
|
+
messages << ['243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89'].pack('H*')
|
79
|
+
...
|
80
|
+
|
81
|
+
signatures = [`00DA9B08172A9B6F0466A2DEFD817F2D7AB437E0D253CB5395A963866B3574BE00880371D01766935B92D2AB4CD5C8A2A5837EC57FED7660773A05F0DE142380`].pack('H*')
|
82
|
+
signatures << [`787A848E71043D280C50470E8E1532B2DD5D20EE912A45DBDD2BD1DFBF187EF68FCE5677CE7A623CB20011225797CE7A8DE1DC6CCD4F754A47DA6C600E59543C`].pack('H*')
|
83
|
+
...
|
84
|
+
|
85
|
+
# batch verify signature.(result is true or false)
|
86
|
+
result = Schnorr.valid_sig?(messages, pubkeys, signatures)
|
87
|
+
```
|
88
|
+
|
68
89
|
### Change elliptic curve
|
69
90
|
|
70
91
|
This library use `secp256k1` curve as default. If you use another curve, you need to specify curve as following:
|
data/lib/schnorr/version.rb
CHANGED
data/lib/schnorr.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'ecdsa'
|
2
|
+
require 'securerandom'
|
2
3
|
require_relative 'schnorr/signature'
|
3
4
|
|
4
5
|
module Schnorr
|
@@ -39,6 +40,48 @@ module Schnorr
|
|
39
40
|
false
|
40
41
|
end
|
41
42
|
|
43
|
+
# Batch verification
|
44
|
+
# @param messages (Array[String]) The array of message with binary format.
|
45
|
+
# @param public_keys (Array[String]) The array of public key with binary format.
|
46
|
+
# @param signatures (Array[String]) The array of signatures with binary format.
|
47
|
+
# @param group (ECDSA::Group) The curve that is being used.
|
48
|
+
# @return (Boolean) whether signature is valid.
|
49
|
+
def valid_sigs?(messages, public_keys, signatures, group: ECDSA::Group::Secp256k1)
|
50
|
+
raise ArgumentError, 'all parameters must be an array with the same length.' if messages.size != public_keys.size || public_keys.size != signatures.size
|
51
|
+
field = group.field
|
52
|
+
pubkeys = public_keys.map{|p| ECDSA::Format::PointOctetString.decode(p, group)}
|
53
|
+
sigs = signatures.map do|signature|
|
54
|
+
sig = Schnorr::Signature.decode(signature)
|
55
|
+
raise Schnorr::InvalidSignatureError, 'Invalid signature: r is not in the field.' unless field.include?(sig.r)
|
56
|
+
raise Schnorr::InvalidSignatureError, 'Invalid signature: s is not in the field.' unless field.include?(sig.s)
|
57
|
+
raise Schnorr::InvalidSignatureError, 'Invalid signature: r is zero.' if sig.r.zero?
|
58
|
+
raise Schnorr::InvalidSignatureError, 'Invalid signature: s is zero.' if sig.s.zero?
|
59
|
+
sig
|
60
|
+
end
|
61
|
+
left = 0
|
62
|
+
right = nil
|
63
|
+
pubkeys.each_with_index do |pubkey, i|
|
64
|
+
r = sigs[i].r
|
65
|
+
s = sigs[i].s
|
66
|
+
e = create_challenge(r, pubkey, messages[i], field, group)
|
67
|
+
c = field.mod(r.pow(3) + 7)
|
68
|
+
y = c.pow((field.prime + 1)/4, field.prime)
|
69
|
+
raise Schnorr::InvalidSignatureError, 'c is not equal to y^2.' unless c == y.pow(2, field.prime)
|
70
|
+
r_point = ECDSA::Point.new(group, r, y)
|
71
|
+
if i == 0
|
72
|
+
left = s
|
73
|
+
right = r_point + pubkey.multiply_by_scalar(e)
|
74
|
+
else
|
75
|
+
a = 1 + SecureRandom.random_number(group.order - 1)
|
76
|
+
left += (a * s)
|
77
|
+
right += (r_point.multiply_by_scalar(a) + pubkey.multiply_by_scalar(a * e))
|
78
|
+
end
|
79
|
+
end
|
80
|
+
group.new_point(left) == right
|
81
|
+
rescue InvalidSignatureError, ECDSA::Format::DecodeError
|
82
|
+
false
|
83
|
+
end
|
84
|
+
|
42
85
|
# Verifies the given {Signature} and raises an {InvalidSignatureError} if it is invalid.
|
43
86
|
# @param message (String) A message to be signed with binary format.
|
44
87
|
# @param public_key (String) The public key with binary format.
|
@@ -59,7 +102,6 @@ module Schnorr
|
|
59
102
|
|
60
103
|
r = group.new_point(sig.s) + pubkey.multiply_by_scalar(e).negate
|
61
104
|
|
62
|
-
|
63
105
|
if r.infinity? || ECDSA::PrimeField.jacobi(r.y, group.field.prime) != 1 || r.x != sig.r
|
64
106
|
raise Schnorr::InvalidSignatureError, 'signature verification failed.'
|
65
107
|
end
|
data/schnorrrb.gemspec
CHANGED
@@ -7,7 +7,7 @@ Gem::Specification.new do |spec|
|
|
7
7
|
spec.name = "schnorr"
|
8
8
|
spec.version = Schnorr::VERSION
|
9
9
|
spec.authors = ["azuchi"]
|
10
|
-
spec.email = ["azuchi@
|
10
|
+
spec.email = ["azuchi@chaintope.com"]
|
11
11
|
|
12
12
|
spec.summary = %q{The ruby implementation of Schnorr signature.}
|
13
13
|
spec.description = %q{The ruby implementation of Schnorr signature.}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: schnorr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- azuchi
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-04-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ecdsa
|
@@ -68,7 +68,7 @@ dependencies:
|
|
68
68
|
version: '3.0'
|
69
69
|
description: The ruby implementation of Schnorr signature.
|
70
70
|
email:
|
71
|
-
- azuchi@
|
71
|
+
- azuchi@chaintope.com
|
72
72
|
executables: []
|
73
73
|
extensions: []
|
74
74
|
extra_rdoc_files: []
|
@@ -108,7 +108,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
108
108
|
- !ruby/object:Gem::Version
|
109
109
|
version: '0'
|
110
110
|
requirements: []
|
111
|
-
|
111
|
+
rubyforge_project:
|
112
|
+
rubygems_version: 2.7.8
|
112
113
|
signing_key:
|
113
114
|
specification_version: 4
|
114
115
|
summary: The ruby implementation of Schnorr signature.
|