Skip to content
This repository was archived by the owner on Jun 3, 2020. It is now read-only.

Commit e9778ae

Browse files
committed
ecdsa: fixes edge case presented in bitcoinjs#336
1 parent 4c61380 commit e9778ae

File tree

3 files changed

+29
-13
lines changed

3 files changed

+29
-13
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
"bs58check": "1.0.3",
5353
"crypto-browserify": "^3.2.6",
5454
"ecurve": "1.0.0",
55-
"typeforce": "0.0.2"
55+
"typeforce": "0.1.0"
5656
},
5757
"devDependencies": {
5858
"async": "^0.9.0",

src/ecdsa.js

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ var ZERO = new Buffer([0])
99
var ONE = new Buffer([1])
1010

1111
// https://tools.ietf.org/html/rfc6979#section-3.2
12-
function deterministicGenerateK(curve, hash, d) {
12+
function deterministicGenerateK(curve, hash, d, checkSig) {
1313
typeForce('Buffer', hash)
1414
typeForce('BigInteger', d)
15+
typeForce('Function', checkSig)
1516

1617
// sanity check
1718
assert.equal(hash.length, 32, 'Hash must be 256 bit')
@@ -55,34 +56,47 @@ function deterministicGenerateK(curve, hash, d) {
5556

5657
var T = BigInteger.fromBuffer(v)
5758

58-
// Step H3, repeat until T is within the interval [1, n - 1]
59-
while ((T.signum() <= 0) || (T.compareTo(curve.n) >= 0)) {
59+
// Step H3, repeat until T is within the interval [1, n - 1] and is suitable for ECDSA
60+
while ((T.signum() <= 0) || (T.compareTo(curve.n) >= 0) || !checkSig(T)) {
6061
k = crypto.createHmac('sha256', k)
6162
.update(v)
6263
.update(ZERO)
6364
.digest()
6465

6566
v = crypto.createHmac('sha256', k).update(v).digest()
6667

68+
// Step H1/H2a, again, ignored as tlen === qlen (256 bit)
69+
// Step H2b again
70+
v = crypto.createHmac('sha256', k).update(v).digest()
6771
T = BigInteger.fromBuffer(v)
6872
}
6973

7074
return T
7175
}
7276

7377
function sign(curve, hash, d) {
74-
var k = deterministicGenerateK(curve, hash, d)
78+
var r, s
7579

80+
var e = BigInteger.fromBuffer(hash)
7681
var n = curve.n
7782
var G = curve.G
78-
var Q = G.multiply(k)
79-
var e = BigInteger.fromBuffer(hash)
8083

81-
var r = Q.affineX.mod(n)
82-
assert.notEqual(r.signum(), 0, 'Invalid R value')
84+
deterministicGenerateK(curve, hash, d, function(k) {
85+
var Q = G.multiply(k)
86+
87+
if (curve.isInfinity(Q))
88+
return false
89+
90+
r = Q.affineX.mod(n)
91+
if (r.signum() === 0)
92+
return false
93+
94+
s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n)
95+
if (s.signum() === 0)
96+
return false
8397

84-
var s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n)
85-
assert.notEqual(s.signum(), 0, 'Invalid S value')
98+
return true
99+
})
86100

87101
var N_OVER_TWO = n.shiftRight(1)
88102

test/ecdsa.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@ var fixtures = require('./fixtures/ecdsa.json')
1515

1616
describe('ecdsa', function() {
1717
describe('deterministicGenerateK', function() {
18+
function checkSig() { return true }
19+
1820
fixtures.valid.forEach(function(f) {
1921
it('for \"' + f.message + '\"', function() {
2022
var d = BigInteger.fromHex(f.d)
2123
var h1 = crypto.sha256(f.message)
2224

23-
var k = ecdsa.deterministicGenerateK(curve, h1, d)
25+
var k = ecdsa.deterministicGenerateK(curve, h1, d, checkSig)
2426
assert.equal(k.toHex(), f.k)
2527
})
2628
})
@@ -35,7 +37,7 @@ describe('ecdsa', function() {
3537
var d = new BigInteger('1')
3638
var h1 = new Buffer(32)
3739

38-
var k = ecdsa.deterministicGenerateK(curve, h1, d)
40+
var k = ecdsa.deterministicGenerateK(curve, h1, d, checkSig)
3941

4042
assert.equal(k.toString(), '42')
4143
}))

0 commit comments

Comments
 (0)