bitcore-lib-ltc
Advanced tools
Comparing version 10.6.2 to 10.7.0
@@ -6,2 +6,3 @@ 'use strict'; | ||
var _ = require('lodash'); | ||
const BufferUtil = require('../util/buffer'); | ||
@@ -31,2 +32,4 @@ var reversebuf = function(buf) { | ||
BN.fromBuffer = function(buf, opts) { | ||
$.checkArgument(BufferUtil.isBuffer(buf), 'first argument should be a buffer'); | ||
buf = Buffer.from(buf); // ensure Uint8Array is converted to Buffer | ||
if (typeof opts !== 'undefined' && opts.endian === 'little') { | ||
@@ -33,0 +36,0 @@ buf = reversebuf(buf); |
'use strict'; | ||
var BN = require('./bn'); | ||
var Point = require('./point'); | ||
var Signature = require('./signature'); | ||
var PublicKey = require('../publickey'); | ||
var Random = require('./random'); | ||
var Hash = require('./hash'); | ||
var BufferUtil = require('../util/buffer'); | ||
var _ = require('lodash'); | ||
var $ = require('../util/preconditions'); | ||
const BN = require('./bn'); | ||
const Point = require('./point'); | ||
const Signature = require('./signature'); | ||
const PublicKey = require('../publickey'); | ||
const Random = require('./random'); | ||
const Hash = require('./hash'); | ||
const BufferUtil = require('../util/buffer'); | ||
const $ = require('../util/preconditions'); | ||
var ECDSA = function ECDSA(obj) { | ||
if (!(this instanceof ECDSA)) { | ||
return new ECDSA(obj); | ||
} | ||
if (obj) { | ||
this.set(obj); | ||
} | ||
}; | ||
/* jshint maxcomplexity: 9 */ | ||
ECDSA.prototype.set = function(obj) { | ||
this.hashbuf = obj.hashbuf || this.hashbuf; | ||
this.endian = obj.endian || this.endian; //the endianness of hashbuf | ||
this.privkey = obj.privkey || this.privkey; | ||
this.pubkey = obj.pubkey || (this.privkey ? this.privkey.publicKey : this.pubkey); | ||
this.sig = obj.sig || this.sig; | ||
this.k = obj.k || this.k; | ||
this.verified = obj.verified || this.verified; | ||
return this; | ||
}; | ||
ECDSA.prototype.privkey2pubkey = function() { | ||
this.pubkey = this.privkey.toPublicKey(); | ||
}; | ||
ECDSA.prototype.calci = function() { | ||
/** | ||
* Attach the recovery factor i to an ECDSA signature. | ||
* @param {Buffer} hashbuf | ||
* @param {Signature} sig | ||
* @param {PulicKey} pubkey | ||
* @returns {Signature} | ||
*/ | ||
const calci = function(hashbuf, sig, pubkey) { | ||
for (var i = 0; i < 4; i++) { | ||
this.sig.i = i; | ||
var Qprime; | ||
try { | ||
Qprime = this.toPublicKey(); | ||
Qprime = getPublicKey(hashbuf, sig, i); | ||
} catch (e) { | ||
@@ -49,76 +30,28 @@ console.error(e); | ||
if (Qprime.point.eq(this.pubkey.point)) { | ||
this.sig.compressed = this.pubkey.compressed; | ||
return this; | ||
if (Qprime.point.eq(pubkey.point)) { | ||
sig.i = i; | ||
sig.compressed = pubkey.compressed; | ||
return sig; | ||
} | ||
} | ||
this.sig.i = undefined; | ||
throw new Error('Unable to find valid recovery factor'); | ||
}; | ||
ECDSA.fromString = function(str) { | ||
var obj = JSON.parse(str); | ||
return new ECDSA(obj); | ||
}; | ||
ECDSA.prototype.randomK = function() { | ||
var N = Point.getN(); | ||
var k; | ||
do { | ||
k = BN.fromBuffer(Random.getRandomBuffer(32)); | ||
} while (!(k.lt(N) && k.gt(BN.Zero))); | ||
this.k = k; | ||
return this; | ||
}; | ||
// https://tools.ietf.org/html/rfc6979#section-3.2 | ||
ECDSA.prototype.deterministicK = function(badrs) { | ||
/** | ||
* Information about public key recovery: | ||
* https://bitcointalk.org/index.php?topic=6430.0 | ||
* http://stackoverflow.com/questions/19665491/how-do-i-get-an-ecdsa-public-key-from-just-a-bitcoin-signature-sec1-4-1-6-k | ||
* @param {Buffer} hashbuf | ||
* @param {Signature} sig | ||
* @param {Number} i | ||
* @returns {PublicKey} | ||
*/ | ||
const getPublicKey = function(hashbuf, sig, i) { | ||
/* jshint maxstatements: 25 */ | ||
// if r or s were invalid when this function was used in signing, | ||
// we do not want to actually compute r, s here for efficiency, so, | ||
// we can increment badrs. explained at end of RFC 6979 section 3.2 | ||
if (_.isUndefined(badrs)) { | ||
badrs = 0; | ||
} | ||
var v = Buffer.alloc(32); | ||
v.fill(0x01); | ||
var k = Buffer.alloc(32); | ||
k.fill(0x00); | ||
var x = this.privkey.bn.toBuffer({ | ||
size: 32 | ||
}); | ||
var hashbuf = this.endian === 'little' ? BufferUtil.reverse(this.hashbuf) : this.hashbuf | ||
k = Hash.sha256hmac(Buffer.concat([v, Buffer.from([0x00]), x, hashbuf]), k); | ||
v = Hash.sha256hmac(v, k); | ||
k = Hash.sha256hmac(Buffer.concat([v, Buffer.from([0x01]), x, hashbuf]), k); | ||
v = Hash.sha256hmac(v, k); | ||
v = Hash.sha256hmac(v, k); | ||
var T = BN.fromBuffer(v); | ||
var N = Point.getN(); | ||
// also explained in 3.2, we must ensure T is in the proper range (0, N) | ||
for (var i = 0; i < badrs || !(T.lt(N) && T.gt(BN.Zero)); i++) { | ||
k = Hash.sha256hmac(Buffer.concat([v, Buffer.from([0x00])]), k); | ||
v = Hash.sha256hmac(v, k); | ||
v = Hash.sha256hmac(v, k); | ||
T = BN.fromBuffer(v); | ||
} | ||
this.k = T; | ||
return this; | ||
}; | ||
// Information about public key recovery: | ||
// https://bitcointalk.org/index.php?topic=6430.0 | ||
// http://stackoverflow.com/questions/19665491/how-do-i-get-an-ecdsa-public-key-from-just-a-bitcoin-signature-sec1-4-1-6-k | ||
ECDSA.prototype.toPublicKey = function() { | ||
/* jshint maxstatements: 25 */ | ||
var i = this.sig.i; | ||
$.checkArgument(i === 0 || i === 1 || i === 2 || i === 3, new Error('i must be equal to 0, 1, 2, or 3')); | ||
var e = BN.fromBuffer(this.hashbuf); | ||
var r = this.sig.r; | ||
var s = this.sig.s; | ||
var e = BN.fromBuffer(hashbuf); | ||
var r = sig.r; | ||
var s = sig.s; | ||
@@ -156,3 +89,3 @@ // A set LSB signifies that the y-coordinate is odd | ||
var pubkey = PublicKey.fromPoint(Q, this.sig.compressed); | ||
var pubkey = PublicKey.fromPoint(Q, sig.compressed); | ||
@@ -162,38 +95,81 @@ return pubkey; | ||
ECDSA.prototype.sigError = function() { | ||
/* jshint maxstatements: 25 */ | ||
if (!BufferUtil.isBuffer(this.hashbuf) || this.hashbuf.length !== 32) { | ||
return 'hashbuf must be a 32 byte buffer'; | ||
} | ||
var r = this.sig.r; | ||
var s = this.sig.s; | ||
if (!(r.gt(BN.Zero) && r.lt(Point.getN())) || !(s.gt(BN.Zero) && s.lt(Point.getN()))) { | ||
return 'r and s not in range'; | ||
} | ||
/** | ||
* Recover a public key from a signature. | ||
* @param {Buffer} hashbuf | ||
* @param {Signature} sig Signature with the recovery factor i. | ||
* @returns {PublicKey} | ||
*/ | ||
const recoverPublicKey = function(hashbuf, sig) { | ||
return getPublicKey(hashbuf, sig, sig.i); | ||
}; | ||
var e = BN.fromBuffer(this.hashbuf, this.endian ? { | ||
endian: this.endian | ||
} : undefined); | ||
var n = Point.getN(); | ||
var sinv = s.invm(n); | ||
var u1 = sinv.mul(e).umod(n); | ||
var u2 = sinv.mul(r).umod(n); | ||
var p = Point.getG().mulAdd(u1, this.pubkey.point, u2); | ||
if (p.isInfinity()) { | ||
return 'p is infinity'; | ||
/** | ||
* Generate a random k | ||
* @returns {BN} | ||
*/ | ||
const getRandomK = function() { | ||
var N = Point.getN(); | ||
var k; | ||
do { | ||
k = BN.fromBuffer(Random.getRandomBuffer(32)); | ||
} while (!(k.lt(N) && k.gt(BN.Zero))); | ||
return k; | ||
}; | ||
/** | ||
* Generate a deterministic k | ||
* REF: https://tools.ietf.org/html/rfc6979#section-3.2 | ||
* @param {Buffer} hashbuf | ||
* @param {PrivateKey} privkey | ||
* @param {Number} badrs Increment until a valid k is found | ||
* @returns {BN} | ||
*/ | ||
const getDeterministicK = function(hashbuf, privkey, badrs) { | ||
/* jshint maxstatements: 25 */ | ||
// if r or s were invalid when this function was used in signing, | ||
// we do not want to actually compute r, s here for efficiency, so, | ||
// we can increment badrs. explained at end of RFC 6979 section 3.2 | ||
if (!badrs) { | ||
badrs = 0; | ||
} | ||
var v = Buffer.alloc(32); | ||
v.fill(0x01); | ||
var k = Buffer.alloc(32); | ||
k.fill(0x00); | ||
var x = privkey.bn.toBuffer({ | ||
size: 32 | ||
}); | ||
k = Hash.sha256hmac(Buffer.concat([v, Buffer.from([0x00]), x, hashbuf]), k); | ||
v = Hash.sha256hmac(v, k); | ||
k = Hash.sha256hmac(Buffer.concat([v, Buffer.from([0x01]), x, hashbuf]), k); | ||
// double hash v | ||
v = Hash.sha256hmac(v, k); | ||
v = Hash.sha256hmac(v, k); | ||
var T = BN.fromBuffer(v); | ||
var N = Point.getN(); | ||
if (p.getX().umod(n).cmp(r) !== 0) { | ||
return 'Invalid signature'; | ||
} else { | ||
return false; | ||
// also explained in 3.2, we must ensure T is in the proper range (0, N) | ||
for (var i = 0; i < badrs || !(T.lt(N) && T.gt(BN.Zero)); i++) { | ||
k = Hash.sha256hmac(Buffer.concat([v, Buffer.from([0x00])]), k); | ||
// double hash v | ||
v = Hash.sha256hmac(v, k); | ||
v = Hash.sha256hmac(v, k); | ||
T = BN.fromBuffer(v); | ||
} | ||
return T; | ||
}; | ||
ECDSA.toLowS = function(s) { | ||
//enforce low s | ||
//see BIP 62, "low S values in signatures" | ||
if (s.gt(BN.fromBuffer(Buffer.from('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0', 'hex')))) { | ||
/** | ||
* Convert s to a low s | ||
* see BIP 62, "low S values in signatures" | ||
* @param {BN} s | ||
* @returns {BN} | ||
*/ | ||
const toLowS = function(s) { | ||
if (s.gt(new BN('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0', 'hex'))) { | ||
s = Point.getN().sub(s); | ||
@@ -204,3 +180,24 @@ } | ||
ECDSA.prototype._findSignature = function(d, e) { | ||
/** | ||
* Sign a hash with a private key. | ||
* @param {Buffer|Uint8Array} hashbuf | ||
* @param {PrivateKey} privkey | ||
* @param {Object|undefined} opts An object of optional parameters | ||
* @param {String} opts.endian 'big' or 'little' (default: big) | ||
* @param {Boolean} opts.randomK Use a random value for k - produces a non-deterministic signature (default: false) | ||
* @returns {Signature} | ||
*/ | ||
const sign = function(hashbuf, privkey, opts) { | ||
const { endian = 'big', randomK = false } = opts || {}; | ||
$.checkState(BufferUtil.isBuffer(hashbuf) && hashbuf.length === 32, 'hashbuf must be a 32 byte buffer'); | ||
$.checkState(privkey && privkey.bn, 'privkey must be a PrivateKey'); | ||
var d = privkey.bn; | ||
hashbuf = Buffer.from(hashbuf); | ||
if (endian === 'little') { | ||
hashbuf.reverse(); | ||
} | ||
var e = BN.fromBuffer(hashbuf); | ||
var N = Point.getN(); | ||
@@ -212,7 +209,4 @@ var G = Point.getG(); | ||
do { | ||
if (!this.k || badrs > 0) { | ||
this.deterministicK(badrs); | ||
} | ||
k = randomK ? getRandomK() : getDeterministicK(hashbuf, privkey, badrs); | ||
badrs++; | ||
k = this.k; | ||
Q = G.mul(k); | ||
@@ -223,80 +217,92 @@ r = Q.x.umod(N); | ||
s = ECDSA.toLowS(s); | ||
return { | ||
s: s, | ||
r: r | ||
}; | ||
s = toLowS(s); | ||
return new Signature({ | ||
s, | ||
r, | ||
compressed: privkey.publicKey.compressed | ||
}); | ||
}; | ||
ECDSA.prototype.sign = function() { | ||
var hashbuf = this.hashbuf; | ||
var privkey = this.privkey; | ||
var d = privkey.bn; | ||
$.checkState(hashbuf && privkey && d, new Error('invalid parameters')); | ||
$.checkState(BufferUtil.isBuffer(hashbuf) && hashbuf.length === 32, new Error('hashbuf must be a 32 byte buffer')); | ||
/** | ||
* Get signature verification error string | ||
* @param {Buffer} hashbuf | ||
* @param {Signature} sig | ||
* @param {PublicKey} pubkey | ||
* @param {Object|undefined} opts An object of optional parameters | ||
* @param {String} opts.endian 'big' or 'little' (default: big) | ||
* @returns {String|undefined} Returns an error string, or undefined if there is no error | ||
*/ | ||
const verificationError = function(hashbuf, sig, pubkey, opts) { | ||
const { endian = 'big' } = opts || {}; | ||
var e = BN.fromBuffer(hashbuf, this.endian ? { | ||
endian: this.endian | ||
} : undefined); | ||
if (!BufferUtil.isBuffer(hashbuf) || hashbuf.length !== 32) { | ||
return 'hashbuf must be a 32 byte buffer'; | ||
} | ||
var obj = this._findSignature(d, e); | ||
obj.compressed = this.pubkey.compressed; | ||
var r = sig.r; | ||
var s = sig.s; | ||
if (!(r.gt(BN.Zero) && r.lt(Point.getN())) || !(s.gt(BN.Zero) && s.lt(Point.getN()))) { | ||
return 'r and s not in range'; | ||
} | ||
this.sig = new Signature(obj); | ||
return this; | ||
}; | ||
var e = BN.fromBuffer(hashbuf, { endian }); | ||
var n = Point.getN(); | ||
var sinv = s.invm(n); | ||
var u1 = sinv.mul(e).umod(n); | ||
var u2 = sinv.mul(r).umod(n); | ||
ECDSA.prototype.signRandomK = function() { | ||
this.randomK(); | ||
return this.sign(); | ||
var p = Point.getG().mulAdd(u1, pubkey.point, u2); | ||
if (p.isInfinity()) { | ||
return 'p is infinity'; | ||
} | ||
if (p.getX().umod(n).cmp(r) !== 0) { | ||
return 'Invalid signature'; | ||
} | ||
return; // no error | ||
}; | ||
ECDSA.prototype.toString = function() { | ||
var obj = {}; | ||
if (this.hashbuf) { | ||
obj.hashbuf = this.hashbuf.toString('hex'); | ||
/** | ||
* Verify a signature | ||
* @param {Buffer} hashbuf | ||
* @param {Signature} sig | ||
* @param {PublicKey} pubkey | ||
* @param {Object|undefined} opts An object of optional parameters | ||
* @param {String} opts.endian 'big' or 'little' (default: big) | ||
* @returns {Boolean} | ||
*/ | ||
const verify = function(hashbuf, sig, pubkey, opts) { | ||
if (!pubkey) { | ||
throw new Error('pubkey required for signature verification'); | ||
} | ||
if (this.privkey) { | ||
obj.privkey = this.privkey.toString(); | ||
pubkey = new PublicKey(pubkey); | ||
if (!sig) { | ||
throw new Error('signature required for verification'); | ||
} | ||
if (this.pubkey) { | ||
obj.pubkey = this.pubkey.toString(); | ||
} | ||
if (this.sig) { | ||
obj.sig = this.sig.toString(); | ||
} | ||
if (this.k) { | ||
obj.k = this.k.toString(); | ||
} | ||
return JSON.stringify(obj); | ||
}; | ||
sig = new Signature(sig); | ||
ECDSA.prototype.verify = function() { | ||
if (!this.sigError()) { | ||
this.verified = true; | ||
} else { | ||
this.verified = false; | ||
} | ||
return this; | ||
return !verificationError(hashbuf, sig, pubkey, opts); | ||
}; | ||
ECDSA.sign = function(hashbuf, privkey, endian) { | ||
return ECDSA().set({ | ||
hashbuf: hashbuf, | ||
endian: endian, | ||
privkey: privkey | ||
}).sign().sig; | ||
module.exports = { | ||
sign, | ||
verify, | ||
verificationError, | ||
// pubkey recovery methods | ||
calci, | ||
recoverPublicKey, | ||
}; | ||
ECDSA.verify = function(hashbuf, sig, pubkey, endian) { | ||
return ECDSA().set({ | ||
hashbuf: hashbuf, | ||
endian: endian, | ||
sig: sig, | ||
pubkey: pubkey | ||
}).verify().verified; | ||
module.exports.__testing__ = { | ||
getDeterministicK, | ||
getPublicKey, | ||
getRandomK, | ||
toLowS, | ||
}; | ||
module.exports = ECDSA; |
@@ -105,10 +105,8 @@ 'use strict'; | ||
var sig; | ||
if(signingMethod === 'ecdsa') { | ||
var hashbuf = sighash(transaction, sighashType, inputIndex, subscript); | ||
sig = ECDSA.sign(hashbuf, privateKey, 'little').set({ | ||
nhashtype: sighashType | ||
}); | ||
return sig; | ||
} | ||
const hashbuf = sighash(transaction, sighashType, inputIndex, subscript); | ||
const sig = ECDSA.sign(hashbuf, privateKey, { endian: 'little' }); | ||
sig.nhashtype = sighashType; | ||
return sig; | ||
} | ||
throw new Error('signingMethod not supported ', signingMethod); | ||
@@ -136,3 +134,3 @@ } | ||
var hashbuf = sighash(transaction, signature.nhashtype, inputIndex, subscript); | ||
return ECDSA.verify(hashbuf, signature, publicKey, 'little'); | ||
return ECDSA.verify(hashbuf, signature, publicKey, { endian: 'little' }); | ||
} | ||
@@ -139,0 +137,0 @@ throw new Error('signingMethod not supported ', signingMethod); |
{ | ||
"name": "bitcore-lib-ltc", | ||
"version": "10.6.2", | ||
"version": "10.7.0", | ||
"description": "A pure and powerful JavaScript Litecoin library.", | ||
@@ -106,3 +106,3 @@ "author": "BitPay <dev@bitpay.com>", | ||
"license": "MIT", | ||
"gitHead": "b8b83ced1b06f9db46f3a872a99e252add57c494" | ||
"gitHead": "f1efdbe2e7b17e22c586145c450d75ea94497591" | ||
} |
@@ -118,2 +118,28 @@ 'use strict'; | ||
it('should work with Uint8Array input', function() { | ||
var bn = BN.fromBuffer(Uint8Array.from([0xa1, 0xb2, 0xc3]), { endian: 'big' }); | ||
bn.toString(16).should.equal('a1b2c3'); | ||
}); | ||
it('should throw on invalid input: Array', function() { | ||
should.throw( | ||
() => BN.fromBuffer(Array.from([0xa1, 0xb2, 0xc3]), { endian: 'big' }), | ||
'Invalid Argument: first argument should be a buffer' | ||
); | ||
}); | ||
it('should throw on invalid input: string', function() { | ||
should.throw( | ||
() => BN.fromBuffer('a1b2c3', { endian: 'big' }), | ||
'Invalid Argument: first argument should be a buffer' | ||
); | ||
}); | ||
it('should throw on invalid input: Uint16Array', function() { | ||
should.throw( | ||
() => BN.fromBuffer(Uint16Array.from([0xa1, 0xb2, 0xc3]), { endian: 'big' }), | ||
'Invalid Argument: first argument should be a buffer' | ||
); | ||
}); | ||
}); | ||
@@ -120,0 +146,0 @@ |
'use strict'; | ||
var ECDSA = require('../../lib/crypto/ecdsa'); | ||
var Hash = require('../../lib/crypto/hash'); | ||
var Privkey = require('../../lib/privatekey'); | ||
var Pubkey = require('../../lib/publickey'); | ||
var Signature = require('../../lib/crypto/signature'); | ||
var BN = require('../../lib/crypto/bn'); | ||
var point = require('../../lib/crypto/point'); | ||
var should = require('chai').should(); | ||
var vectors = require('../data/ecdsa'); | ||
const should = require('chai').should(); | ||
const ECDSA = require('../../lib/crypto/ecdsa'); | ||
const Hash = require('../../lib/crypto/hash'); | ||
const PrivateKey = require('../../lib/privatekey'); | ||
const Pubkey = require('../../lib/publickey'); | ||
const Signature = require('../../lib/crypto/signature'); | ||
const BN = require('../../lib/crypto/bn'); | ||
const point = require('../../lib/crypto/point'); | ||
const vectors = require('../data/ecdsa'); | ||
describe('ECDSA', function() { | ||
it('instantiation', function() { | ||
var ecdsa = new ECDSA(); | ||
should.exist(ecdsa); | ||
}); | ||
const hashbuf = Hash.sha256(Buffer.from('test data')); | ||
const privkey = new PrivateKey(new BN('fee0a1f7afebf9d2a5a80c0c98a31c709681cce195cbcd06342b517970c0be1e', 16)); | ||
const pubkey = privkey.toPublicKey(); | ||
const signature = ECDSA.sign(hashbuf, privkey); | ||
var ecdsa = new ECDSA(); | ||
ecdsa.hashbuf = Hash.sha256(Buffer.from('test data')); | ||
ecdsa.privkey = new Privkey(BN.fromBuffer( | ||
Buffer.from('fee0a1f7afebf9d2a5a80c0c98a31c709681cce195cbcd06342b517970c0be1e', 'hex') | ||
)); | ||
ecdsa.privkey2pubkey(); | ||
describe('#set', function() { | ||
it('sets hashbuf', function() { | ||
should.exist(ECDSA().set({ | ||
hashbuf: ecdsa.hashbuf | ||
}).hashbuf); | ||
}); | ||
}); | ||
describe('#calci', function() { | ||
it('calculates i correctly', function() { | ||
ecdsa.randomK(); | ||
ecdsa.sign(); | ||
ecdsa.calci(); | ||
should.exist(ecdsa.sig.i); | ||
const sig = ECDSA.sign(hashbuf, privkey); | ||
ECDSA.calci(hashbuf, sig, pubkey); | ||
should.exist(sig.i); | ||
}); | ||
@@ -45,15 +29,9 @@ | ||
var hashbuf = Hash.sha256(Buffer.from('some data')); | ||
var r = new BN('71706645040721865894779025947914615666559616020894583599959600180037551395766', 10); | ||
var s = new BN('109412465507152403114191008482955798903072313614214706891149785278625167723646', 10); | ||
var ecdsa = new ECDSA({ | ||
privkey: new Privkey(BN.fromBuffer(Hash.sha256(Buffer.from('test')))), | ||
hashbuf: hashbuf, | ||
sig: new Signature({ | ||
r: r, | ||
s: s | ||
}) | ||
const sig = new Signature({ | ||
r: new BN('71706645040721865894779025947914615666559616020894583599959600180037551395766', 10), | ||
s: new BN('109412465507152403114191008482955798903072313614214706891149785278625167723646', 10) | ||
}); | ||
ecdsa.calci(); | ||
ecdsa.sig.i.should.equal(1); | ||
const privkey = new PrivateKey(new BN.fromBuffer(Hash.sha256(Buffer.from('test')))); | ||
ECDSA.calci(hashbuf, sig, privkey.toPublicKey()); | ||
sig.i.should.equal(1); | ||
}); | ||
@@ -63,20 +41,7 @@ | ||
describe('#fromString', function() { | ||
describe('#getRandomK', function() { | ||
it('round trip with fromString', function() { | ||
var str = ecdsa.toString(); | ||
var ecdsa2 = new ECDSA.fromString(str); | ||
should.exist(ecdsa2.hashbuf); | ||
should.exist(ecdsa2.privkey); | ||
}); | ||
}); | ||
describe('#randomK', function() { | ||
it('should generate a new random k when called twice in a row', function() { | ||
ecdsa.randomK(); | ||
var k1 = ecdsa.k; | ||
ecdsa.randomK(); | ||
var k2 = ecdsa.k; | ||
var k1 = ECDSA.__testing__.getRandomK(); | ||
var k2 = ECDSA.__testing__.getRandomK(); | ||
(k1.cmp(k2) === 0).should.equal(false); | ||
@@ -86,4 +51,3 @@ }); | ||
it('should generate a random k that is (almost always) greater than this relatively small number', function() { | ||
ecdsa.randomK(); | ||
var k1 = ecdsa.k; | ||
var k1 = ECDSA.__testing__.getRandomK(); | ||
var k2 = new BN(Math.pow(2, 32)).mul(new BN(Math.pow(2, 32))).mul(new BN(Math.pow(2, 32))); | ||
@@ -95,32 +59,32 @@ k2.gt(k1).should.equal(false); | ||
describe('#deterministicK', function() { | ||
describe('#getDeterministicK', function() { | ||
it('should generate the same deterministic k', function() { | ||
ecdsa.deterministicK(); | ||
ecdsa.k.toBuffer().toString('hex') | ||
var k = ECDSA.__testing__.getDeterministicK(hashbuf, privkey); | ||
k.toBuffer().toString('hex') | ||
.should.equal('fcce1de7a9bcd6b2d3defade6afa1913fb9229e3b7ddf4749b55c4848b2a196e'); | ||
}); | ||
it('should generate the same deterministic k if badrs is set', function() { | ||
ecdsa.deterministicK(0); | ||
ecdsa.k.toBuffer().toString('hex') | ||
var k = ECDSA.__testing__.getDeterministicK(hashbuf, privkey, 0); | ||
k.toBuffer().toString('hex') | ||
.should.equal('fcce1de7a9bcd6b2d3defade6afa1913fb9229e3b7ddf4749b55c4848b2a196e'); | ||
ecdsa.deterministicK(1); | ||
ecdsa.k.toBuffer().toString('hex') | ||
k = ECDSA.__testing__.getDeterministicK(hashbuf, privkey, 1); | ||
k.toBuffer().toString('hex') | ||
.should.not.equal('fcce1de7a9bcd6b2d3defade6afa1913fb9229e3b7ddf4749b55c4848b2a196e'); | ||
ecdsa.k.toBuffer().toString('hex') | ||
k.toBuffer().toString('hex') | ||
.should.equal('727fbcb59eb48b1d7d46f95a04991fc512eb9dbf9105628e3aec87428df28fd8'); | ||
}); | ||
it('should compute this test vector correctly', function() { | ||
// test fixture from bitcoinjs | ||
// https://github.com/bitcoinjs/bitcoinjs-lib/blob/10630873ebaa42381c5871e20336fbfb46564ac8/test/fixtures/ecdsa.json#L6 | ||
var ecdsa = new ECDSA(); | ||
ecdsa.hashbuf = Hash.sha256(Buffer.from('Everything should be made as simple as possible, but not simpler.')); | ||
ecdsa.privkey = new Privkey(new BN(1)); | ||
ecdsa.privkey2pubkey(); | ||
ecdsa.deterministicK(); | ||
ecdsa.k.toBuffer().toString('hex') | ||
const hashbuf = Hash.sha256(Buffer.from('Everything should be made as simple as possible, but not simpler.')); | ||
const privkey = new PrivateKey(new BN(1)); | ||
const k = ECDSA.__testing__.getDeterministicK(hashbuf, privkey); | ||
k.toBuffer().toString('hex') | ||
.should.equal('ec633bd56a5774a0940cb97e27a9e4e51dc94af737596a0c5cbb3d30332d92a5'); | ||
ecdsa.sign(); | ||
ecdsa.sig.r.toString() | ||
const sig = ECDSA.sign(hashbuf, privkey); | ||
sig.r.toString() | ||
.should.equal('23362334225185207751494092901091441011938859014081160902781146257181456271561'); | ||
ecdsa.sig.s.toString() | ||
sig.s.toString() | ||
.should.equal('50433721247292933944369538617440297985091596895097604618403996029256432099938'); | ||
@@ -130,28 +94,22 @@ }); | ||
describe('#toPublicKey', function() { | ||
describe('#recoverPublicKey', function() { | ||
it('should calculate the correct public key', function() { | ||
ecdsa.k = new BN('114860389168127852803919605627759231199925249596762615988727970217268189974335', 10); | ||
ecdsa.sign(); | ||
ecdsa.sig.i = 0; | ||
var pubkey = ecdsa.toPublicKey(); | ||
pubkey.point.eq(ecdsa.pubkey.point).should.equal(true); | ||
const sig = ECDSA.sign(hashbuf, privkey); | ||
ECDSA.calci(hashbuf, sig, privkey.publicKey); | ||
const pubkey = ECDSA.recoverPublicKey(hashbuf, sig); | ||
pubkey.point.eq(privkey.publicKey.point).should.equal(true); | ||
}); | ||
it('should calculate the correct public key for this signature with low s', function() { | ||
ecdsa.k = new BN('114860389168127852803919605627759231199925249596762615988727970217268189974335', 10); | ||
ecdsa.sig = Signature.fromString('3045022100ec3cfe0e335791ad278b4ec8eac93d0347' + | ||
'a97877bb1d54d35d189e225c15f6650220278cf15b05ce47fb37d2233802899d94c774d5480bba9f0f2d996baa13370c43'); | ||
ecdsa.sig.i = 0; | ||
var pubkey = ecdsa.toPublicKey(); | ||
pubkey.point.eq(ecdsa.pubkey.point).should.equal(true); | ||
const sig = Signature.fromString('3045022100ec3cfe0e335791ad278b4ec8eac93d0347a97877bb1d54d35d189e225c15f6650220278cf15b05ce47fb37d2233802899d94c774d5480bba9f0f2d996baa13370c43'); | ||
sig.i = 0; | ||
const pubkey = ECDSA.recoverPublicKey(hashbuf, sig); | ||
pubkey.point.eq(privkey.publicKey.point).should.equal(true); | ||
}); | ||
it('should calculate the correct public key for this signature with high s', function() { | ||
ecdsa.k = new BN('114860389168127852803919605627759231199925249596762615988727970217268189974335', 10); | ||
ecdsa.sign(); | ||
ecdsa.sig = Signature.fromString('3046022100ec3cfe0e335791ad278b4ec8eac93d0347' + | ||
'a97877bb1d54d35d189e225c15f665022100d8730ea4fa31b804c82ddcc7fd766269f33a079ea38e012c9238f2e2bcff34fe'); | ||
ecdsa.sig.i = 1; | ||
var pubkey = ecdsa.toPublicKey(); | ||
pubkey.point.eq(ecdsa.pubkey.point).should.equal(true); | ||
const sig = Signature.fromString('3046022100ec3cfe0e335791ad278b4ec8eac93d0347a97877bb1d54d35d189e225c15f665022100d8730ea4fa31b804c82ddcc7fd766269f33a079ea38e012c9238f2e2bcff34fe'); | ||
sig.i = 1; | ||
const pubkey = ECDSA.recoverPublicKey(hashbuf, sig); | ||
pubkey.point.eq(privkey.publicKey.point).should.equal(true); | ||
}); | ||
@@ -161,26 +119,22 @@ | ||
describe('#sigError', function() { | ||
describe('#verificationError', function() { | ||
it('should return an error if the hash is invalid', function() { | ||
var ecdsa = new ECDSA(); | ||
ecdsa.sigError().should.equal('hashbuf must be a 32 byte buffer'); | ||
ECDSA.verificationError(null, signature, pubkey).should.equal('hashbuf must be a 32 byte buffer'); | ||
}); | ||
it('should return an error if r, s are invalid', function() { | ||
var ecdsa = new ECDSA(); | ||
ecdsa.hashbuf = Hash.sha256(Buffer.from('test')); | ||
var pk = Pubkey.fromDER(Buffer.from('041ff0fe0f7b15ffaa85ff9f4744d539139c252a49' + | ||
'710fb053bb9f2b933173ff9a7baad41d04514751e6851f5304fd243751703bed21b914f6be218c0fa354a341', 'hex')); | ||
ecdsa.pubkey = pk; | ||
ecdsa.sig = new Signature(); | ||
ecdsa.sig.r = new BN(0); | ||
ecdsa.sig.s = new BN(0); | ||
ecdsa.sigError().should.equal('r and s not in range'); | ||
const hashbuf = Hash.sha256(Buffer.from('test')); | ||
const pk = Pubkey.fromDER(Buffer.from('041ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a7baad41d04514751e6851f5304fd243751703bed21b914f6be218c0fa354a341', 'hex')); | ||
const sig = new Signature({ | ||
r: new BN(0), | ||
s: new BN(0) | ||
}); | ||
ECDSA.verificationError(hashbuf, sig, pk).should.equal('r and s not in range'); | ||
}); | ||
it('should return an error if the signature is incorrect', function() { | ||
ecdsa.sig = Signature.fromString('3046022100e9915e6236695f093a4128ac2a956c40' + | ||
'ed971531de2f4f41ba05fac7e2bd019c02210094e6a4a769cc7f2a8ab3db696c7cd8d56bcdbfff860a8c81de4bc6a798b90827'); | ||
ecdsa.sig.r = ecdsa.sig.r.add(new BN(1)); | ||
ecdsa.sigError().should.equal('Invalid signature'); | ||
const sig = Signature.fromString('3046022100e9915e6236695f093a4128ac2a956c40ed971531de2f4f41ba05fac7e2bd019c02210094e6a4a769cc7f2a8ab3db696c7cd8d56bcdbfff860a8c81de4bc6a798b90827'); | ||
sig.r = sig.r.add(new BN(1)); | ||
ECDSA.verificationError(hashbuf, sig, pubkey).should.equal('Invalid signature'); | ||
}); | ||
@@ -193,140 +147,150 @@ | ||
it('should create a valid signature', function() { | ||
ecdsa.randomK(); | ||
ecdsa.sign(); | ||
ecdsa.verify().verified.should.equal(true); | ||
const sig = ECDSA.sign(hashbuf, privkey); | ||
ECDSA.verify(hashbuf, sig, pubkey).should.equal(true); | ||
}); | ||
it('should should throw an error if hashbuf is not 32 bytes', function() { | ||
var ecdsa2 = ECDSA().set({ | ||
hashbuf: ecdsa.hashbuf.slice(0, 31), | ||
privkey: ecdsa.privkey | ||
}); | ||
ecdsa2.randomK(); | ||
ecdsa2.sign.bind(ecdsa2).should.throw('hashbuf must be a 32 byte buffer'); | ||
it('should create a valid signature defaulting to deterministicK', function() { | ||
const sig = ECDSA.sign(hashbuf, privkey); | ||
sig.toString('hex').should.equal(signature.toString('hex')); | ||
}); | ||
it('should default to deterministicK', function() { | ||
var ecdsa2 = new ECDSA(ecdsa); | ||
ecdsa2.k = undefined; | ||
var called = 0; | ||
var deterministicK = ecdsa2.deterministicK.bind(ecdsa2); | ||
ecdsa2.deterministicK = function() { | ||
deterministicK(); | ||
called++; | ||
}; | ||
ecdsa2.sign(); | ||
called.should.equal(1); | ||
it('should create a valid signature explicitly using deterministicK', function() { | ||
const sig = ECDSA.sign(hashbuf, privkey, { randomK: false }); | ||
sig.toString('hex').should.equal(signature.toString('hex')); | ||
}); | ||
it('should create a valid signature using randomK', function() { | ||
const sig = ECDSA.sign(hashbuf, privkey, { randomK: true }); | ||
ECDSA.verify(hashbuf, sig, pubkey).should.equal(true); | ||
sig.toString('hex').should.not.equal(signature.toString('hex')); | ||
}); | ||
it('should not re-use k values', function() { | ||
const sig1 = ECDSA.sign(hashbuf, privkey, { randomK: true }); | ||
const sig2 = ECDSA.sign(hashbuf, privkey, { randomK: true }); | ||
sig1.toString('hex').should.not.equal(sig2.toString('hex')); | ||
}); | ||
it('should should throw an error if hashbuf is not 32 bytes', function() { | ||
try { | ||
ECDSA.sign(hashbuf.slice(0, 31), privkey, { randomK: true }); | ||
throw new Error('should have thrown'); | ||
} catch (e) { | ||
e.message.should.equal('Invalid state: hashbuf must be a 32 byte buffer'); | ||
} | ||
}); | ||
it('should generate right K', function() { | ||
var msg1 = Buffer.from('52204d20fd0131ae1afd173fd80a3a746d2dcc0cddced8c9dc3d61cc7ab6e966', 'hex'); | ||
var msg2 = [].reverse.call(Buffer.from(msg1)) | ||
var pk = Buffer.from('16f243e962c59e71e54189e67e66cf2440a1334514c09c00ddcc21632bac9808', 'hex'); | ||
var signature1 = ECDSA.sign(msg1, Privkey.fromBuffer(pk)).toBuffer().toString('hex'); | ||
var signature2 = ECDSA.sign(msg2, Privkey.fromBuffer(pk), 'little').toBuffer().toString('hex'); | ||
const msg1 = Buffer.from('52204d20fd0131ae1afd173fd80a3a746d2dcc0cddced8c9dc3d61cc7ab6e966', 'hex'); | ||
const msg2 = [].reverse.call(Buffer.from(msg1)) | ||
const pk = Buffer.from('16f243e962c59e71e54189e67e66cf2440a1334514c09c00ddcc21632bac9808', 'hex'); | ||
const signature1 = ECDSA.sign(msg1, PrivateKey.fromBuffer(pk)).toBuffer().toString('hex'); | ||
const signature2 = ECDSA.sign(msg2, PrivateKey.fromBuffer(pk), { endian: 'little' }).toBuffer().toString('hex'); | ||
signature1.should.equal(signature2); | ||
}); | ||
}); | ||
it('should generate correct signature for Uint8Array input', function() { | ||
const pk = PrivateKey.fromString('1471d2f131a665b24d419f0920e854993153391e64d1971704ded65ffc3d1f0c'); | ||
const hashbuf = Buffer.from('7afd0a663b64666242ef6edf3542bc18a6a4587b01249a1fd2d8164b0eedf8d6', 'hex'); | ||
const ctrlSig = ECDSA.sign(hashbuf, pk); | ||
const testSig = ECDSA.sign(Uint8Array.from(hashbuf), pk); | ||
ctrlSig.toString('hex').should.equal('30450221009cf9c9f5e45fba55c5f3237423158ecbdb66267edfc18742bef13277d919d8e302200d83137ceaab33eea61c7a5cbbebc5856cdc524f396556eadeae2a1f1d9bb691'); | ||
ctrlSig.toString('hex').should.equal(testSig.toString('hex')); | ||
}); | ||
describe('#toString', function() { | ||
it('should convert this to a string', function() { | ||
var str = ecdsa.toString(); | ||
(typeof str === 'string').should.equal(true); | ||
it('should throw on improper input: Array', function() { | ||
const pk = PrivateKey.fromString('1471d2f131a665b24d419f0920e854993153391e64d1971704ded65ffc3d1f0c'); | ||
const hashbuf = Buffer.from('7afd0a663b64666242ef6edf3542bc18a6a4587b01249a1fd2d8164b0eedf8d6', 'hex'); | ||
should.throw( | ||
() => ECDSA.sign(Array.from(hashbuf), pk), | ||
'Invalid state: hashbuf must be a 32 byte buffer' | ||
); | ||
}); | ||
}); | ||
describe('signing and verification', function() { | ||
describe('@sign', function() { | ||
it('should produce a signature', function() { | ||
var sig = ECDSA.sign(ecdsa.hashbuf, ecdsa.privkey); | ||
(sig instanceof Signature).should.equal(true); | ||
}); | ||
it('should produce a signature, and be different when called twice', function() { | ||
ecdsa.signRandomK(); | ||
should.exist(ecdsa.sig); | ||
var ecdsa2 = ECDSA(ecdsa); | ||
ecdsa2.signRandomK(); | ||
ecdsa.sig.toString().should.not.equal(ecdsa2.sig.toString()); | ||
}); | ||
it('should throw on improper input: Uint16Array', function() { | ||
const pk = PrivateKey.fromString('1471d2f131a665b24d419f0920e854993153391e64d1971704ded65ffc3d1f0c'); | ||
const hashbuf = Buffer.from('7afd0a663b64666242ef6edf3542bc18a6a4587b01249a1fd2d8164b0eedf8d6', 'hex'); | ||
should.throw( | ||
() => ECDSA.sign(Uint16Array.from(hashbuf), pk), | ||
'Invalid state: hashbuf must be a 32 byte buffer' | ||
); | ||
}); | ||
describe('#verify', function() { | ||
it('should verify a signature that was just signed', function() { | ||
ecdsa.sig = Signature.fromString('3046022100e9915e6236695f093a4128ac2a956c' + | ||
'40ed971531de2f4f41ba05fac7e2bd019c02210094e6a4a769cc7f2a8ab3db696c7cd8d56bcdbfff860a8c81de4bc6a798b90827'); | ||
ecdsa.verify().verified.should.equal(true); | ||
}); | ||
it('should verify this known good signature', function() { | ||
ecdsa.signRandomK(); | ||
ecdsa.verify().verified.should.equal(true); | ||
}); | ||
it('should verify a valid signature, and unverify an invalid signature', function() { | ||
var sig = ECDSA.sign(ecdsa.hashbuf, ecdsa.privkey); | ||
ECDSA.verify(ecdsa.hashbuf, sig, ecdsa.pubkey).should.equal(true); | ||
var fakesig = new Signature(sig.r.add(new BN(1)), sig.s); | ||
ECDSA.verify(ecdsa.hashbuf, fakesig, ecdsa.pubkey).should.equal(false); | ||
}); | ||
it('should work with big and little endian', function() { | ||
var sig = ECDSA.sign(ecdsa.hashbuf, ecdsa.privkey, 'big'); | ||
ECDSA.verify(ecdsa.hashbuf, sig, ecdsa.pubkey, 'big').should.equal(true); | ||
ECDSA.verify(ecdsa.hashbuf, sig, ecdsa.pubkey, 'little').should.equal(false); | ||
sig = ECDSA.sign(ecdsa.hashbuf, ecdsa.privkey, 'little'); | ||
ECDSA.verify(ecdsa.hashbuf, sig, ecdsa.pubkey, 'big').should.equal(false); | ||
ECDSA.verify(ecdsa.hashbuf, sig, ecdsa.pubkey, 'little').should.equal(true); | ||
}); | ||
}); | ||
describe('#verify', function() { | ||
it('should verify a signature that was just signed', function() { | ||
const sig = Signature.fromString('3046022100e9915e6236695f093a4128ac2a956c40ed971531de2f4f41ba05fac7e2bd019c02210094e6a4a769cc7f2a8ab3db696c7cd8d56bcdbfff860a8c81de4bc6a798b90827'); | ||
ECDSA.verify(hashbuf, sig, pubkey).should.equal(true); | ||
}); | ||
it('should verify this known good signature', function() { | ||
const sig = ECDSA.sign(hashbuf, privkey, { randomK: true }); | ||
ECDSA.verify(hashbuf, sig, pubkey).should.equal(true); | ||
}); | ||
it('should verify a valid signature, and unverify an invalid signature', function() { | ||
const sig = ECDSA.sign(hashbuf, privkey); | ||
ECDSA.verify(hashbuf, sig, pubkey).should.equal(true); | ||
const fakesig = new Signature(sig.r.add(new BN(1)), sig.s); | ||
ECDSA.verify(hashbuf, fakesig, pubkey).should.equal(false); | ||
}); | ||
it('should work with big and little endian', function() { | ||
let sig = ECDSA.sign(hashbuf, privkey, { endian: 'big' }); | ||
ECDSA.verify(hashbuf, sig, pubkey, { endian: 'big' }).should.equal(true); | ||
ECDSA.verify(hashbuf, sig, pubkey, { endian: 'little' }).should.equal(false); | ||
sig = ECDSA.sign(hashbuf, privkey, { endian: 'little' }); | ||
ECDSA.verify(hashbuf, sig, pubkey, { endian: 'big' }).should.equal(false); | ||
ECDSA.verify(hashbuf, sig, pubkey, { endian: 'little' }).should.equal(true); | ||
}); | ||
}); | ||
describe('vectors', function() { | ||
describe('vectors', function() { | ||
vectors.valid.forEach(function(obj, i) { | ||
it('should validate valid vector ' + i, function() { | ||
var ecdsa = ECDSA().set({ | ||
privkey: new Privkey(BN.fromBuffer(Buffer.from(obj.d, 'hex'))), | ||
k: BN.fromBuffer(Buffer.from(obj.k, 'hex')), | ||
hashbuf: Hash.sha256(Buffer.from(obj.message)), | ||
sig: new Signature().set({ | ||
r: new BN(obj.signature.r), | ||
s: new BN(obj.signature.s), | ||
i: obj.i | ||
}) | ||
}); | ||
var ecdsa2 = ECDSA(ecdsa); | ||
ecdsa2.k = undefined; | ||
ecdsa2.sign(); | ||
ecdsa2.calci(); | ||
ecdsa2.k.toString().should.equal(ecdsa.k.toString()); | ||
ecdsa2.sig.toString().should.equal(ecdsa.sig.toString()); | ||
ecdsa2.sig.i.should.equal(ecdsa.sig.i); | ||
ecdsa.verify().verified.should.equal(true); | ||
for (const i in vectors.valid) { | ||
const obj = vectors.valid[i]; | ||
it('should validate valid vector ' + i, function() { | ||
const privkey = new PrivateKey(new BN(obj.d, 16)); | ||
const vectorK = new BN(obj.k, 16); | ||
const hashbuf = Hash.sha256(Buffer.from(obj.message)); | ||
const vectorSig = new Signature({ | ||
r: new BN(obj.signature.r), | ||
s: new BN(obj.signature.s), | ||
i: obj.i | ||
}); | ||
const sig = ECDSA.sign(hashbuf, privkey); | ||
ECDSA.calci(hashbuf, sig, privkey.publicKey); | ||
const k = ECDSA.__testing__.getDeterministicK(hashbuf, privkey) | ||
k.toString('hex').should.equal(vectorK.toString('hex')); | ||
sig.toString().should.equal(vectorSig.toString()); | ||
sig.i.should.equal(obj.i); | ||
ECDSA.verify(hashbuf, sig, privkey.publicKey).should.equal(true); | ||
}); | ||
} | ||
vectors.invalid.sigError.forEach(function(obj, i) { | ||
it('should validate invalid.sigError vector ' + i + ': ' + obj.description, function() { | ||
var ecdsa = ECDSA().set({ | ||
pubkey: Pubkey.fromPoint(point.fromX(true, 1)), | ||
sig: new Signature(new BN(obj.signature.r), new BN(obj.signature.s)), | ||
hashbuf: Hash.sha256(Buffer.from(obj.message)) | ||
}); | ||
ecdsa.sigError().should.equal(obj.exception); | ||
}); | ||
for (const i in vectors.invalid.sigError) { | ||
const obj = vectors.invalid.sigError[i]; | ||
it('should validate invalid.sigError vector ' + i + ': ' + obj.description, function() { | ||
const pubkey = Pubkey.fromPoint(point.fromX(true, 1)); | ||
const sig = new Signature(new BN(obj.signature.r), new BN(obj.signature.s)); | ||
const hashbuf = Hash.sha256(Buffer.from(obj.message)); | ||
const error = ECDSA.verificationError(hashbuf, sig, pubkey); | ||
error.should.equal(obj.exception); | ||
}); | ||
} | ||
vectors.deterministicK.forEach(function(obj, i) { | ||
it('should validate deterministicK vector ' + i, function() { | ||
var hashbuf = Hash.sha256(Buffer.from(obj.message)); | ||
var privkey = Privkey(BN.fromBuffer(Buffer.from(obj.privkey, 'hex')), 'mainnet'); | ||
var ecdsa = ECDSA({ | ||
privkey: privkey, | ||
hashbuf: hashbuf | ||
}); | ||
ecdsa.deterministicK(0).k.toString('hex').should.equal(obj.k_bad00); | ||
ecdsa.deterministicK(1).k.toString('hex').should.equal(obj.k_bad01); | ||
ecdsa.deterministicK(15).k.toString('hex').should.equal(obj.k_bad15); | ||
}); | ||
for (const i in vectors.deterministicK) { | ||
const obj = vectors.deterministicK[i]; | ||
it('should validate deterministicK vector ' + i, function() { | ||
const hashbuf = Hash.sha256(Buffer.from(obj.message)); | ||
const privkey = new PrivateKey(new BN(obj.privkey, 16), 'mainnet'); | ||
ECDSA.__testing__.getDeterministicK(hashbuf, privkey, 0).toString('hex').should.equal(obj.k_bad00); | ||
ECDSA.__testing__.getDeterministicK(hashbuf, privkey, 1).toString('hex').should.equal(obj.k_bad01); | ||
ECDSA.__testing__.getDeterministicK(hashbuf, privkey, 15).toString('hex').should.equal(obj.k_bad15); | ||
}); | ||
} | ||
}); | ||
}); | ||
}); |
4326173
87953