Merge pull request #418 from bitcoinjs/ecdsatypes

Stricter typing in ECDSA
This commit is contained in:
Wei Lu 2015-07-05 16:42:44 +08:00
commit db3523d2c9
3 changed files with 59 additions and 61 deletions

View file

@ -75,6 +75,10 @@ function deterministicGenerateK (curve, hash, d, checkSig) {
} }
function sign (curve, hash, d) { function sign (curve, hash, d) {
typeForce('Curve', curve)
typeForce('Buffer', hash)
typeForce('BigInteger', d)
var e = BigInteger.fromBuffer(hash) var e = BigInteger.fromBuffer(hash)
var n = curve.n var n = curve.n
var G = curve.G var G = curve.G
@ -105,6 +109,11 @@ function sign (curve, hash, d) {
} }
function verify (curve, hash, signature, Q) { function verify (curve, hash, signature, Q) {
typeForce('Curve', curve)
typeForce('Buffer', hash)
typeForce('ECSignature', signature)
typeForce('Point', Q)
var n = curve.n var n = curve.n
var G = curve.G var G = curve.G
@ -153,6 +162,10 @@ function verify (curve, hash, signature, Q) {
* http://www.secg.org/download/aid-780/sec1-v2.pdf * http://www.secg.org/download/aid-780/sec1-v2.pdf
*/ */
function recoverPubKey (curve, e, signature, i) { function recoverPubKey (curve, e, signature, i) {
typeForce('Curve', curve)
typeForce('BigInteger', e)
typeForce('ECSignature', signature)
typeForce('Number', i)
assert.strictEqual(i & 3, i, 'Recovery param is more than two bits') assert.strictEqual(i & 3, i, 'Recovery param is more than two bits')
var n = curve.n var n = curve.n
@ -206,6 +219,11 @@ function recoverPubKey (curve, e, signature, i) {
* that resulted in a successful pubkey recovery. * that resulted in a successful pubkey recovery.
*/ */
function calcPubKeyRecoveryParam (curve, e, signature, Q) { function calcPubKeyRecoveryParam (curve, e, signature, Q) {
typeForce('Curve', curve)
typeForce('BigInteger', e)
typeForce('ECSignature', signature)
typeForce('Point', Q)
for (var i = 0; i < 4; i++) { for (var i = 0; i < 4; i++) {
var Qprime = recoverPubKey(curve, e, signature, i) var Qprime = recoverPubKey(curve, e, signature, i)

View file

@ -89,10 +89,7 @@ describe('ecdsa', function () {
it('recovers the pubKey for ' + f.d, function () { it('recovers the pubKey for ' + f.d, function () {
var d = BigInteger.fromHex(f.d) var d = BigInteger.fromHex(f.d)
var Q = curve.G.multiply(d) var Q = curve.G.multiply(d)
var signature = { var signature = ECSignature.fromDER(new Buffer(f.signature, 'hex'))
r: new BigInteger(f.signature.r),
s: new BigInteger(f.signature.s)
}
var h1 = crypto.sha256(f.message) var h1 = crypto.sha256(f.message)
var e = BigInteger.fromBuffer(h1) var e = BigInteger.fromBuffer(h1)
var Qprime = ecdsa.recoverPubKey(curve, e, signature, f.i) var Qprime = ecdsa.recoverPubKey(curve, e, signature, f.i)
@ -125,9 +122,9 @@ describe('ecdsa', function () {
}) })
fixtures.invalid.recoverPubKey.forEach(function (f) { fixtures.invalid.recoverPubKey.forEach(function (f) {
it('throws on ' + f.description, function () { it('throws on ' + f.description + ' (' + f.exception + ')', function () {
var e = BigInteger.fromHex(f.e) var e = BigInteger.fromHex(f.e)
var signature = new ECSignature(new BigInteger(f.signature.r), new BigInteger(f.signature.s)) var signature = new ECSignature(new BigInteger(f.signatureRaw.r, 16), new BigInteger(f.signatureRaw.s, 16))
assert.throws(function () { assert.throws(function () {
ecdsa.recoverPubKey(curve, e, signature, f.i) ecdsa.recoverPubKey(curve, e, signature, f.i)
@ -141,10 +138,9 @@ describe('ecdsa', function () {
it('produces a deterministic signature for "' + f.message + '"', function () { it('produces a deterministic signature for "' + f.message + '"', function () {
var d = BigInteger.fromHex(f.d) var d = BigInteger.fromHex(f.d)
var hash = crypto.sha256(f.message) var hash = crypto.sha256(f.message)
var signature = ecdsa.sign(curve, hash, d) var signature = ecdsa.sign(curve, hash, d).toDER()
assert.strictEqual(signature.r.toString(), f.signature.r) assert.strictEqual(signature.toString('hex'), f.signature)
assert.strictEqual(signature.s.toString(), f.signature.s)
}) })
}) })
@ -163,7 +159,7 @@ describe('ecdsa', function () {
it('verifies a valid signature for "' + f.message + '"', function () { it('verifies a valid signature for "' + f.message + '"', function () {
var d = BigInteger.fromHex(f.d) var d = BigInteger.fromHex(f.d)
var H = crypto.sha256(f.message) var H = crypto.sha256(f.message)
var signature = new ECSignature(new BigInteger(f.signature.r), new BigInteger(f.signature.s)) var signature = ECSignature.fromDER(new Buffer(f.signature, 'hex'))
var Q = curve.G.multiply(d) var Q = curve.G.multiply(d)
assert(ecdsa.verify(curve, H, signature, Q)) assert(ecdsa.verify(curve, H, signature, Q))
@ -174,7 +170,15 @@ describe('ecdsa', function () {
it('fails to verify with ' + f.description, function () { it('fails to verify with ' + f.description, function () {
var H = crypto.sha256(f.message) var H = crypto.sha256(f.message)
var d = BigInteger.fromHex(f.d) var d = BigInteger.fromHex(f.d)
var signature = new ECSignature(new BigInteger(f.signature.r), new BigInteger(f.signature.s))
var signature
if (f.signature) {
signature = ECSignature.fromDER(new Buffer(f.signature, 'hex'))
} else if (f.signatureRaw) {
signature = new ECSignature(new BigInteger(f.signatureRaw.r, 16), new BigInteger(f.signatureRaw.s, 16))
}
var Q = curve.G.multiply(d) var Q = curve.G.multiply(d)
assert.strictEqual(ecdsa.verify(curve, H, signature, Q), false) assert.strictEqual(ecdsa.verify(curve, H, signature, Q), false)

View file

@ -6,70 +6,49 @@
"k": "ec633bd56a5774a0940cb97e27a9e4e51dc94af737596a0c5cbb3d30332d92a5", "k": "ec633bd56a5774a0940cb97e27a9e4e51dc94af737596a0c5cbb3d30332d92a5",
"message": "Everything should be made as simple as possible, but not simpler.", "message": "Everything should be made as simple as possible, but not simpler.",
"i": 0, "i": 0,
"signature": { "signature": "3044022033a69cd2065432a30f3d1ce4eb0d59b8ab58c74f27c41a7fdb5696ad4e6108c902206f807982866f785d3f6418d24163ddae117b7db4d5fdf0071de069fa54342262"
"r": "23362334225185207751494092901091441011938859014081160902781146257181456271561",
"s": "50433721247292933944369538617440297985091596895097604618403996029256432099938"
}
}, },
{ {
"d": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", "d": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
"k": "9dc74cbfd383980fb4ae5d2680acddac9dac956dca65a28c80ac9c847c2374e4", "k": "9dc74cbfd383980fb4ae5d2680acddac9dac956dca65a28c80ac9c847c2374e4",
"message": "Equations are more important to me, because politics is for the present, but an equation is something for eternity.", "message": "Equations are more important to me, because politics is for the present, but an equation is something for eternity.",
"i": 0, "i": 0,
"signature": { "signature": "3044022054c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed022007082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5"
"r": "38341707918488238920692284707283974715538935465589664377561695343399725051885",
"s": "3180566392414476763164587487324397066658063772201694230600609996154610926757"
}
}, },
{ {
"d": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", "d": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
"k": "fd27071f01648ebbdd3e1cfbae48facc9fa97edc43bbbc9a7fdc28eae13296f5", "k": "fd27071f01648ebbdd3e1cfbae48facc9fa97edc43bbbc9a7fdc28eae13296f5",
"message": "Not only is the Universe stranger than we think, it is stranger than we can think.", "message": "Not only is the Universe stranger than we think, it is stranger than we can think.",
"i": 0, "i": 0,
"signature": { "signature": "3045022100ff466a9f1b7b273e2f4c3ffe032eb2e814121ed18ef84665d0f515360dab3dd002206fc95f5132e5ecfdc8e5e6e616cc77151455d46ed48f5589b7db7771a332b283"
"r": "115464191557905790016094131873849783294273568009648050793030031933291767741904",
"s": "50562520307781850052192542766631199590053690478900449960232079510155113443971"
}
}, },
{ {
"d": "0000000000000000000000000000000000000000000000000000000000000001", "d": "0000000000000000000000000000000000000000000000000000000000000001",
"k": "f0cd2ba5fc7c183de589f6416220a36775a146740798756d8d949f7166dcc87f", "k": "f0cd2ba5fc7c183de589f6416220a36775a146740798756d8d949f7166dcc87f",
"message": "How wonderful that we have met with a paradox. Now we have some hope of making progress.", "message": "How wonderful that we have met with a paradox. Now we have some hope of making progress.",
"i": 1, "i": 1,
"signature": { "signature": "3045022100c0dafec8251f1d5010289d210232220b03202cba34ec11fec58b3e93a85b91d3022075afdc06b7d6322a590955bf264e7aaa155847f614d80078a90292fe205064d3"
"r": "87230998027579607140680851455601772643840468630989315269459846730712163783123",
"s": "53231320085894623106179381504478252331065330583563809963303318469380290929875"
}
}, },
{ {
"d": "69ec59eaa1f4f2e36b639716b7c30ca86d9a5375c7b38d8918bd9c0ebc80ba64", "d": "69ec59eaa1f4f2e36b639716b7c30ca86d9a5375c7b38d8918bd9c0ebc80ba64",
"k": "6bb4a594ad57c1aa22dbe991a9d8501daf4688bf50a4892ef21bd7c711afda97", "k": "6bb4a594ad57c1aa22dbe991a9d8501daf4688bf50a4892ef21bd7c711afda97",
"message": "Computer science is no more about computers than astronomy is about telescopes.", "message": "Computer science is no more about computers than astronomy is about telescopes.",
"i": 0, "i": 0,
"signature": { "signature": "304402207186363571d65e084e7f02b0b77c3ec44fb1b257dee26274c38c928986fea45d02200de0b38e06807e46bda1f1e293f4f6323e854c86d58abdd00c46c16441085df6"
"r": "51348483531757779992459563033975330355971795607481991320287437101831125115997",
"s": "6277080015686056199074771961940657638578000617958603212944619747099038735862"
}
}, },
{ {
"d": "00000000000000000000000000007246174ab1e92e9149c6e446fe194d072637", "d": "00000000000000000000000000007246174ab1e92e9149c6e446fe194d072637",
"k": "097b5c8ee22c3ea78a4d3635e0ff6fe85a1eb92ce317ded90b9e71aab2b861cb", "k": "097b5c8ee22c3ea78a4d3635e0ff6fe85a1eb92ce317ded90b9e71aab2b861cb",
"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", "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",
"i": 1, "i": 1,
"signature": { "signature": "3045022100fbfe5076a15860ba8ed00e75e9bd22e05d230f02a936b653eb55b61c99dda48702200e68880ebb0050fe4312b1b1eb0899e1b82da89baa5b895f612619edf34cbd37"
"r": "113979859486826658566290715281614250298918272782414232881639314569529560769671",
"s": "6517071009538626957379450615706485096874328019806177698938278220732027419959"
}
}, },
{ {
"d": "000000000000000000000000000000000000000000056916d0f9b31dc9b637f3", "d": "000000000000000000000000000000000000000000056916d0f9b31dc9b637f3",
"k": "19355c36c8cbcdfb2382e23b194b79f8c97bf650040fc7728dfbf6b39a97c25b", "k": "19355c36c8cbcdfb2382e23b194b79f8c97bf650040fc7728dfbf6b39a97c25b",
"message": "The question of whether computers can think is like the question of whether submarines can swim.", "message": "The question of whether computers can think is like the question of whether submarines can swim.",
"i": 1, "i": 1,
"signature": { "signature": "3045022100cde1302d83f8dd835d89aef803c74a119f561fbaef3eb9129e45f30de86abbf9022006ce643f5049ee1f27890467b77a6a8e11ec4661cc38cd8badf90115fbd03cef"
"r": "93122007060065279508564838030979550535085999589142852106617159184757394422777",
"s": "3078539468410661027472930027406594684630312677495124015420811882501887769839"
}
} }
], ],
"rfc6979": [ "rfc6979": [
@ -151,7 +130,7 @@
"description": "Invalid r value (< 0)", "description": "Invalid r value (< 0)",
"exception": "Invalid r value", "exception": "Invalid r value",
"e": "01", "e": "01",
"signature": { "signatureRaw": {
"r": "-01", "r": "-01",
"s": "02" "s": "02"
}, },
@ -161,7 +140,7 @@
"description": "Invalid r value (== 0)", "description": "Invalid r value (== 0)",
"exception": "Invalid r value", "exception": "Invalid r value",
"e": "01", "e": "01",
"signature": { "signatureRaw": {
"r": "00", "r": "00",
"s": "02" "s": "02"
}, },
@ -171,7 +150,7 @@
"description": "Invalid s value (< 0)", "description": "Invalid s value (< 0)",
"exception": "Invalid s value", "exception": "Invalid s value",
"e": "01", "e": "01",
"signature": { "signatureRaw": {
"r": "02", "r": "02",
"s": "-01" "s": "-01"
}, },
@ -181,7 +160,7 @@
"description": "Invalid s value (== 0)", "description": "Invalid s value (== 0)",
"exception": "Invalid s value", "exception": "Invalid s value",
"e": "01", "e": "01",
"signature": { "signatureRaw": {
"r": "02", "r": "02",
"s": "00" "s": "00"
}, },
@ -191,8 +170,8 @@
"description": "Invalid r value (nR is infinity)", "description": "Invalid r value (nR is infinity)",
"exception": "nR is not a valid curve point", "exception": "nR is not a valid curve point",
"e": "01", "e": "01",
"signature": { "signatureRaw": {
"r": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", "r": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
"s": "01" "s": "01"
}, },
"i": 0 "i": 0
@ -201,8 +180,8 @@
"description": "Invalid curve point", "description": "Invalid curve point",
"exception": "Point is not on the curve", "exception": "Point is not on the curve",
"e": "01", "e": "01",
"signature": { "signatureRaw": {
"r": "99999999999999999999999999999999999999", "r": "4b3b4ca85a86c47a098a223fffffffff",
"s": "01" "s": "01"
}, },
"i": 0 "i": 0
@ -211,7 +190,7 @@
"description": "Invalid i value (> 3)", "description": "Invalid i value (> 3)",
"exception": "Recovery param is more than two bits", "exception": "Recovery param is more than two bits",
"e": "01", "e": "01",
"signature": { "signatureRaw": {
"r": "00", "r": "00",
"s": "02" "s": "02"
}, },
@ -223,16 +202,13 @@
"description": "The wrong signature", "description": "The wrong signature",
"d": "01", "d": "01",
"message": "foo", "message": "foo",
"signature": { "signature": "3044022054c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed022007082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5"
"r": "38341707918488238920692284707283974715538935465589664377561695343399725051885",
"s": "3180566392414476763164587487324397066658063772201694230600609996154610926757"
}
}, },
{ {
"description": "Invalid r value (< 0)", "description": "Invalid r value (< 0)",
"d": "01", "d": "01",
"message": "foo", "message": "foo",
"signature": { "signatureRaw": {
"r": "-01", "r": "-01",
"s": "02" "s": "02"
} }
@ -241,7 +217,7 @@
"description": "Invalid r value (== 0)", "description": "Invalid r value (== 0)",
"d": "01", "d": "01",
"message": "foo", "message": "foo",
"signature": { "signatureRaw": {
"r": "00", "r": "00",
"s": "02" "s": "02"
} }
@ -250,7 +226,7 @@
"description": "Invalid r value (>= n)", "description": "Invalid r value (>= n)",
"d": "01", "d": "01",
"message": "foo", "message": "foo",
"signature": { "signatureRaw": {
"r": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", "r": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141",
"s": "02" "s": "02"
} }
@ -259,7 +235,7 @@
"description": "Invalid s value (< 0)", "description": "Invalid s value (< 0)",
"d": "01", "d": "01",
"message": "foo", "message": "foo",
"signature": { "signatureRaw": {
"r": "02", "r": "02",
"s": "-01" "s": "-01"
} }
@ -268,7 +244,7 @@
"description": "Invalid s value (== 0)", "description": "Invalid s value (== 0)",
"d": "01", "d": "01",
"message": "foo", "message": "foo",
"signature": { "signatureRaw": {
"r": "02", "r": "02",
"s": "00" "s": "00"
} }
@ -277,7 +253,7 @@
"description": "Invalid s value (>= n)", "description": "Invalid s value (>= n)",
"d": "01", "d": "01",
"message": "foo", "message": "foo",
"signature": { "signatureRaw": {
"r": "02", "r": "02",
"s": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141" "s": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"
} }
@ -286,9 +262,9 @@
"description": "Invalid r, s values (r = s = -n)", "description": "Invalid r, s values (r = s = -n)",
"d": "01", "d": "01",
"message": "foo", "message": "foo",
"signature": { "signatureRaw": {
"r": "-115792089237316195423570985008687907852837564279074904382605163141518161494337", "r": "-fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141",
"s": "-115792089237316195423570985008687907852837564279074904382605163141518161494337" "s": "-fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"
} }
} }
] ]