ecdsa: remove curve parameter

This commit is contained in:
Daniel Cousens 2015-08-25 20:43:32 +10:00
parent 146bc8e11a
commit ccfaaf0b6f
4 changed files with 53 additions and 55 deletions

View file

@ -8,16 +8,17 @@ var ECSignature = require('./ecsignature')
var ZERO = new Buffer([0])
var ONE = new Buffer([1])
var ecurve = require('ecurve')
var secp256k1 = ecurve.getCurveByName('secp256k1')
// https://tools.ietf.org/html/rfc6979#section-3.2
function deterministicGenerateK (curve, hash, d, checkSig) {
function deterministicGenerateK (hash, x, checkSig) {
typeforce(types.tuple(
types.ECCurve,
types.Hash256bit,
types.BigInt,
types.Buffer256bit,
types.Function
), arguments)
var x = d.toBuffer(32)
var k = new Buffer(32)
var v = new Buffer(32)
@ -57,7 +58,7 @@ function deterministicGenerateK (curve, hash, d, checkSig) {
var T = BigInteger.fromBuffer(v)
// Step H3, repeat until T is within the interval [1, n - 1] and is suitable for ECDSA
while ((T.signum() <= 0) || (T.compareTo(curve.n) >= 0) || !checkSig(T)) {
while (T.signum() <= 0 || T.compareTo(secp256k1.n) >= 0 || !checkSig(T)) {
k = createHmac('sha256', k)
.update(v)
.update(ZERO)
@ -74,18 +75,21 @@ function deterministicGenerateK (curve, hash, d, checkSig) {
return T
}
function sign (curve, hash, d) {
typeforce(types.tuple(types.ECCurve, types.Hash256bit, types.BigInt), arguments)
var N_OVER_TWO = secp256k1.n.shiftRight(1)
function sign (hash, d) {
typeforce(types.tuple(types.Hash256bit, types.BigInt), arguments)
var x = d.toBuffer(32)
var e = BigInteger.fromBuffer(hash)
var n = curve.n
var G = curve.G
var n = secp256k1.n
var G = secp256k1.G
var r, s
deterministicGenerateK(curve, hash, d, function (k) {
deterministicGenerateK(hash, x, function (k) {
var Q = G.multiply(k)
if (curve.isInfinity(Q)) return false
if (secp256k1.isInfinity(Q)) return false
r = Q.affineX.mod(n)
if (r.signum() === 0) return false
@ -96,8 +100,6 @@ function sign (curve, hash, d) {
return true
})
var N_OVER_TWO = n.shiftRight(1)
// enforce low S values, see bip62: 'low s values in signatures'
if (s.compareTo(N_OVER_TWO) > 0) {
s = n.subtract(s)
@ -106,16 +108,15 @@ function sign (curve, hash, d) {
return new ECSignature(r, s)
}
function verify (curve, hash, signature, Q) {
function verify (hash, signature, Q) {
typeforce(types.tuple(
types.ECCurve,
types.Hash256bit,
types.ECSignature,
types.ECPoint
), arguments)
var n = curve.n
var G = curve.G
var n = secp256k1.n
var G = secp256k1.G
var r = signature.r
var s = signature.s
@ -141,7 +142,7 @@ function verify (curve, hash, signature, Q) {
var R = G.multiplyTwo(u1, Q, u2)
// 1.4.5 (cont.) Enforce R is not at infinity
if (curve.isInfinity(R)) return false
if (secp256k1.isInfinity(R)) return false
// 1.4.6 Convert the field element R.x to an integer
var xR = R.affineX
@ -161,16 +162,15 @@ function verify (curve, hash, signature, Q) {
*
* http://www.secg.org/download/aid-780/sec1-v2.pdf
*/
function recoverPubKey (curve, e, signature, i) {
function recoverPubKey (e, signature, i) {
typeforce(types.tuple(
types.ECCurve,
types.BigInt,
types.ECSignature,
types.UInt2
), arguments)
var n = curve.n
var G = curve.G
var n = secp256k1.n
var G = secp256k1.G
var r = signature.r
var s = signature.s
@ -186,11 +186,11 @@ function recoverPubKey (curve, e, signature, i) {
// 1.1 Let x = r + jn
var x = isSecondKey ? r.add(n) : r
var R = curve.pointFromX(isYOdd, x)
var R = secp256k1.pointFromX(isYOdd, x)
// 1.4 Check that nR is at infinity
var nR = R.multiply(n)
if (!curve.isInfinity(nR)) throw new Error('nR is not a valid curve point')
if (!secp256k1.isInfinity(nR)) throw new Error('nR is not a valid curve point')
// Compute r^-1
var rInv = r.modInverse(n)
@ -202,7 +202,7 @@ function recoverPubKey (curve, e, signature, i) {
// Q = r^-1 (sR + -eG)
var Q = R.multiplyTwo(s, G, eNeg).multiply(rInv)
curve.validate(Q)
secp256k1.validate(Q)
return Q
}
@ -218,16 +218,15 @@ function recoverPubKey (curve, e, signature, i) {
* This function simply tries all four cases and returns the value
* that resulted in a successful pubkey recovery.
*/
function calcPubKeyRecoveryParam (curve, e, signature, Q) {
function calcPubKeyRecoveryParam (e, signature, Q) {
typeforce(types.tuple(
types.ECCurve,
types.BigInt,
types.ECSignature,
types.ECPoint
), arguments)
for (var i = 0; i < 4; i++) {
var Qprime = recoverPubKey(curve, e, signature, i)
var Qprime = recoverPubKey(e, signature, i)
// 1.6.2 Verify Q
if (Qprime.equals(Q)) {
@ -243,5 +242,8 @@ module.exports = {
deterministicGenerateK: deterministicGenerateK,
recoverPubKey: recoverPubKey,
sign: sign,
verify: verify
verify: verify,
// TODO: remove
__curve: secp256k1
}

View file

@ -1,7 +1,6 @@
var bcrypto = require('./crypto')
var bs58check = require('bs58check')
var ecdsa = require('./ecdsa')
var ecurve = require('ecurve')
var randomBytes = require('randombytes')
var typeforce = require('typeforce')
var types = require('./types')
@ -10,7 +9,8 @@ var wif = require('wif')
var NETWORKS = require('./networks')
var BigInteger = require('bigi')
var secp256k1 = ecurve.getCurveByName('secp256k1')
var ecurve = require('ecurve')
var secp256k1 = ecdsa.__curve
function ECPair (d, Q, options) {
if (options) {
@ -112,7 +112,7 @@ ECPair.prototype.getPublicKeyBuffer = function () {
ECPair.prototype.sign = function (hash) {
if (!this.d) throw new Error('Missing private key')
return ecdsa.sign(secp256k1, hash, this.d)
return ecdsa.sign(hash, this.d)
}
ECPair.prototype.toWIF = function () {
@ -122,7 +122,7 @@ ECPair.prototype.toWIF = function () {
}
ECPair.prototype.verify = function (hash, signature) {
return ecdsa.verify(secp256k1, hash, signature, this.Q)
return ecdsa.verify(hash, signature, this.Q)
}
module.exports = ECPair

View file

@ -7,9 +7,6 @@ var BigInteger = require('bigi')
var ECPair = require('./ecpair')
var ECSignature = require('./ecsignature')
var ecurve = require('ecurve')
var ecparams = ecurve.getCurveByName('secp256k1')
function magicHash (message, network) {
var messagePrefix = new Buffer(network.messagePrefix)
var messageBuffer = new Buffer(message)
@ -25,7 +22,7 @@ function sign (keyPair, message, network) {
var hash = magicHash(message, network)
var signature = keyPair.sign(hash)
var e = BigInteger.fromBuffer(hash)
var i = ecdsa.calcPubKeyRecoveryParam(ecparams, e, signature, keyPair.Q)
var i = ecdsa.calcPubKeyRecoveryParam(e, signature, keyPair.Q)
return signature.toCompact(i, keyPair.compressed)
}
@ -40,7 +37,7 @@ function verify (address, signature, message, network) {
var hash = magicHash(message, network)
var parsed = ECSignature.parseCompact(signature)
var e = BigInteger.fromBuffer(hash)
var Q = ecdsa.recoverPubKey(ecparams, e, parsed.signature, parsed.i)
var Q = ecdsa.recoverPubKey(e, parsed.signature, parsed.i)
var keyPair = new ECPair(null, Q, {
compressed: parsed.compressed,

View file

@ -10,8 +10,7 @@ var sinon = require('sinon')
var BigInteger = require('bigi')
var ECSignature = require('../src/ecsignature')
var ecurve = require('ecurve')
var curve = ecurve.getCurveByName('secp256k1')
var curve = ecdsa.__curve
var fixtures = require('./fixtures/ecdsa.json')
@ -23,10 +22,10 @@ describe('ecdsa', function () {
fixtures.valid.ecdsa.forEach(function (f) {
it('for "' + f.message + '"', function () {
var d = BigInteger.fromHex(f.d)
var x = BigInteger.fromHex(f.d).toBuffer(32)
var h1 = bcrypto.sha256(f.message)
var k = ecdsa.deterministicGenerateK(curve, h1, d, checkSig)
var k = ecdsa.deterministicGenerateK(h1, x, checkSig)
assert.strictEqual(k.toHex(), f.k)
})
})
@ -38,9 +37,9 @@ describe('ecdsa', function () {
.onCall(1).returns(curve.n) // > n-1
.onCall(2).returns(new BigInteger('42')) // valid
var d = new BigInteger('1')
var x = new BigInteger('1').toBuffer(32)
var h1 = new Buffer(32)
var k = ecdsa.deterministicGenerateK(curve, h1, d, checkSig)
var k = ecdsa.deterministicGenerateK(h1, x, checkSig)
assert.strictEqual(k.toString(), '42')
}))
@ -58,20 +57,20 @@ describe('ecdsa', function () {
checkSig.onCall(0).returns(false) // bad signature
checkSig.onCall(1).returns(true) // good signature
var d = new BigInteger('1')
var x = new BigInteger('1').toBuffer(32)
var h1 = new Buffer(32)
var k = ecdsa.deterministicGenerateK(curve, h1, d, checkSig)
var k = ecdsa.deterministicGenerateK(h1, x, checkSig)
assert.strictEqual(k.toString(), '53')
}))
fixtures.valid.rfc6979.forEach(function (f) {
it('produces the expected k values for ' + f.message + " if k wasn't suitable", function () {
var d = BigInteger.fromHex(f.d)
var x = BigInteger.fromHex(f.d).toBuffer(32)
var h1 = bcrypto.sha256(f.message)
var results = []
ecdsa.deterministicGenerateK(curve, h1, d, function (k) {
ecdsa.deterministicGenerateK(h1, x, function (k) {
results.push(k)
return results.length === 16
@ -92,7 +91,7 @@ describe('ecdsa', function () {
var signature = ECSignature.fromDER(new Buffer(f.signature, 'hex'))
var h1 = bcrypto.sha256(f.message)
var e = BigInteger.fromBuffer(h1)
var Qprime = ecdsa.recoverPubKey(curve, e, signature, f.i)
var Qprime = ecdsa.recoverPubKey(e, signature, f.i)
assert(Qprime.equals(Q))
})
@ -113,7 +112,7 @@ describe('ecdsa', function () {
points.forEach(function (expectedHex, i) {
it('recovers an expected point for i of ' + i, function () {
var Qprime = ecdsa.recoverPubKey(curve, e, signature, i)
var Qprime = ecdsa.recoverPubKey(e, signature, i)
var QprimeHex = Qprime.getEncoded().toString('hex')
assert.strictEqual(QprimeHex, expectedHex)
@ -127,7 +126,7 @@ describe('ecdsa', function () {
var signature = new ECSignature(new BigInteger(f.signatureRaw.r, 16), new BigInteger(f.signatureRaw.s, 16))
assert.throws(function () {
ecdsa.recoverPubKey(curve, e, signature, f.i)
ecdsa.recoverPubKey(e, signature, f.i)
}, new RegExp(f.exception))
})
})
@ -138,7 +137,7 @@ describe('ecdsa', function () {
it('produces a deterministic signature for "' + f.message + '"', function () {
var d = BigInteger.fromHex(f.d)
var hash = bcrypto.sha256(f.message)
var signature = ecdsa.sign(curve, hash, d).toDER()
var signature = ecdsa.sign(hash, d).toDER()
assert.strictEqual(signature.toString('hex'), f.signature)
})
@ -146,7 +145,7 @@ describe('ecdsa', function () {
it('should sign with low S value', function () {
var hash = bcrypto.sha256('Vires in numeris')
var sig = ecdsa.sign(curve, hash, BigInteger.ONE)
var sig = ecdsa.sign(hash, BigInteger.ONE)
// See BIP62 for more information
var N_OVER_TWO = curve.n.shiftRight(1)
@ -162,7 +161,7 @@ describe('ecdsa', function () {
var signature = ECSignature.fromDER(new Buffer(f.signature, 'hex'))
var Q = curve.G.multiply(d)
assert(ecdsa.verify(curve, H, signature, Q))
assert(ecdsa.verify(H, signature, Q))
})
})
@ -180,7 +179,7 @@ describe('ecdsa', function () {
var Q = curve.G.multiply(d)
assert.strictEqual(ecdsa.verify(curve, H, signature, Q), false)
assert.strictEqual(ecdsa.verify(H, signature, Q), false)
})
})
})