From 776656df8be551f8454c64d137d1ca36e287363b Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Sat, 21 Jun 2014 22:25:09 +1000 Subject: [PATCH] ecdsa: adhere strictly to RFC6979 The previous impl. was in breach of the following section: > Please note that when k is generated from T, the result of bits2int is > compared to q, not reduced modulo q. If the value is not between 1 and > q-1, the process loops. > Performing a simple modular reduction would induce biases that would be > detrimental to signature security. --- src/ecdsa.js | 33 ++++++++++++++++++++++++++------- test/ecdsa.js | 2 +- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/ecdsa.js b/src/ecdsa.js index 60fe624..5a0ee2c 100644 --- a/src/ecdsa.js +++ b/src/ecdsa.js @@ -5,6 +5,7 @@ var BigInteger = require('bigi') var ECSignature = require('./ecsignature') var Point = require('ecurve').Point +// https://tools.ietf.org/html/rfc6979#section-3.2 function deterministicGenerateK(curve, hash, d) { assert(Buffer.isBuffer(hash), 'Hash must be a Buffer, not ' + hash) assert.equal(hash.length, 32, 'Hash must be 256 bit') @@ -13,22 +14,40 @@ function deterministicGenerateK(curve, hash, d) { var x = d.toBuffer(32) var k = new Buffer(32) var v = new Buffer(32) - k.fill(0) + + // Step B v.fill(1) + // Step C + k.fill(0) + + // Step D k = crypto.HmacSHA256(Buffer.concat([v, new Buffer([0]), x, hash]), k) + + // Step E v = crypto.HmacSHA256(v, k) + // Step F k = crypto.HmacSHA256(Buffer.concat([v, new Buffer([1]), x, hash]), k) - v = crypto.HmacSHA256(v, k) + + // Step G v = crypto.HmacSHA256(v, k) - var n = curve.n - var kB = BigInteger.fromBuffer(v).mod(n) - assert(kB.compareTo(BigInteger.ONE) > 0, 'Invalid k value') - assert(kB.compareTo(n) < 0, 'Invalid k value') + // Step H1/H2a, ignored as tlen === qlen (256 bit) + // Step H2b + v = crypto.HmacSHA256(v, k) - return kB + var T = BigInteger.fromBuffer(v) + + // Step H3, repeat until T is within the interval [0, n - 1] + while ((T.signum() <= 0) || (T.compareTo(curve.n) >= 0)) { + k = crypto.HmacSHA256(Buffer.concat([v, new Buffer([0])]), k) + v = crypto.HmacSHA256(v, k) + + T = BigInteger.fromBuffer(v) + } + + return T } function sign(curve, hash, d) { diff --git a/test/ecdsa.js b/test/ecdsa.js index f025e5e..3c2f2e5 100644 --- a/test/ecdsa.js +++ b/test/ecdsa.js @@ -15,7 +15,7 @@ var fixtures = require('./fixtures/ecdsa.json') describe('ecdsa', function() { describe('deterministicGenerateK', function() { fixtures.valid.forEach(function(f) { - it('determines k for \"' + f.message + '\"', function() { + it('for \"' + f.message + '\"', function() { var d = BigInteger.fromHex(f.d) var h1 = crypto.sha256(f.message)