Skip to content

Commit db3523d

Browse files
committed
Merge pull request bitcoinjs#418 from bitcoinjs/ecdsatypes
Stricter typing in ECDSA
2 parents 97c4de9 + 2ffa041 commit db3523d

File tree

3 files changed

+59
-61
lines changed

3 files changed

+59
-61
lines changed

src/ecdsa.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ function deterministicGenerateK (curve, hash, d, checkSig) {
7575
}
7676

7777
function sign (curve, hash, d) {
78+
typeForce('Curve', curve)
79+
typeForce('Buffer', hash)
80+
typeForce('BigInteger', d)
81+
7882
var e = BigInteger.fromBuffer(hash)
7983
var n = curve.n
8084
var G = curve.G
@@ -105,6 +109,11 @@ function sign (curve, hash, d) {
105109
}
106110

107111
function verify (curve, hash, signature, Q) {
112+
typeForce('Curve', curve)
113+
typeForce('Buffer', hash)
114+
typeForce('ECSignature', signature)
115+
typeForce('Point', Q)
116+
108117
var n = curve.n
109118
var G = curve.G
110119

@@ -153,6 +162,10 @@ function verify (curve, hash, signature, Q) {
153162
* http://www.secg.org/download/aid-780/sec1-v2.pdf
154163
*/
155164
function recoverPubKey (curve, e, signature, i) {
165+
typeForce('Curve', curve)
166+
typeForce('BigInteger', e)
167+
typeForce('ECSignature', signature)
168+
typeForce('Number', i)
156169
assert.strictEqual(i & 3, i, 'Recovery param is more than two bits')
157170

158171
var n = curve.n
@@ -206,6 +219,11 @@ function recoverPubKey (curve, e, signature, i) {
206219
* that resulted in a successful pubkey recovery.
207220
*/
208221
function calcPubKeyRecoveryParam (curve, e, signature, Q) {
222+
typeForce('Curve', curve)
223+
typeForce('BigInteger', e)
224+
typeForce('ECSignature', signature)
225+
typeForce('Point', Q)
226+
209227
for (var i = 0; i < 4; i++) {
210228
var Qprime = recoverPubKey(curve, e, signature, i)
211229

test/ecdsa.js

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,7 @@ describe('ecdsa', function () {
8989
it('recovers the pubKey for ' + f.d, function () {
9090
var d = BigInteger.fromHex(f.d)
9191
var Q = curve.G.multiply(d)
92-
var signature = {
93-
r: new BigInteger(f.signature.r),
94-
s: new BigInteger(f.signature.s)
95-
}
92+
var signature = ECSignature.fromDER(new Buffer(f.signature, 'hex'))
9693
var h1 = crypto.sha256(f.message)
9794
var e = BigInteger.fromBuffer(h1)
9895
var Qprime = ecdsa.recoverPubKey(curve, e, signature, f.i)
@@ -125,9 +122,9 @@ describe('ecdsa', function () {
125122
})
126123

127124
fixtures.invalid.recoverPubKey.forEach(function (f) {
128-
it('throws on ' + f.description, function () {
125+
it('throws on ' + f.description + ' (' + f.exception + ')', function () {
129126
var e = BigInteger.fromHex(f.e)
130-
var signature = new ECSignature(new BigInteger(f.signature.r), new BigInteger(f.signature.s))
127+
var signature = new ECSignature(new BigInteger(f.signatureRaw.r, 16), new BigInteger(f.signatureRaw.s, 16))
131128

132129
assert.throws(function () {
133130
ecdsa.recoverPubKey(curve, e, signature, f.i)
@@ -141,10 +138,9 @@ describe('ecdsa', function () {
141138
it('produces a deterministic signature for "' + f.message + '"', function () {
142139
var d = BigInteger.fromHex(f.d)
143140
var hash = crypto.sha256(f.message)
144-
var signature = ecdsa.sign(curve, hash, d)
141+
var signature = ecdsa.sign(curve, hash, d).toDER()
145142

146-
assert.strictEqual(signature.r.toString(), f.signature.r)
147-
assert.strictEqual(signature.s.toString(), f.signature.s)
143+
assert.strictEqual(signature.toString('hex'), f.signature)
148144
})
149145
})
150146

@@ -163,7 +159,7 @@ describe('ecdsa', function () {
163159
it('verifies a valid signature for "' + f.message + '"', function () {
164160
var d = BigInteger.fromHex(f.d)
165161
var H = crypto.sha256(f.message)
166-
var signature = new ECSignature(new BigInteger(f.signature.r), new BigInteger(f.signature.s))
162+
var signature = ECSignature.fromDER(new Buffer(f.signature, 'hex'))
167163
var Q = curve.G.multiply(d)
168164

169165
assert(ecdsa.verify(curve, H, signature, Q))
@@ -174,7 +170,15 @@ describe('ecdsa', function () {
174170
it('fails to verify with ' + f.description, function () {
175171
var H = crypto.sha256(f.message)
176172
var d = BigInteger.fromHex(f.d)
177-
var signature = new ECSignature(new BigInteger(f.signature.r), new BigInteger(f.signature.s))
173+
174+
var signature
175+
if (f.signature) {
176+
signature = ECSignature.fromDER(new Buffer(f.signature, 'hex'))
177+
178+
} else if (f.signatureRaw) {
179+
signature = new ECSignature(new BigInteger(f.signatureRaw.r, 16), new BigInteger(f.signatureRaw.s, 16))
180+
}
181+
178182
var Q = curve.G.multiply(d)
179183

180184
assert.strictEqual(ecdsa.verify(curve, H, signature, Q), false)

test/fixtures/ecdsa.json

Lines changed: 26 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -6,70 +6,49 @@
66
"k": "ec633bd56a5774a0940cb97e27a9e4e51dc94af737596a0c5cbb3d30332d92a5",
77
"message": "Everything should be made as simple as possible, but not simpler.",
88
"i": 0,
9-
"signature": {
10-
"r": "23362334225185207751494092901091441011938859014081160902781146257181456271561",
11-
"s": "50433721247292933944369538617440297985091596895097604618403996029256432099938"
12-
}
9+
"signature": "3044022033a69cd2065432a30f3d1ce4eb0d59b8ab58c74f27c41a7fdb5696ad4e6108c902206f807982866f785d3f6418d24163ddae117b7db4d5fdf0071de069fa54342262"
1310
},
1411
{
1512
"d": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
1613
"k": "9dc74cbfd383980fb4ae5d2680acddac9dac956dca65a28c80ac9c847c2374e4",
1714
"message": "Equations are more important to me, because politics is for the present, but an equation is something for eternity.",
1815
"i": 0,
19-
"signature": {
20-
"r": "38341707918488238920692284707283974715538935465589664377561695343399725051885",
21-
"s": "3180566392414476763164587487324397066658063772201694230600609996154610926757"
22-
}
16+
"signature": "3044022054c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed022007082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5"
2317
},
2418
{
2519
"d": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
2620
"k": "fd27071f01648ebbdd3e1cfbae48facc9fa97edc43bbbc9a7fdc28eae13296f5",
2721
"message": "Not only is the Universe stranger than we think, it is stranger than we can think.",
2822
"i": 0,
29-
"signature": {
30-
"r": "115464191557905790016094131873849783294273568009648050793030031933291767741904",
31-
"s": "50562520307781850052192542766631199590053690478900449960232079510155113443971"
32-
}
23+
"signature": "3045022100ff466a9f1b7b273e2f4c3ffe032eb2e814121ed18ef84665d0f515360dab3dd002206fc95f5132e5ecfdc8e5e6e616cc77151455d46ed48f5589b7db7771a332b283"
3324
},
3425
{
3526
"d": "0000000000000000000000000000000000000000000000000000000000000001",
3627
"k": "f0cd2ba5fc7c183de589f6416220a36775a146740798756d8d949f7166dcc87f",
3728
"message": "How wonderful that we have met with a paradox. Now we have some hope of making progress.",
3829
"i": 1,
39-
"signature": {
40-
"r": "87230998027579607140680851455601772643840468630989315269459846730712163783123",
41-
"s": "53231320085894623106179381504478252331065330583563809963303318469380290929875"
42-
}
30+
"signature": "3045022100c0dafec8251f1d5010289d210232220b03202cba34ec11fec58b3e93a85b91d3022075afdc06b7d6322a590955bf264e7aaa155847f614d80078a90292fe205064d3"
4331
},
4432
{
4533
"d": "69ec59eaa1f4f2e36b639716b7c30ca86d9a5375c7b38d8918bd9c0ebc80ba64",
4634
"k": "6bb4a594ad57c1aa22dbe991a9d8501daf4688bf50a4892ef21bd7c711afda97",
4735
"message": "Computer science is no more about computers than astronomy is about telescopes.",
4836
"i": 0,
49-
"signature": {
50-
"r": "51348483531757779992459563033975330355971795607481991320287437101831125115997",
51-
"s": "6277080015686056199074771961940657638578000617958603212944619747099038735862"
52-
}
37+
"signature": "304402207186363571d65e084e7f02b0b77c3ec44fb1b257dee26274c38c928986fea45d02200de0b38e06807e46bda1f1e293f4f6323e854c86d58abdd00c46c16441085df6"
5338
},
5439
{
5540
"d": "00000000000000000000000000007246174ab1e92e9149c6e446fe194d072637",
5641
"k": "097b5c8ee22c3ea78a4d3635e0ff6fe85a1eb92ce317ded90b9e71aab2b861cb",
5742
"message": "...if you aren't, at any given time, scandalized by code you wrote five or even three years ago, you're not learning anywhere near enough",
5843
"i": 1,
59-
"signature": {
60-
"r": "113979859486826658566290715281614250298918272782414232881639314569529560769671",
61-
"s": "6517071009538626957379450615706485096874328019806177698938278220732027419959"
62-
}
44+
"signature": "3045022100fbfe5076a15860ba8ed00e75e9bd22e05d230f02a936b653eb55b61c99dda48702200e68880ebb0050fe4312b1b1eb0899e1b82da89baa5b895f612619edf34cbd37"
6345
},
6446
{
6547
"d": "000000000000000000000000000000000000000000056916d0f9b31dc9b637f3",
6648
"k": "19355c36c8cbcdfb2382e23b194b79f8c97bf650040fc7728dfbf6b39a97c25b",
6749
"message": "The question of whether computers can think is like the question of whether submarines can swim.",
6850
"i": 1,
69-
"signature": {
70-
"r": "93122007060065279508564838030979550535085999589142852106617159184757394422777",
71-
"s": "3078539468410661027472930027406594684630312677495124015420811882501887769839"
72-
}
51+
"signature": "3045022100cde1302d83f8dd835d89aef803c74a119f561fbaef3eb9129e45f30de86abbf9022006ce643f5049ee1f27890467b77a6a8e11ec4661cc38cd8badf90115fbd03cef"
7352
}
7453
],
7554
"rfc6979": [
@@ -151,7 +130,7 @@
151130
"description": "Invalid r value (< 0)",
152131
"exception": "Invalid r value",
153132
"e": "01",
154-
"signature": {
133+
"signatureRaw": {
155134
"r": "-01",
156135
"s": "02"
157136
},
@@ -161,7 +140,7 @@
161140
"description": "Invalid r value (== 0)",
162141
"exception": "Invalid r value",
163142
"e": "01",
164-
"signature": {
143+
"signatureRaw": {
165144
"r": "00",
166145
"s": "02"
167146
},
@@ -171,7 +150,7 @@
171150
"description": "Invalid s value (< 0)",
172151
"exception": "Invalid s value",
173152
"e": "01",
174-
"signature": {
153+
"signatureRaw": {
175154
"r": "02",
176155
"s": "-01"
177156
},
@@ -181,7 +160,7 @@
181160
"description": "Invalid s value (== 0)",
182161
"exception": "Invalid s value",
183162
"e": "01",
184-
"signature": {
163+
"signatureRaw": {
185164
"r": "02",
186165
"s": "00"
187166
},
@@ -191,8 +170,8 @@
191170
"description": "Invalid r value (nR is infinity)",
192171
"exception": "nR is not a valid curve point",
193172
"e": "01",
194-
"signature": {
195-
"r": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141",
173+
"signatureRaw": {
174+
"r": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
196175
"s": "01"
197176
},
198177
"i": 0
@@ -201,8 +180,8 @@
201180
"description": "Invalid curve point",
202181
"exception": "Point is not on the curve",
203182
"e": "01",
204-
"signature": {
205-
"r": "99999999999999999999999999999999999999",
183+
"signatureRaw": {
184+
"r": "4b3b4ca85a86c47a098a223fffffffff",
206185
"s": "01"
207186
},
208187
"i": 0
@@ -211,7 +190,7 @@
211190
"description": "Invalid i value (> 3)",
212191
"exception": "Recovery param is more than two bits",
213192
"e": "01",
214-
"signature": {
193+
"signatureRaw": {
215194
"r": "00",
216195
"s": "02"
217196
},
@@ -223,16 +202,13 @@
223202
"description": "The wrong signature",
224203
"d": "01",
225204
"message": "foo",
226-
"signature": {
227-
"r": "38341707918488238920692284707283974715538935465589664377561695343399725051885",
228-
"s": "3180566392414476763164587487324397066658063772201694230600609996154610926757"
229-
}
205+
"signature": "3044022054c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed022007082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5"
230206
},
231207
{
232208
"description": "Invalid r value (< 0)",
233209
"d": "01",
234210
"message": "foo",
235-
"signature": {
211+
"signatureRaw": {
236212
"r": "-01",
237213
"s": "02"
238214
}
@@ -241,7 +217,7 @@
241217
"description": "Invalid r value (== 0)",
242218
"d": "01",
243219
"message": "foo",
244-
"signature": {
220+
"signatureRaw": {
245221
"r": "00",
246222
"s": "02"
247223
}
@@ -250,7 +226,7 @@
250226
"description": "Invalid r value (>= n)",
251227
"d": "01",
252228
"message": "foo",
253-
"signature": {
229+
"signatureRaw": {
254230
"r": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141",
255231
"s": "02"
256232
}
@@ -259,7 +235,7 @@
259235
"description": "Invalid s value (< 0)",
260236
"d": "01",
261237
"message": "foo",
262-
"signature": {
238+
"signatureRaw": {
263239
"r": "02",
264240
"s": "-01"
265241
}
@@ -268,7 +244,7 @@
268244
"description": "Invalid s value (== 0)",
269245
"d": "01",
270246
"message": "foo",
271-
"signature": {
247+
"signatureRaw": {
272248
"r": "02",
273249
"s": "00"
274250
}
@@ -277,7 +253,7 @@
277253
"description": "Invalid s value (>= n)",
278254
"d": "01",
279255
"message": "foo",
280-
"signature": {
256+
"signatureRaw": {
281257
"r": "02",
282258
"s": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"
283259
}
@@ -286,9 +262,9 @@
286262
"description": "Invalid r, s values (r = s = -n)",
287263
"d": "01",
288264
"message": "foo",
289-
"signature": {
290-
"r": "-115792089237316195423570985008687907852837564279074904382605163141518161494337",
291-
"s": "-115792089237316195423570985008687907852837564279074904382605163141518161494337"
265+
"signatureRaw": {
266+
"r": "-fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141",
267+
"s": "-fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"
292268
}
293269
}
294270
]

0 commit comments

Comments
 (0)