New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

bitcore-lib-ltc

Package Overview
Dependencies
Maintainers
0
Versions
50
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

bitcore-lib-ltc - npm Package Compare versions

Comparing version 10.6.2 to 10.7.0

3

lib/crypto/bn.js

@@ -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);

396

lib/crypto/ecdsa.js
'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);
});
}
});
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc