|
|
@ -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) |
|
|
|
|
|
|
|
// Step G
|
|
|
|
v = crypto.HmacSHA256(v, k) |
|
|
|
|
|
|
|
// Step H1/H2a, ignored as tlen === qlen (256 bit)
|
|
|
|
// Step H2b
|
|
|
|
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') |
|
|
|
var T = BigInteger.fromBuffer(v) |
|
|
|
|
|
|
|
return kB |
|
|
|
// Step H3, repeat until T is within the interval [1, 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) { |
|
|
@ -97,8 +116,7 @@ function recoverPubKey(curve, e, signature, i) { |
|
|
|
var s = signature.s |
|
|
|
|
|
|
|
// A set LSB signifies that the y-coordinate is odd
|
|
|
|
// By reduction, the y-coordinate is even if it is clear
|
|
|
|
var isYEven = !(i & 1) |
|
|
|
var isYOdd = i & 1 |
|
|
|
|
|
|
|
// The more significant bit specifies whether we should use the
|
|
|
|
// first or second candidate key.
|
|
|
@ -106,28 +124,12 @@ function recoverPubKey(curve, e, signature, i) { |
|
|
|
|
|
|
|
var n = curve.n |
|
|
|
var G = curve.G |
|
|
|
var p = curve.p |
|
|
|
var a = curve.a |
|
|
|
var b = curve.b |
|
|
|
|
|
|
|
// We precalculate (p + 1) / 4 where p is the field order
|
|
|
|
if (!curve.P_OVER_FOUR) { |
|
|
|
curve.P_OVER_FOUR = p.add(BigInteger.ONE).shiftRight(2) |
|
|
|
} |
|
|
|
|
|
|
|
// 1.1 Let x = r + jn
|
|
|
|
var x = isSecondKey ? r.add(n) : r |
|
|
|
|
|
|
|
// 1.2, 1.3 Convert x to a point R using routine specified in Section 2.3.4
|
|
|
|
var alpha = x.pow(3).add(a.multiply(x)).add(b).mod(p) |
|
|
|
var beta = alpha.modPow(curve.P_OVER_FOUR, p) |
|
|
|
|
|
|
|
// If beta is even, but y isn't, or vice versa, then convert it,
|
|
|
|
// otherwise we're done and y == beta.
|
|
|
|
var y = (beta.isEven() ^ isYEven) ? p.subtract(beta) : beta |
|
|
|
var R = curve.pointFromX(isYOdd, x) |
|
|
|
|
|
|
|
// 1.4 Check that nR is at infinity
|
|
|
|
var R = Point.fromAffine(curve, x, y) |
|
|
|
var nR = R.multiply(n) |
|
|
|
assert(curve.isInfinity(nR), 'nR is not a valid curve point') |
|
|
|
|
|
|
|