schnorr_sig 0.1.0.1 → 0.2.1.1
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/VERSION +1 -1
- data/lib/schnorr_sig/fast.rb +2 -2
- data/lib/schnorr_sig/pure.rb +221 -0
- data/lib/schnorr_sig.rb +9 -220
- data/test/vectors.rb +1 -2
- data/test/vectors_extra.rb +1 -2
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 22902f36da6e027cac43fc471364294806a80fdc6d88e3743566d06ae632b3a1
|
4
|
+
data.tar.gz: a3759fb782d4aec2fd78b02113d6717bbf9892f6fb3b82be866b08e07ba38d5a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5afe8575ec3355d303720539e2e5019639214374f26cefa9c89f52dabd625dc79e12f055b4f5c775f40cf334a7ac11deaa095cc6295e6cd6e5ed3b3f27439dc2
|
7
|
+
data.tar.gz: 5950afef772f28370c7f1ca12bda717f560f8cf2f76d1c255fede1a8ce1677dea8dbd17ba4e4c55af7ac475058892c0da17e13235d6574b3155b7da6912d9f8c
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.2.1.1
|
data/lib/schnorr_sig/fast.rb
CHANGED
@@ -0,0 +1,221 @@
|
|
1
|
+
require 'schnorr_sig/util' # project
|
2
|
+
require 'ecdsa_ext' # gem
|
3
|
+
autoload :SecureRandom, 'securerandom' # stdlib
|
4
|
+
|
5
|
+
# This implementation is based on the BIP340 spec: https://bips.xyz/340
|
6
|
+
# re-open SchnorrSig to add more functions, errors, and constants
|
7
|
+
module SchnorrSig
|
8
|
+
class Error < RuntimeError; end
|
9
|
+
class BoundsError < Error; end
|
10
|
+
class SanityCheck < Error; end
|
11
|
+
class VerifyFail < Error; end
|
12
|
+
class InfinityPoint < Error; end
|
13
|
+
|
14
|
+
GROUP = ECDSA::Group::Secp256k1
|
15
|
+
P = GROUP.field.prime # smaller than 256**32
|
16
|
+
N = GROUP.order # smaller than P
|
17
|
+
B = GROUP.byte_length # 32
|
18
|
+
|
19
|
+
# val (dot) G, returns ECDSA::Point
|
20
|
+
def self.dot_group(val)
|
21
|
+
# ecdsa_ext uses jacobian projection: 10x faster than GROUP.generator * val
|
22
|
+
(GROUP.generator.to_jacobian * val).to_affine
|
23
|
+
end
|
24
|
+
|
25
|
+
# returns even_val or N - even_val
|
26
|
+
def self.select_even_y(point, even_val)
|
27
|
+
point.y.even? ? even_val : N - even_val
|
28
|
+
end
|
29
|
+
|
30
|
+
# int(x) function signature matches BIP340, returns a bignum (presumably)
|
31
|
+
class << self
|
32
|
+
alias_method :int, :bin2big
|
33
|
+
end
|
34
|
+
|
35
|
+
# bytes(val) function signature matches BIP340, returns a binary string
|
36
|
+
def self.bytes(val)
|
37
|
+
case val
|
38
|
+
when Integer
|
39
|
+
# BIP340: The function bytes(x), where x is an integer,
|
40
|
+
# returns the 32-byte encoding of x, most significant byte first.
|
41
|
+
big2bin(val)
|
42
|
+
when ECDSA::Point
|
43
|
+
# BIP340: The function bytes(P), where P is a point, returns bytes(x(P)).
|
44
|
+
val.infinity? ? raise(InfinityPoint, va.inspect) : big2bin(val.x)
|
45
|
+
else
|
46
|
+
raise(SanityCheck, val.inspect)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Input
|
51
|
+
# The secret key, sk: 32 bytes binary
|
52
|
+
# The message, m: binary / UTF-8 / agnostic
|
53
|
+
# Auxiliary random data, a: 32 bytes binary
|
54
|
+
# Output
|
55
|
+
# The signature, sig: 64 bytes binary
|
56
|
+
def self.sign(sk, m, a = Random.bytes(B))
|
57
|
+
bytestring!(sk, B) and string!(m) and bytestring!(a, B)
|
58
|
+
|
59
|
+
# BIP340: Let d' = int(sk)
|
60
|
+
# BIP340: Fail if d' = 0 or d' >= n
|
61
|
+
d0 = int(sk)
|
62
|
+
raise(BoundsError, "d0") if !d0.positive? or d0 >= N
|
63
|
+
|
64
|
+
# BIP340: Let P = d' . G
|
65
|
+
p = dot_group(d0) # this is a point on the elliptic curve
|
66
|
+
bytes_p = bytes(p)
|
67
|
+
|
68
|
+
# BIP340: Let d = d' if has_even_y(P), otherwise let d = n - d'
|
69
|
+
d = select_even_y(p, d0)
|
70
|
+
|
71
|
+
# BIP340: Let t be the bytewise xor of bytes(d) and hash[BIP0340/aux](a)
|
72
|
+
t = d ^ int(tagged_hash('BIP0340/aux', a))
|
73
|
+
|
74
|
+
# BIP340: Let rand = hash[BIP0340/nonce](t || bytes(P) || m)
|
75
|
+
nonce = tagged_hash('BIP0340/nonce', bytes(t) + bytes_p + m)
|
76
|
+
|
77
|
+
# BIP340: Let k' = int(rand) mod n
|
78
|
+
# BIP340: Fail if k' = 0
|
79
|
+
k0 = int(nonce) % N
|
80
|
+
raise(BoundsError, "k0") if !k0.positive?
|
81
|
+
|
82
|
+
# BIP340: Let R = k' . G
|
83
|
+
r = dot_group(k0) # this is a point on the elliptic curve
|
84
|
+
bytes_r = bytes(r)
|
85
|
+
|
86
|
+
# BIP340: Let k = k' if has_even_y(R), otherwise let k = n - k'
|
87
|
+
k = select_even_y(r, k0)
|
88
|
+
|
89
|
+
# BIP340:
|
90
|
+
# Let e = int(hash[BIP0340/challenge](bytes(R) || bytes(P) || m)) mod n
|
91
|
+
e = int(tagged_hash('BIP0340/challenge', bytes_r + bytes_p + m)) % N
|
92
|
+
|
93
|
+
# BIP340: Let sig = bytes(R) || bytes((k + ed) mod n)
|
94
|
+
# BIP340: Fail unless Verify(bytes(P), m, sig)
|
95
|
+
# BIP340: Return the signature sig
|
96
|
+
sig = bytes_r + bytes((k + e * d) % N)
|
97
|
+
raise(VerifyFail) unless verify?(bytes_p, m, sig)
|
98
|
+
sig
|
99
|
+
end
|
100
|
+
|
101
|
+
# see https://bips.xyz/340#design (Tagged hashes)
|
102
|
+
# Input
|
103
|
+
# A tag: UTF-8 > binary > agnostic
|
104
|
+
# The payload, msg: UTF-8 / binary / agnostic
|
105
|
+
# Output
|
106
|
+
# 32 bytes binary
|
107
|
+
def self.tagged_hash(tag, msg)
|
108
|
+
string!(tag) and string!(msg)
|
109
|
+
warn("tag expected to be UTF-8") unless tag.encoding == Encoding::UTF_8
|
110
|
+
|
111
|
+
# BIP340: The function hash[name](x) where x is a byte array
|
112
|
+
# returns the 32-byte hash
|
113
|
+
# SHA256(SHA256(tag) || SHA256(tag) || x)
|
114
|
+
# where tag is the UTF-8 encoding of name.
|
115
|
+
tag_hash = Digest::SHA256.digest(tag)
|
116
|
+
Digest::SHA256.digest(tag_hash + tag_hash + msg)
|
117
|
+
end
|
118
|
+
|
119
|
+
# Input
|
120
|
+
# The public key, pk: 32 bytes binary
|
121
|
+
# The message, m: UTF-8 / binary / agnostic
|
122
|
+
# A signature, sig: 64 bytes binary
|
123
|
+
# Output
|
124
|
+
# Boolean
|
125
|
+
def self.verify?(pk, m, sig)
|
126
|
+
bytestring!(pk, B) and string!(m) and bytestring!(sig, B * 2)
|
127
|
+
|
128
|
+
# BIP340: Let P = lift_x(int(pk))
|
129
|
+
p = lift_x(int(pk))
|
130
|
+
|
131
|
+
# BIP340: Let r = int(sig[0:32]) fail if r >= p
|
132
|
+
r = int(sig[0..B-1])
|
133
|
+
raise(BoundsError, "r >= p") if r >= P
|
134
|
+
|
135
|
+
# BIP340: Let s = int(sig[32:64]); fail if s >= n
|
136
|
+
s = int(sig[B..-1])
|
137
|
+
raise(BoundsError, "s >= n") if s >= N
|
138
|
+
|
139
|
+
# BIP340:
|
140
|
+
# Let e = int(hash[BIP0340/challenge](bytes(r) || bytes(P) || m)) mod n
|
141
|
+
e = bytes(r) + bytes(p) + m
|
142
|
+
e = int(tagged_hash('BIP0340/challenge', e)) % N
|
143
|
+
|
144
|
+
# BIP340: Let R = s . G - e . P
|
145
|
+
# BIP340: Fail if is_infinite(R)
|
146
|
+
# BIP340: Fail if not has_even_y(R)
|
147
|
+
# BIP340: Fail if x(R) != r
|
148
|
+
# BIP340: Return success iff no failure occurred before reaching this point
|
149
|
+
big_r = dot_group(s) + p.multiply_by_scalar(e).negate
|
150
|
+
!big_r.infinity? and big_r.y.even? and big_r.x == r
|
151
|
+
end
|
152
|
+
|
153
|
+
# BIP340: The function lift_x(x), where x is a 256-bit unsigned integer,
|
154
|
+
# returns the point P for which x(P) = x and has_even_y(P),
|
155
|
+
# or fails if x is greater than p-1 or no such point exists.
|
156
|
+
# Input
|
157
|
+
# A large integer, x
|
158
|
+
# Output
|
159
|
+
# ECDSA::Point
|
160
|
+
def self.lift_x(x)
|
161
|
+
integer!(x)
|
162
|
+
|
163
|
+
# BIP340: Fail if x >= p
|
164
|
+
raise(BoundsError, "x") if x >= P or x <= 0
|
165
|
+
|
166
|
+
# BIP340: Let c = x^3 + 7 mod p
|
167
|
+
c = (x.pow(3, P) + 7) % P
|
168
|
+
|
169
|
+
# BIP340: Let y = c ^ ((p + 1) / 4) mod p
|
170
|
+
y = c.pow((P + 1) / 4, P) # use pow to avoid Bignum overflow
|
171
|
+
|
172
|
+
# BIP340: Fail if c != y^2 mod p
|
173
|
+
raise(SanityCheck, "c != y^2 mod p") if c != y.pow(2, P)
|
174
|
+
|
175
|
+
# BIP340: Return the unique point P such that:
|
176
|
+
# x(P) = x and y(P) = y if y mod 2 = 0
|
177
|
+
# y(P) = p - y otherwise
|
178
|
+
GROUP.new_point [x, y.even? ? y : P - y]
|
179
|
+
end
|
180
|
+
|
181
|
+
# Input
|
182
|
+
# The secret key, sk: 32 bytes binary
|
183
|
+
# Output
|
184
|
+
# 32 bytes binary (represents P.x for point P on the curve)
|
185
|
+
def self.pubkey(sk)
|
186
|
+
bytestring!(sk, B)
|
187
|
+
|
188
|
+
# BIP340: Let d' = int(sk)
|
189
|
+
# BIP340: Fail if d' = 0 or d' >= n
|
190
|
+
# BIP340: Return bytes(d' . G)
|
191
|
+
d0 = int(sk)
|
192
|
+
raise(BoundsError, "d0") if !d0.positive? or d0 >= N
|
193
|
+
bytes(dot_group(d0))
|
194
|
+
end
|
195
|
+
|
196
|
+
# generate a new keypair based on random data
|
197
|
+
def self.keypair
|
198
|
+
sk = Random.bytes(B)
|
199
|
+
[sk, pubkey(sk)]
|
200
|
+
end
|
201
|
+
|
202
|
+
# as above, but using SecureRandom
|
203
|
+
def self.secure_keypair
|
204
|
+
sk = SecureRandom.bytes(B)
|
205
|
+
[sk, pubkey(sk)]
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
if __FILE__ == $0
|
210
|
+
msg = 'hello world'
|
211
|
+
sk, pk = SchnorrSig.keypair
|
212
|
+
puts "Message: #{msg}"
|
213
|
+
puts "Secret key: #{SchnorrSig.bin2hex(sk)}"
|
214
|
+
puts "Public key: #{SchnorrSig.bin2hex(pk)}"
|
215
|
+
|
216
|
+
sig = SchnorrSig.sign(sk, msg)
|
217
|
+
puts
|
218
|
+
puts "Verified signature: #{SchnorrSig.bin2hex(sig)}"
|
219
|
+
puts "Encoding: #{sig.encoding}"
|
220
|
+
puts "Length: #{sig.length}"
|
221
|
+
end
|
data/lib/schnorr_sig.rb
CHANGED
@@ -1,221 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
class SanityCheck < Error; end
|
11
|
-
class VerifyFail < Error; end
|
12
|
-
class InfinityPoint < Error; end
|
13
|
-
|
14
|
-
GROUP = ECDSA::Group::Secp256k1
|
15
|
-
P = GROUP.field.prime # smaller than 256**32
|
16
|
-
N = GROUP.order # smaller than P
|
17
|
-
B = GROUP.byte_length # 32
|
18
|
-
|
19
|
-
# val (dot) G, returns ECDSA::Point
|
20
|
-
def self.dot_group(val)
|
21
|
-
# ecdsa_ext uses jacobian projection: 10x faster than GROUP.generator * val
|
22
|
-
(GROUP.generator.to_jacobian * val).to_affine
|
23
|
-
end
|
24
|
-
|
25
|
-
# returns even_val or N - even_val
|
26
|
-
def self.select_even_y(point, even_val)
|
27
|
-
point.y.even? ? even_val : N - even_val
|
28
|
-
end
|
29
|
-
|
30
|
-
# int(x) function signature matches BIP340, returns a bignum (presumably)
|
31
|
-
class << self
|
32
|
-
alias_method :int, :bin2big
|
33
|
-
end
|
34
|
-
|
35
|
-
# bytes(val) function signature matches BIP340, returns a binary string
|
36
|
-
def self.bytes(val)
|
37
|
-
case val
|
38
|
-
when Integer
|
39
|
-
# BIP340: The function bytes(x), where x is an integer,
|
40
|
-
# returns the 32-byte encoding of x, most significant byte first.
|
41
|
-
big2bin(val)
|
42
|
-
when ECDSA::Point
|
43
|
-
# BIP340: The function bytes(P), where P is a point, returns bytes(x(P)).
|
44
|
-
val.infinity? ? raise(InfinityPoint, va.inspect) : big2bin(val.x)
|
45
|
-
else
|
46
|
-
raise(SanityCheck, val.inspect)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
# Input
|
51
|
-
# The secret key, sk: 32 bytes binary
|
52
|
-
# The message, m: binary / UTF-8 / agnostic
|
53
|
-
# Auxiliary random data, a: 32 bytes binary
|
54
|
-
# Output
|
55
|
-
# The signature, sig: 64 bytes binary
|
56
|
-
def self.sign(sk, m, a = Random.bytes(B))
|
57
|
-
bytestring!(sk, B) and string!(m) and bytestring!(a, B)
|
58
|
-
|
59
|
-
# BIP340: Let d' = int(sk)
|
60
|
-
# BIP340: Fail if d' = 0 or d' >= n
|
61
|
-
d0 = int(sk)
|
62
|
-
raise(BoundsError, "d0") if !d0.positive? or d0 >= N
|
63
|
-
|
64
|
-
# BIP340: Let P = d' . G
|
65
|
-
p = dot_group(d0) # this is a point on the elliptic curve
|
66
|
-
bytes_p = bytes(p)
|
67
|
-
|
68
|
-
# BIP340: Let d = d' if has_even_y(P), otherwise let d = n - d'
|
69
|
-
d = select_even_y(p, d0)
|
70
|
-
|
71
|
-
# BIP340: Let t be the bytewise xor of bytes(d) and hash[BIP0340/aux](a)
|
72
|
-
t = d ^ int(tagged_hash('BIP0340/aux', a))
|
73
|
-
|
74
|
-
# BIP340: Let rand = hash[BIP0340/nonce](t || bytes(P) || m)
|
75
|
-
nonce = tagged_hash('BIP0340/nonce', bytes(t) + bytes_p + m)
|
76
|
-
|
77
|
-
# BIP340: Let k' = int(rand) mod n
|
78
|
-
# BIP340: Fail if k' = 0
|
79
|
-
k0 = int(nonce) % N
|
80
|
-
raise(BoundsError, "k0") if !k0.positive?
|
81
|
-
|
82
|
-
# BIP340: Let R = k' . G
|
83
|
-
r = dot_group(k0) # this is a point on the elliptic curve
|
84
|
-
bytes_r = bytes(r)
|
85
|
-
|
86
|
-
# BIP340: Let k = k' if has_even_y(R), otherwise let k = n - k'
|
87
|
-
k = select_even_y(r, k0)
|
88
|
-
|
89
|
-
# BIP340:
|
90
|
-
# Let e = int(hash[BIP0340/challenge](bytes(R) || bytes(P) || m)) mod n
|
91
|
-
e = int(tagged_hash('BIP0340/challenge', bytes_r + bytes_p + m)) % N
|
92
|
-
|
93
|
-
# BIP340: Let sig = bytes(R) || bytes((k + ed) mod n)
|
94
|
-
# BIP340: Fail unless Verify(bytes(P), m, sig)
|
95
|
-
# BIP340: Return the signature sig
|
96
|
-
sig = bytes_r + bytes((k + e * d) % N)
|
97
|
-
raise(VerifyFail) unless verify?(bytes_p, m, sig)
|
98
|
-
sig
|
99
|
-
end
|
100
|
-
|
101
|
-
# see https://bips.xyz/340#design (Tagged hashes)
|
102
|
-
# Input
|
103
|
-
# A tag: UTF-8 > binary > agnostic
|
104
|
-
# The payload, msg: UTF-8 / binary / agnostic
|
105
|
-
# Output
|
106
|
-
# 32 bytes binary
|
107
|
-
def self.tagged_hash(tag, msg)
|
108
|
-
string!(tag) and string!(msg)
|
109
|
-
warn("tag expected to be UTF-8") unless tag.encoding == Encoding::UTF_8
|
110
|
-
|
111
|
-
# BIP340: The function hash[name](x) where x is a byte array
|
112
|
-
# returns the 32-byte hash
|
113
|
-
# SHA256(SHA256(tag) || SHA256(tag) || x)
|
114
|
-
# where tag is the UTF-8 encoding of name.
|
115
|
-
tag_hash = Digest::SHA256.digest(tag)
|
116
|
-
Digest::SHA256.digest(tag_hash + tag_hash + msg)
|
117
|
-
end
|
118
|
-
|
119
|
-
# Input
|
120
|
-
# The public key, pk: 32 bytes binary
|
121
|
-
# The message, m: UTF-8 / binary / agnostic
|
122
|
-
# A signature, sig: 64 bytes binary
|
123
|
-
# Output
|
124
|
-
# Boolean
|
125
|
-
def self.verify?(pk, m, sig)
|
126
|
-
bytestring!(pk, B) and string!(m) and bytestring!(sig, B * 2)
|
127
|
-
|
128
|
-
# BIP340: Let P = lift_x(int(pk))
|
129
|
-
p = lift_x(int(pk))
|
130
|
-
|
131
|
-
# BIP340: Let r = int(sig[0:32]) fail if r >= p
|
132
|
-
r = int(sig[0..B-1])
|
133
|
-
raise(BoundsError, "r >= p") if r >= P
|
134
|
-
|
135
|
-
# BIP340: Let s = int(sig[32:64]); fail if s >= n
|
136
|
-
s = int(sig[B..-1])
|
137
|
-
raise(BoundsError, "s >= n") if s >= N
|
138
|
-
|
139
|
-
# BIP340:
|
140
|
-
# Let e = int(hash[BIP0340/challenge](bytes(r) || bytes(P) || m)) mod n
|
141
|
-
e = bytes(r) + bytes(p) + m
|
142
|
-
e = int(tagged_hash('BIP0340/challenge', e)) % N
|
143
|
-
|
144
|
-
# BIP340: Let R = s . G - e . P
|
145
|
-
# BIP340: Fail if is_infinite(R)
|
146
|
-
# BIP340: Fail if not has_even_y(R)
|
147
|
-
# BIP340: Fail if x(R) != r
|
148
|
-
# BIP340: Return success iff no failure occurred before reaching this point
|
149
|
-
big_r = dot_group(s) + p.multiply_by_scalar(e).negate
|
150
|
-
!big_r.infinity? and big_r.y.even? and big_r.x == r
|
151
|
-
end
|
152
|
-
|
153
|
-
# BIP340: The function lift_x(x), where x is a 256-bit unsigned integer,
|
154
|
-
# returns the point P for which x(P) = x and has_even_y(P),
|
155
|
-
# or fails if x is greater than p-1 or no such point exists.
|
156
|
-
# Input
|
157
|
-
# A large integer, x
|
158
|
-
# Output
|
159
|
-
# ECDSA::Point
|
160
|
-
def self.lift_x(x)
|
161
|
-
integer!(x)
|
162
|
-
|
163
|
-
# BIP340: Fail if x >= p
|
164
|
-
raise(BoundsError, "x") if x >= P or x <= 0
|
165
|
-
|
166
|
-
# BIP340: Let c = x^3 + 7 mod p
|
167
|
-
c = (x.pow(3, P) + 7) % P
|
168
|
-
|
169
|
-
# BIP340: Let y = c ^ ((p + 1) / 4) mod p
|
170
|
-
y = c.pow((P + 1) / 4, P) # use pow to avoid Bignum overflow
|
171
|
-
|
172
|
-
# BIP340: Fail if c != y^2 mod p
|
173
|
-
raise(SanityCheck, "c != y^2 mod p") if c != y.pow(2, P)
|
174
|
-
|
175
|
-
# BIP340: Return the unique point P such that:
|
176
|
-
# x(P) = x and y(P) = y if y mod 2 = 0
|
177
|
-
# y(P) = p - y otherwise
|
178
|
-
GROUP.new_point [x, y.even? ? y : P - y]
|
179
|
-
end
|
180
|
-
|
181
|
-
# Input
|
182
|
-
# The secret key, sk: 32 bytes binary
|
183
|
-
# Output
|
184
|
-
# 32 bytes binary (represents P.x for point P on the curve)
|
185
|
-
def self.pubkey(sk)
|
186
|
-
bytestring!(sk, B)
|
187
|
-
|
188
|
-
# BIP340: Let d' = int(sk)
|
189
|
-
# BIP340: Fail if d' = 0 or d' >= n
|
190
|
-
# BIP340: Return bytes(d' . G)
|
191
|
-
d0 = int(sk)
|
192
|
-
raise(BoundsError, "d0") if !d0.positive? or d0 >= N
|
193
|
-
bytes(dot_group(d0))
|
194
|
-
end
|
195
|
-
|
196
|
-
# generate a new keypair based on random data
|
197
|
-
def self.keypair
|
198
|
-
sk = Random.bytes(B)
|
199
|
-
[sk, pubkey(sk)]
|
200
|
-
end
|
201
|
-
|
202
|
-
# as above, but using SecureRandom
|
203
|
-
def self.secure_keypair
|
204
|
-
sk = SecureRandom.bytes(B)
|
205
|
-
[sk, pubkey(sk)]
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
if __FILE__ == $0
|
210
|
-
msg = 'hello world'
|
211
|
-
sk, pk = SchnorrSig.keypair
|
212
|
-
puts "Message: #{msg}"
|
213
|
-
puts "Secret key: #{SchnorrSig.bin2hex(sk)}"
|
214
|
-
puts "Public key: #{SchnorrSig.bin2hex(pk)}"
|
215
|
-
|
216
|
-
sig = SchnorrSig.sign(sk, msg)
|
217
|
-
puts
|
218
|
-
puts "Verified signature: #{SchnorrSig.bin2hex(sig)}"
|
219
|
-
puts "Encoding: #{sig.encoding}"
|
220
|
-
puts "Length: #{sig.length}"
|
1
|
+
if ENV['SCHNORR_SIG']&.downcase == 'fast'
|
2
|
+
begin
|
3
|
+
require 'schnorr_sig/fast'
|
4
|
+
rescue LoadError
|
5
|
+
warn "LoadError: schnorr_sig/fast cannot be loaded"
|
6
|
+
require 'schnorr_sig/pure'
|
7
|
+
end
|
8
|
+
else
|
9
|
+
require 'schnorr_sig/pure'
|
221
10
|
end
|
data/test/vectors.rb
CHANGED
data/test/vectors_extra.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: schnorr_sig
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.2.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rick Hull
|
@@ -35,6 +35,7 @@ files:
|
|
35
35
|
- VERSION
|
36
36
|
- lib/schnorr_sig.rb
|
37
37
|
- lib/schnorr_sig/fast.rb
|
38
|
+
- lib/schnorr_sig/pure.rb
|
38
39
|
- lib/schnorr_sig/util.rb
|
39
40
|
- schnorr_sig.gemspec
|
40
41
|
- test/vectors.rb
|