Merge pull request #835 from maraoz/lint/tests
improve coverage and style for crypto/ folder
This commit is contained in:
commit
bf09710110
140
lib/crypto/bn.js
140
lib/crypto/bn.js
|
@ -1,6 +1,8 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var _BN = require('bn.js');
|
var _BN = require('bn.js');
|
||||||
|
var $ = require('../util/preconditions');
|
||||||
|
var _ = require('lodash');
|
||||||
|
|
||||||
var BN = function BN(n, base) {
|
var BN = function BN(n, base) {
|
||||||
if (!(this instanceof BN)) {
|
if (!(this instanceof BN)) {
|
||||||
|
@ -14,25 +16,23 @@ BN.prototype = _BN.prototype;
|
||||||
var reversebuf = function(buf) {
|
var reversebuf = function(buf) {
|
||||||
var buf2 = new Buffer(buf.length);
|
var buf2 = new Buffer(buf.length);
|
||||||
for (var i = 0; i < buf.length; i++) {
|
for (var i = 0; i < buf.length; i++) {
|
||||||
buf2[i] = buf[buf.length-1-i];
|
buf2[i] = buf[buf.length - 1 - i];
|
||||||
}
|
}
|
||||||
return buf2;
|
return buf2;
|
||||||
};
|
};
|
||||||
|
|
||||||
BN.prototype.fromNumber = function(n) {
|
BN.fromNumber = function(n) {
|
||||||
var bn = BN(n);
|
$.checkArgument(_.isNumber(n));
|
||||||
bn.copy(this);
|
return BN(n);
|
||||||
return this;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
BN.prototype.toNumber = function() {
|
BN.prototype.toNumber = function() {
|
||||||
return parseInt(this['toString'](10), 10);
|
return parseInt(this.toString(10), 10);
|
||||||
};
|
};
|
||||||
|
|
||||||
BN.prototype.fromString = function(str) {
|
BN.fromString = function(str) {
|
||||||
var bn = BN(str);
|
$.checkArgument(_.isString(str));
|
||||||
bn.copy(this);
|
return BN(str);
|
||||||
return this;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
BN.fromBuffer = function(buf, opts) {
|
BN.fromBuffer = function(buf, opts) {
|
||||||
|
@ -44,38 +44,37 @@ BN.fromBuffer = function(buf, opts) {
|
||||||
return bn;
|
return bn;
|
||||||
};
|
};
|
||||||
|
|
||||||
BN.prototype.fromBuffer = function(buf, opts) {
|
BN.trim = function(buf, natlen) {
|
||||||
var bn = BN.fromBuffer(buf, opts);
|
return buf.slice(natlen - buf.length, buf.length);
|
||||||
bn.copy(this);
|
};
|
||||||
|
|
||||||
return this;
|
BN.pad = function(buf, natlen, size) {
|
||||||
|
var rbuf = new Buffer(size);
|
||||||
|
for (var i = 0; i < buf.length; i++) {
|
||||||
|
rbuf[rbuf.length - 1 - i] = buf[buf.length - 1 - i];
|
||||||
|
}
|
||||||
|
for (i = 0; i < size - natlen; i++) {
|
||||||
|
rbuf[i] = 0;
|
||||||
|
}
|
||||||
|
return rbuf;
|
||||||
};
|
};
|
||||||
|
|
||||||
BN.prototype.toBuffer = function(opts) {
|
BN.prototype.toBuffer = function(opts) {
|
||||||
var buf;
|
var buf, hex;
|
||||||
if (opts && opts.size) {
|
if (opts && opts.size) {
|
||||||
var hex = this.toString(16, 2);
|
hex = this.toString(16, 2);
|
||||||
var natlen = hex.length/2;
|
var natlen = hex.length / 2;
|
||||||
buf = new Buffer(hex, 'hex');
|
buf = new Buffer(hex, 'hex');
|
||||||
|
|
||||||
if (natlen == opts.size)
|
if (natlen === opts.size) {
|
||||||
buf = buf;
|
buf = buf;
|
||||||
|
} else if (natlen > opts.size) {
|
||||||
else if (natlen > opts.size) {
|
buf = BN.trim(buf, natlen);
|
||||||
buf = buf.slice(natlen - buf.length, buf.length);
|
} else if (natlen < opts.size) {
|
||||||
|
buf = BN.pad(buf, natlen, opts.size);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
else if (natlen < opts.size) {
|
hex = this.toString(16, 2);
|
||||||
var rbuf = new Buffer(opts.size);
|
|
||||||
for (var i = 0; i < buf.length; i++)
|
|
||||||
rbuf[rbuf.length-1-i] = buf[buf.length-1-i];
|
|
||||||
for (var i = 0; i < opts.size - natlen; i++)
|
|
||||||
rbuf[i] = 0;
|
|
||||||
buf = rbuf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var hex = this.toString(16, 2);
|
|
||||||
buf = new Buffer(hex, 'hex');
|
buf = new Buffer(hex, 'hex');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,51 +87,58 @@ BN.prototype.toBuffer = function(opts) {
|
||||||
|
|
||||||
// signed magnitude buffer
|
// signed magnitude buffer
|
||||||
// most significant bit represents sign (0 = positive, -1 = negative)
|
// most significant bit represents sign (0 = positive, -1 = negative)
|
||||||
BN.prototype.fromSM = function(buf, opts) {
|
BN.fromSM = function(buf, opts) {
|
||||||
if (buf.length === 0)
|
var ret;
|
||||||
this.fromBuffer(new Buffer([0]));
|
if (buf.length === 0) {
|
||||||
|
return BN.fromBuffer(new Buffer([0]));
|
||||||
|
}
|
||||||
|
|
||||||
var endian = 'big';
|
var endian = 'big';
|
||||||
if (opts)
|
if (opts) {
|
||||||
endian = opts.endian;
|
endian = opts.endian;
|
||||||
|
}
|
||||||
if (endian == 'little')
|
if (endian === 'little') {
|
||||||
buf = reversebuf(buf);
|
buf = reversebuf(buf);
|
||||||
|
}
|
||||||
|
|
||||||
if (buf[0] & 0x80) {
|
if (buf[0] & 0x80) {
|
||||||
buf[0] = buf[0] & 0x7f;
|
buf[0] = buf[0] & 0x7f;
|
||||||
this.fromBuffer(buf);
|
ret = BN.fromBuffer(buf);
|
||||||
this.neg().copy(this);
|
ret.neg().copy(ret);
|
||||||
} else {
|
} else {
|
||||||
this.fromBuffer(buf);
|
ret = BN.fromBuffer(buf);
|
||||||
}
|
}
|
||||||
return this;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
BN.prototype.toSM = function(opts) {
|
BN.prototype.toSMBigEndian = function() {
|
||||||
var endian = 'big';
|
|
||||||
if (opts)
|
|
||||||
endian = opts.endian;
|
|
||||||
|
|
||||||
var buf;
|
var buf;
|
||||||
if (this.cmp(0) == -1) {
|
if (this.cmp(0) === -1) {
|
||||||
buf = this.neg().toBuffer();
|
buf = this.neg().toBuffer();
|
||||||
if (buf[0] & 0x80)
|
if (buf[0] & 0x80) {
|
||||||
buf = Buffer.concat([new Buffer([0x80]), buf]);
|
buf = Buffer.concat([new Buffer([0x80]), buf]);
|
||||||
else
|
} else {
|
||||||
buf[0] = buf[0] | 0x80;
|
buf[0] = buf[0] | 0x80;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
buf = this.toBuffer();
|
buf = this.toBuffer();
|
||||||
if (buf[0] & 0x80)
|
if (buf[0] & 0x80) {
|
||||||
buf = Buffer.concat([new Buffer([0x00]), buf]);
|
buf = Buffer.concat([new Buffer([0x00]), buf]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf.length === 1 & buf[0] === 0)
|
if (buf.length === 1 & buf[0] === 0) {
|
||||||
buf = new Buffer([]);
|
buf = new Buffer([]);
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
};
|
||||||
|
BN.prototype.toSM = function(opts) {
|
||||||
|
var endian = opts ? opts.endian : 'big';
|
||||||
|
var buf = this.toSMBigEndian();
|
||||||
|
|
||||||
if (endian == 'little')
|
if (endian === 'little') {
|
||||||
buf = reversebuf(buf);
|
buf = reversebuf(buf);
|
||||||
|
}
|
||||||
return buf;
|
return buf;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -140,10 +146,9 @@ BN.prototype.toSM = function(opts) {
|
||||||
// bitcoind's script interpreter use CScriptNum, which is not really a proper
|
// bitcoind's script interpreter use CScriptNum, which is not really a proper
|
||||||
// bignum. Instead, an error is thrown if trying to input a number bigger than
|
// bignum. Instead, an error is thrown if trying to input a number bigger than
|
||||||
// 4 bytes. We copy that behavior here.
|
// 4 bytes. We copy that behavior here.
|
||||||
BN.prototype.fromScriptNumBuffer = function(buf, fRequireMinimal) {
|
BN.fromScriptNumBuffer = function(buf, fRequireMinimal) {
|
||||||
var nMaxNumSize = 4;
|
var nMaxNumSize = 4;
|
||||||
if (buf.length > nMaxNumSize)
|
$.checkArgument(buf.length <= nMaxNumSize, new Error('script number overflow'));
|
||||||
throw new Error('script number overflow');
|
|
||||||
if (fRequireMinimal && buf.length > 0) {
|
if (fRequireMinimal && buf.length > 0) {
|
||||||
// Check that the number is encoded with the minimum possible
|
// Check that the number is encoded with the minimum possible
|
||||||
// number of bytes.
|
// number of bytes.
|
||||||
|
@ -158,28 +163,33 @@ BN.prototype.fromScriptNumBuffer = function(buf, fRequireMinimal) {
|
||||||
// is +-255, which encode to 0xff00 and 0xff80 respectively.
|
// is +-255, which encode to 0xff00 and 0xff80 respectively.
|
||||||
// (big-endian).
|
// (big-endian).
|
||||||
if (buf.length <= 1 || (buf[buf.length - 2] & 0x80) === 0) {
|
if (buf.length <= 1 || (buf[buf.length - 2] & 0x80) === 0) {
|
||||||
throw new Error("non-minimally encoded script number");
|
throw new Error('non-minimally encoded script number');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this.fromSM(buf, {endian: 'little'});
|
return BN.fromSM(buf, {
|
||||||
|
endian: 'little'
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// The corollary to the above, with the notable exception that we do not throw
|
// The corollary to the above, with the notable exception that we do not throw
|
||||||
// an error if the output is larger than four bytes. (Which can happen if
|
// an error if the output is larger than four bytes. (Which can happen if
|
||||||
// performing a numerical operation that results in an overflow to more than 4
|
// performing a numerical operation that results in an overflow to more than 4
|
||||||
// bytes).
|
// bytes).
|
||||||
BN.prototype.toScriptNumBuffer = function(buf) {
|
BN.prototype.toScriptNumBuffer = function() {
|
||||||
return this.toSM({endian: 'little'});
|
return this.toSM({
|
||||||
|
endian: 'little'
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
function decorate(name) {
|
var decorate = function decorate(name) {
|
||||||
BN.prototype['_' + name] = BN.prototype[name];
|
BN.prototype['_' + name] = BN.prototype[name];
|
||||||
var f = function(b) {
|
var f = function(b) {
|
||||||
if (typeof b === 'string')
|
if (typeof b === 'string') {
|
||||||
b = new BN(b);
|
b = new BN(b);
|
||||||
else if (typeof b === 'number')
|
} else if (typeof b === 'number') {
|
||||||
b = new BN(b.toString());
|
b = new BN(b.toString());
|
||||||
|
}
|
||||||
return this['_' + name](b);
|
return this['_' + name](b);
|
||||||
};
|
};
|
||||||
BN.prototype[name] = f;
|
BN.prototype[name] = f;
|
||||||
|
|
|
@ -4,9 +4,11 @@ var BN = require('./bn');
|
||||||
var Point = require('./point');
|
var Point = require('./point');
|
||||||
var Signature = require('./signature');
|
var Signature = require('./signature');
|
||||||
var PublicKey = require('../publickey');
|
var PublicKey = require('../publickey');
|
||||||
var PrivateKey = require('../privatekey');
|
|
||||||
var Random = require('./random');
|
var Random = require('./random');
|
||||||
var Hash = require('./hash');
|
var Hash = require('./hash');
|
||||||
|
var BufferUtil = require('../util/buffer');
|
||||||
|
var _ = require('lodash');
|
||||||
|
var $ = require('../util/preconditions');
|
||||||
|
|
||||||
var ECDSA = function ECDSA(obj) {
|
var ECDSA = function ECDSA(obj) {
|
||||||
if (!(this instanceof ECDSA)) {
|
if (!(this instanceof ECDSA)) {
|
||||||
|
@ -17,6 +19,7 @@ var ECDSA = function ECDSA(obj) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* jshint maxcomplexity: 9 */
|
||||||
ECDSA.prototype.set = function(obj) {
|
ECDSA.prototype.set = function(obj) {
|
||||||
this.hashbuf = obj.hashbuf || this.hashbuf;
|
this.hashbuf = obj.hashbuf || this.hashbuf;
|
||||||
this.endian = obj.endian || this.endian; //the endianness of hashbuf
|
this.endian = obj.endian || this.endian; //the endianness of hashbuf
|
||||||
|
@ -37,7 +40,7 @@ ECDSA.prototype.calci = function() {
|
||||||
this.sig.i = i;
|
this.sig.i = i;
|
||||||
var Qprime;
|
var Qprime;
|
||||||
try {
|
try {
|
||||||
Qprime = this.sig2pubkey();
|
Qprime = this.toPublicKey();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
continue;
|
continue;
|
||||||
|
@ -53,61 +56,48 @@ ECDSA.prototype.calci = function() {
|
||||||
throw new Error('Unable to find valid recovery factor');
|
throw new Error('Unable to find valid recovery factor');
|
||||||
};
|
};
|
||||||
|
|
||||||
ECDSA.prototype.fromString = function(str) {
|
ECDSA.fromString = function(str) {
|
||||||
var obj = JSON.parse(str);
|
var obj = JSON.parse(str);
|
||||||
if (obj.hashbuf) {
|
return new ECDSA(obj);
|
||||||
this.hashbuf = new Buffer(obj.hashbuf, 'hex');
|
|
||||||
}
|
|
||||||
if (obj.pubkey) {
|
|
||||||
this.pubkey = PublicKey.fromString(obj.pubkey);
|
|
||||||
}
|
|
||||||
if (obj.privkey) {
|
|
||||||
this.privkey = PrivateKey.fromString(obj.privkey);
|
|
||||||
}
|
|
||||||
if (obj.sig) {
|
|
||||||
this.sig = Signature.fromString(obj.sig);
|
|
||||||
}
|
|
||||||
if (obj.k) {
|
|
||||||
this.k = BN(obj.k, 10);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ECDSA.prototype.randomK = function() {
|
ECDSA.prototype.randomK = function() {
|
||||||
var N = Point.getN();
|
var N = Point.getN();
|
||||||
var k;
|
var k;
|
||||||
do {
|
do {
|
||||||
k = BN().fromBuffer(Random.getRandomBuffer(32));
|
k = BN.fromBuffer(Random.getRandomBuffer(32));
|
||||||
} while (!(k.lt(N) && k.gt(0)));
|
} while (!(k.lt(N) && k.gt(0)));
|
||||||
this.k = k;
|
this.k = k;
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// https://tools.ietf.org/html/rfc6979#section-3.2
|
// https://tools.ietf.org/html/rfc6979#section-3.2
|
||||||
ECDSA.prototype.deterministicK = function(badrs) {
|
ECDSA.prototype.deterministicK = function(badrs) {
|
||||||
|
/* jshint maxstatements: 25 */
|
||||||
|
if (_.isUndefined(badrs)) {
|
||||||
|
badrs = 0;
|
||||||
|
}
|
||||||
var v = new Buffer(32);
|
var v = new Buffer(32);
|
||||||
v.fill(0x01);
|
v.fill(0x01);
|
||||||
var k = new Buffer(32);
|
var k = new Buffer(32);
|
||||||
k.fill(0x00);
|
k.fill(0x00);
|
||||||
var x = this.privkey.bn.toBuffer({size: 32});
|
var x = this.privkey.bn.toBuffer({
|
||||||
|
size: 32
|
||||||
|
});
|
||||||
k = Hash.sha256hmac(Buffer.concat([v, new Buffer([0x00]), x, this.hashbuf]), k);
|
k = Hash.sha256hmac(Buffer.concat([v, new Buffer([0x00]), x, this.hashbuf]), k);
|
||||||
v = Hash.sha256hmac(v, k);
|
v = Hash.sha256hmac(v, k);
|
||||||
k = Hash.sha256hmac(Buffer.concat([v, new Buffer([0x01]), x, this.hashbuf]), k);
|
k = Hash.sha256hmac(Buffer.concat([v, new Buffer([0x01]), x, this.hashbuf]), k);
|
||||||
v = Hash.sha256hmac(v, k);
|
v = Hash.sha256hmac(v, k);
|
||||||
v = Hash.sha256hmac(v, k);
|
v = Hash.sha256hmac(v, k);
|
||||||
var T = BN().fromBuffer(v);
|
var T = BN.fromBuffer(v);
|
||||||
var N = Point.getN();
|
var N = Point.getN();
|
||||||
|
|
||||||
// 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 (typeof badrs === 'undefined')
|
|
||||||
badrs = 0;
|
|
||||||
// also explained in 3.2, we must ensure T is in the proper range (0, N)
|
// 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(0)); i++) {
|
for (var i = 0; i < badrs || !(T.lt(N) && T.gt(0)); i++) {
|
||||||
k = Hash.sha256hmac(Buffer.concat([v, new Buffer([0x00])]), k);
|
k = Hash.sha256hmac(Buffer.concat([v, new Buffer([0x00])]), k);
|
||||||
v = Hash.sha256hmac(v, k);
|
v = Hash.sha256hmac(v, k);
|
||||||
T = BN().fromBuffer(v);
|
T = BN.fromBuffer(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.k = T;
|
this.k = T;
|
||||||
|
@ -117,12 +107,12 @@ ECDSA.prototype.deterministicK = function(badrs) {
|
||||||
// Information about public key recovery:
|
// Information about public key recovery:
|
||||||
// https://bitcointalk.org/index.php?topic=6430.0
|
// 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
|
// 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.sig2pubkey = function() {
|
ECDSA.prototype.toPublicKey = function() {
|
||||||
|
/* jshint maxstatements: 25 */
|
||||||
var i = this.sig.i;
|
var i = this.sig.i;
|
||||||
if (!(i === 0 || i === 1 || i === 2 || i === 3))
|
$.checkArgument(i === 0 || i === 1 || i === 2 || i === 3, new Error('i must be equal to 0, 1, 2, or 3'));
|
||||||
throw new Error('i must be equal to 0, 1, 2, or 3');
|
|
||||||
|
|
||||||
var e = BN().fromBuffer(this.hashbuf);
|
var e = BN.fromBuffer(this.hashbuf);
|
||||||
var r = this.sig.r;
|
var r = this.sig.r;
|
||||||
var s = this.sig.s;
|
var s = this.sig.s;
|
||||||
|
|
||||||
|
@ -143,8 +133,9 @@ ECDSA.prototype.sig2pubkey = function() {
|
||||||
// 1.4 Check that nR is at infinity
|
// 1.4 Check that nR is at infinity
|
||||||
var nR = R.mul(n);
|
var nR = R.mul(n);
|
||||||
|
|
||||||
if (!nR.isInfinity())
|
if (!nR.isInfinity()) {
|
||||||
throw new Error('nR is not a valid curve point');
|
throw new Error('nR is not a valid curve point');
|
||||||
|
}
|
||||||
|
|
||||||
// Compute -e from e
|
// Compute -e from e
|
||||||
var eNeg = e.neg().mod(n);
|
var eNeg = e.neg().mod(n);
|
||||||
|
@ -162,67 +153,87 @@ ECDSA.prototype.sig2pubkey = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
ECDSA.prototype.sigError = function() {
|
ECDSA.prototype.sigError = function() {
|
||||||
if (!Buffer.isBuffer(this.hashbuf) || this.hashbuf.length !== 32) {
|
/* jshint maxstatements: 25 */
|
||||||
|
if (!BufferUtil.isBuffer(this.hashbuf) || this.hashbuf.length !== 32) {
|
||||||
return 'hashbuf must be a 32 byte buffer';
|
return 'hashbuf must be a 32 byte buffer';
|
||||||
}
|
}
|
||||||
|
|
||||||
var r = this.sig.r;
|
var r = this.sig.r;
|
||||||
var s = this.sig.s;
|
var s = this.sig.s;
|
||||||
if (!(r.gt(0) && r.lt(Point.getN()))
|
if (!(r.gt(0) && r.lt(Point.getN())) || !(s.gt(0) && s.lt(Point.getN()))) {
|
||||||
|| !(s.gt(0) && s.lt(Point.getN())))
|
|
||||||
return 'r and s not in range';
|
return 'r and s not in range';
|
||||||
|
}
|
||||||
|
|
||||||
var e = BN().fromBuffer(this.hashbuf, this.endian ? {endian: this.endian} : undefined);
|
var e = BN.fromBuffer(this.hashbuf, this.endian ? {
|
||||||
|
endian: this.endian
|
||||||
|
} : undefined);
|
||||||
var n = Point.getN();
|
var n = Point.getN();
|
||||||
var sinv = s.invm(n);
|
var sinv = s.invm(n);
|
||||||
var u1 = sinv.mul(e).mod(n);
|
var u1 = sinv.mul(e).mod(n);
|
||||||
var u2 = sinv.mul(r).mod(n);
|
var u2 = sinv.mul(r).mod(n);
|
||||||
|
|
||||||
var p = Point.getG().mulAdd(u1, this.pubkey.point, u2);
|
var p = Point.getG().mulAdd(u1, this.pubkey.point, u2);
|
||||||
if (p.isInfinity())
|
if (p.isInfinity()) {
|
||||||
return 'p is infinity';
|
return 'p is infinity';
|
||||||
|
}
|
||||||
|
|
||||||
if (!(p.getX().mod(n).cmp(r) === 0))
|
if (p.getX().mod(n).cmp(r) !== 0) {
|
||||||
return 'Invalid signature';
|
return 'Invalid signature';
|
||||||
else
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ECDSA.toLowS = function(s) {
|
||||||
|
//enforce low s
|
||||||
|
//see BIP 62, "low S values in signatures"
|
||||||
|
if (s.gt(BN.fromBuffer(new Buffer('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0', 'hex')))) {
|
||||||
|
s = Point.getN().sub(s);
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
};
|
||||||
|
|
||||||
|
ECDSA.prototype._findSignature = function(d, e) {
|
||||||
|
var N = Point.getN();
|
||||||
|
var G = Point.getG();
|
||||||
|
// try different values of k until r, s are valid
|
||||||
|
var badrs = 0;
|
||||||
|
var k, Q, r, s;
|
||||||
|
do {
|
||||||
|
if (!this.k || badrs > 0) {
|
||||||
|
this.deterministicK(badrs);
|
||||||
|
}
|
||||||
|
badrs++;
|
||||||
|
k = this.k;
|
||||||
|
Q = G.mul(k);
|
||||||
|
r = Q.x.mod(N);
|
||||||
|
s = k.invm(N).mul(e.add(d.mul(r))).mod(N);
|
||||||
|
} while (r.cmp(0) <= 0 || s.cmp(0) <= 0);
|
||||||
|
|
||||||
|
s = ECDSA.toLowS(s);
|
||||||
|
return {
|
||||||
|
s: s,
|
||||||
|
r: r
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ECDSA.prototype.sign = function() {
|
ECDSA.prototype.sign = function() {
|
||||||
var hashbuf = this.hashbuf;
|
var hashbuf = this.hashbuf;
|
||||||
var privkey = this.privkey;
|
var privkey = this.privkey;
|
||||||
|
|
||||||
var d = privkey.bn;
|
var d = privkey.bn;
|
||||||
|
|
||||||
if (!hashbuf || !privkey || !d)
|
$.checkState(hashbuf && privkey && d, new Error('invalid parameters'));
|
||||||
throw new Error('invalid parameters');
|
$.checkState(BufferUtil.isBuffer(hashbuf) && hashbuf.length === 32, new Error('hashbuf must be a 32 byte buffer'));
|
||||||
|
|
||||||
if (!Buffer.isBuffer(hashbuf) || hashbuf.length !== 32)
|
var e = BN.fromBuffer(hashbuf, this.endian ? {
|
||||||
throw new Error('hashbuf must be a 32 byte buffer');
|
endian: this.endian
|
||||||
|
} : undefined);
|
||||||
|
|
||||||
var N = Point.getN();
|
var obj = this._findSignature(d, e);
|
||||||
var G = Point.getG();
|
obj.compressed = this.pubkey.compressed;
|
||||||
var e = BN().fromBuffer(hashbuf, this.endian ? {endian: this.endian} : undefined);
|
|
||||||
|
|
||||||
// try different values of k until r, s are valid
|
this.sig = new Signature(obj);
|
||||||
var badrs = 0;
|
|
||||||
do {
|
|
||||||
if (!this.k || badrs > 0)
|
|
||||||
this.deterministicK(badrs);
|
|
||||||
badrs++;
|
|
||||||
var k = this.k;
|
|
||||||
var Q = G.mul(k);
|
|
||||||
var r = Q.x.mod(N);
|
|
||||||
var s = k.invm(N).mul(e.add(d.mul(r))).mod(N);
|
|
||||||
} while (r.cmp(0) <= 0 || s.cmp(0) <= 0);
|
|
||||||
|
|
||||||
//enforce low s
|
|
||||||
//see BIP 62, "low S values in signatures"
|
|
||||||
if (s.gt(BN().fromBuffer(new Buffer('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0', 'hex')))) {
|
|
||||||
s = Point.getN().sub(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.sig = new Signature({r: r, s: s, compressed: this.pubkey.compressed});
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -252,10 +263,11 @@ ECDSA.prototype.toString = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
ECDSA.prototype.verify = function() {
|
ECDSA.prototype.verify = function() {
|
||||||
if (!this.sigError())
|
if (!this.sigError()) {
|
||||||
this.verified = true;
|
this.verified = true;
|
||||||
else
|
} else {
|
||||||
this.verified = false;
|
this.verified = false;
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var BN = require('./bn');
|
var BN = require('./bn');
|
||||||
|
var _ = require('lodash');
|
||||||
|
var $ = require('../util/preconditions');
|
||||||
|
var BufferUtil = require('../util/buffer');
|
||||||
|
|
||||||
var Signature = function Signature(r, s) {
|
var Signature = function Signature(r, s) {
|
||||||
if (!(this instanceof Signature))
|
if (!(this instanceof Signature)) {
|
||||||
return new Signature(r, s);
|
return new Signature(r, s);
|
||||||
|
}
|
||||||
if (r instanceof BN) {
|
if (r instanceof BN) {
|
||||||
this.set({
|
this.set({
|
||||||
r: r,
|
r: r,
|
||||||
|
@ -16,37 +20,32 @@ var Signature = function Signature(r, s) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* jshint maxcomplexity: 7 */
|
||||||
Signature.prototype.set = function(obj) {
|
Signature.prototype.set = function(obj) {
|
||||||
this.r = obj.r || this.r || undefined;
|
this.r = obj.r || this.r || undefined;
|
||||||
this.s = obj.s || this.s || undefined;
|
this.s = obj.s || this.s || undefined;
|
||||||
this.i = typeof obj.i !== 'undefined' ? obj.i : this.i; //public key recovery parameter in range [0, 3]
|
this.i = typeof obj.i !== 'undefined' ? obj.i : this.i; //public key recovery parameter in range [0, 3]
|
||||||
this.compressed = typeof obj.compressed !== 'undefined' ? obj.compressed : this.compressed; //whether the recovered pubkey is compressed
|
this.compressed = typeof obj.compressed !== 'undefined' ?
|
||||||
|
obj.compressed : this.compressed; //whether the recovered pubkey is compressed
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
Signature.fromCompact = function(buf) {
|
Signature.fromCompact = function(buf) {
|
||||||
var sig = new Signature();
|
var sig = new Signature();
|
||||||
|
//TODO: handle uncompressed pubkeys
|
||||||
var compressed = true;
|
var compressed = true;
|
||||||
var i = buf.slice(0, 1)[0] - 27 - 4;
|
var i = buf.slice(0, 1)[0] - 27 - 4;
|
||||||
//TODO: handle uncompressed pubkeys
|
|
||||||
|
|
||||||
var b2 = buf.slice(1, 33);
|
var b2 = buf.slice(1, 33);
|
||||||
var b3 = buf.slice(33, 65);
|
var b3 = buf.slice(33, 65);
|
||||||
|
|
||||||
if (!(i === 0 || i === 1 || i === 2 || i === 3)) {
|
$.checkArgument(i === 0 || i === 1 || i === 2 || i === 3, new Error('i must be 0, 1, 2, or 3'));
|
||||||
throw new Error('i must be 0, 1, 2, or 3');
|
$.checkArgument(b2.length === 32, new Error('r must be 32 bytes'));
|
||||||
}
|
$.checkArgument(b3.length === 32, new Error('s must be 32 bytes'));
|
||||||
if (b2.length !== 32) {
|
|
||||||
throw new Error('r must be 32 bytes');
|
|
||||||
}
|
|
||||||
if (b3.length !== 32) {
|
|
||||||
throw new Error('s must be 32 bytes');
|
|
||||||
}
|
|
||||||
|
|
||||||
sig.compressed = compressed;
|
sig.compressed = compressed;
|
||||||
sig.i = i;
|
sig.i = i;
|
||||||
sig.r = BN().fromBuffer(b2);
|
sig.r = BN.fromBuffer(b2);
|
||||||
sig.s = BN().fromBuffer(b3);
|
sig.s = BN.fromBuffer(b3);
|
||||||
|
|
||||||
return sig;
|
return sig;
|
||||||
};
|
};
|
||||||
|
@ -80,58 +79,40 @@ Signature.fromString = function(str) {
|
||||||
* In order to mimic the non-strict DER encoding of OpenSSL, set strict = false.
|
* In order to mimic the non-strict DER encoding of OpenSSL, set strict = false.
|
||||||
*/
|
*/
|
||||||
Signature.parseDER = function(buf, strict) {
|
Signature.parseDER = function(buf, strict) {
|
||||||
if (typeof strict === 'undefined') {
|
$.checkArgument(BufferUtil.isBuffer(buf), new Error('DER formatted signature should be a buffer'));
|
||||||
|
if (_.isUndefined(strict)) {
|
||||||
strict = true;
|
strict = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Buffer.isBuffer(buf)) {
|
|
||||||
throw new Error('DER formatted signature should be a buffer');
|
|
||||||
}
|
|
||||||
|
|
||||||
var header = buf[0];
|
var header = buf[0];
|
||||||
|
$.checkArgument(header === 0x30, new Error('Header byte should be 0x30'));
|
||||||
if (header !== 0x30) {
|
|
||||||
throw new Error('Header byte should be 0x30');
|
|
||||||
}
|
|
||||||
|
|
||||||
var length = buf[1];
|
var length = buf[1];
|
||||||
var buflength = buf.slice(2).length;
|
var buflength = buf.slice(2).length;
|
||||||
if (strict && length !== buflength) {
|
$.checkArgument(!strict || length === buflength, new Error('Length byte should length of what follows'));
|
||||||
throw new Error('Length byte should length of what follows');
|
|
||||||
} else {
|
length = length < buflength ? length : buflength;
|
||||||
length = length < buflength ? length : buflength;
|
|
||||||
}
|
|
||||||
|
|
||||||
var rheader = buf[2 + 0];
|
var rheader = buf[2 + 0];
|
||||||
if (rheader !== 0x02) {
|
$.checkArgument(rheader === 0x02, new Error('Integer byte for r should be 0x02'));
|
||||||
throw new Error('Integer byte for r should be 0x02');
|
|
||||||
}
|
|
||||||
|
|
||||||
var rlength = buf[2 + 1];
|
var rlength = buf[2 + 1];
|
||||||
var rbuf = buf.slice(2 + 2, 2 + 2 + rlength);
|
var rbuf = buf.slice(2 + 2, 2 + 2 + rlength);
|
||||||
var r = BN().fromBuffer(rbuf);
|
var r = BN.fromBuffer(rbuf);
|
||||||
var rneg = buf[2 + 1 + 1] === 0x00 ? true : false;
|
var rneg = buf[2 + 1 + 1] === 0x00 ? true : false;
|
||||||
if (rlength !== rbuf.length) {
|
$.checkArgument(rlength === rbuf.length, new Error('Length of r incorrect'));
|
||||||
throw new Error('Length of r incorrect');
|
|
||||||
}
|
|
||||||
|
|
||||||
var sheader = buf[2 + 2 + rlength + 0];
|
var sheader = buf[2 + 2 + rlength + 0];
|
||||||
if (sheader !== 0x02) {
|
$.checkArgument(sheader === 0x02, new Error('Integer byte for s should be 0x02'));
|
||||||
throw new Error('Integer byte for s should be 0x02');
|
|
||||||
}
|
|
||||||
|
|
||||||
var slength = buf[2 + 2 + rlength + 1];
|
var slength = buf[2 + 2 + rlength + 1];
|
||||||
var sbuf = buf.slice(2 + 2 + rlength + 2, 2 + 2 + rlength + 2 + slength);
|
var sbuf = buf.slice(2 + 2 + rlength + 2, 2 + 2 + rlength + 2 + slength);
|
||||||
var s = BN().fromBuffer(sbuf);
|
var s = BN.fromBuffer(sbuf);
|
||||||
var sneg = buf[2 + 2 + rlength + 2 + 2] === 0x00 ? true : false;
|
var sneg = buf[2 + 2 + rlength + 2 + 2] === 0x00 ? true : false;
|
||||||
if (slength !== sbuf.length) {
|
$.checkArgument(slength === sbuf.length, new Error('Length of s incorrect'));
|
||||||
throw new Error('Length of s incorrect');
|
|
||||||
}
|
|
||||||
|
|
||||||
var sumlength = 2 + 2 + rlength + 2 + slength;
|
var sumlength = 2 + 2 + rlength + 2 + slength;
|
||||||
if (length !== sumlength - 2) {
|
$.checkArgument(length === sumlength - 2, new Error('Length of signature incorrect'));
|
||||||
throw new Error('Length of signature incorrect');
|
|
||||||
}
|
|
||||||
|
|
||||||
var obj = {
|
var obj = {
|
||||||
header: header,
|
header: header,
|
||||||
|
|
|
@ -73,7 +73,7 @@ BufferReader.prototype.readUInt32LE = function() {
|
||||||
|
|
||||||
BufferReader.prototype.readUInt64BEBN = function() {
|
BufferReader.prototype.readUInt64BEBN = function() {
|
||||||
var buf = this.buf.slice(this.pos, this.pos + 8);
|
var buf = this.buf.slice(this.pos, this.pos + 8);
|
||||||
var bn = BN().fromBuffer(buf);
|
var bn = BN.fromBuffer(buf);
|
||||||
this.pos = this.pos + 8;
|
this.pos = this.pos + 8;
|
||||||
return bn;
|
return bn;
|
||||||
};
|
};
|
||||||
|
@ -81,7 +81,7 @@ BufferReader.prototype.readUInt64BEBN = function() {
|
||||||
BufferReader.prototype.readUInt64LEBN = function() {
|
BufferReader.prototype.readUInt64LEBN = function() {
|
||||||
var buf = this.buf.slice(this.pos, this.pos + 8);
|
var buf = this.buf.slice(this.pos, this.pos + 8);
|
||||||
var reversebuf = BufferReader({buf: buf}).readReverse();
|
var reversebuf = BufferReader({buf: buf}).readReverse();
|
||||||
var bn = BN().fromBuffer(reversebuf);
|
var bn = BN.fromBuffer(reversebuf);
|
||||||
this.pos = this.pos + 8;
|
this.pos = this.pos + 8;
|
||||||
return bn;
|
return bn;
|
||||||
};
|
};
|
||||||
|
|
|
@ -117,7 +117,7 @@ HDPrivateKey.prototype._deriveWithNumber = function(index, hardened) {
|
||||||
data = BufferUtil.concat([this.publicKey.toBuffer(), indexBuffer]);
|
data = BufferUtil.concat([this.publicKey.toBuffer(), indexBuffer]);
|
||||||
}
|
}
|
||||||
var hash = Hash.sha512hmac(data, this._buffers.chainCode);
|
var hash = Hash.sha512hmac(data, this._buffers.chainCode);
|
||||||
var leftPart = BN().fromBuffer(hash.slice(0, 32), {size: 32});
|
var leftPart = BN.fromBuffer(hash.slice(0, 32), {size: 32});
|
||||||
var chainCode = hash.slice(32, 64);
|
var chainCode = hash.slice(32, 64);
|
||||||
|
|
||||||
var privateKey = leftPart.add(this.privateKey.toBigNumber()).mod(Point.getN()).toBuffer({size: 32});
|
var privateKey = leftPart.add(this.privateKey.toBigNumber()).mod(Point.getN()).toBuffer({size: 32});
|
||||||
|
@ -334,7 +334,7 @@ HDPrivateKey.prototype._buildFromBuffers = function(arg) {
|
||||||
xprivkey = arg.xprivkey;
|
xprivkey = arg.xprivkey;
|
||||||
}
|
}
|
||||||
|
|
||||||
var privateKey = new PrivateKey(BN().fromBuffer(arg.privateKey));
|
var privateKey = new PrivateKey(BN.fromBuffer(arg.privateKey));
|
||||||
var publicKey = privateKey.toPublicKey();
|
var publicKey = privateKey.toPublicKey();
|
||||||
var size = HDPrivateKey.ParentFingerPrintSize;
|
var size = HDPrivateKey.ParentFingerPrintSize;
|
||||||
var fingerPrint = Hash.sha256ripemd160(publicKey.toBuffer()).slice(0, size);
|
var fingerPrint = Hash.sha256ripemd160(publicKey.toBuffer()).slice(0, size);
|
||||||
|
|
|
@ -110,7 +110,7 @@ HDPublicKey.prototype._deriveWithNumber = function (index, hardened) {
|
||||||
var indexBuffer = BufferUtil.integerAsBuffer(index);
|
var indexBuffer = BufferUtil.integerAsBuffer(index);
|
||||||
var data = BufferUtil.concat([this.publicKey.toBuffer(), indexBuffer]);
|
var data = BufferUtil.concat([this.publicKey.toBuffer(), indexBuffer]);
|
||||||
var hash = Hash.sha512hmac(data, this._buffers.chainCode);
|
var hash = Hash.sha512hmac(data, this._buffers.chainCode);
|
||||||
var leftPart = BN().fromBuffer(hash.slice(0, 32), {size: 32});
|
var leftPart = BN.fromBuffer(hash.slice(0, 32), {size: 32});
|
||||||
var chainCode = hash.slice(32, 64);
|
var chainCode = hash.slice(32, 64);
|
||||||
|
|
||||||
var publicKey = PublicKey.fromPoint(Point.getG().mul(leftPart).add(this.publicKey.point));
|
var publicKey = PublicKey.fromPoint(Point.getG().mul(leftPart).add(this.publicKey.point));
|
||||||
|
@ -219,7 +219,7 @@ HDPublicKey.prototype._buildFromJSON = function (arg) {
|
||||||
|
|
||||||
HDPublicKey.prototype._buildFromPrivate = function (arg) {
|
HDPublicKey.prototype._buildFromPrivate = function (arg) {
|
||||||
var args = _.clone(arg._buffers);
|
var args = _.clone(arg._buffers);
|
||||||
var point = Point.getG().mul(BN().fromBuffer(args.privateKey));
|
var point = Point.getG().mul(BN.fromBuffer(args.privateKey));
|
||||||
args.publicKey = Point.pointToCompressed(point);
|
args.publicKey = Point.pointToCompressed(point);
|
||||||
args.version = BufferUtil.integerAsBuffer(Network.get(BufferUtil.integerFromBuffer(args.version)).xpubkey);
|
args.version = BufferUtil.integerAsBuffer(Network.get(BufferUtil.integerFromBuffer(args.version)).xpubkey);
|
||||||
args.privateKey = undefined;
|
args.privateKey = undefined;
|
||||||
|
|
|
@ -128,7 +128,7 @@ PrivateKey._getRandomBN = function(){
|
||||||
var bn;
|
var bn;
|
||||||
do {
|
do {
|
||||||
var privbuf = Random.getRandomBuffer(32);
|
var privbuf = Random.getRandomBuffer(32);
|
||||||
bn = BN().fromBuffer(privbuf);
|
bn = BN.fromBuffer(privbuf);
|
||||||
condition = bn.lt(Point.getN());
|
condition = bn.lt(Point.getN());
|
||||||
} while (!condition);
|
} while (!condition);
|
||||||
return bn;
|
return bn;
|
||||||
|
|
|
@ -682,7 +682,7 @@ Interpreter.prototype.step = function() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
buf = this.stack[this.stack.length - 1];
|
buf = this.stack[this.stack.length - 1];
|
||||||
bn = BN().fromScriptNumBuffer(buf, fRequireMinimal);
|
bn = BN.fromScriptNumBuffer(buf, fRequireMinimal);
|
||||||
n = bn.toNumber();
|
n = bn.toNumber();
|
||||||
this.stack.pop();
|
this.stack.pop();
|
||||||
if (n < 0 || n >= this.stack.length) {
|
if (n < 0 || n >= this.stack.length) {
|
||||||
|
@ -769,11 +769,6 @@ Interpreter.prototype.step = function() {
|
||||||
buf1 = this.stack[this.stack.length - 2];
|
buf1 = this.stack[this.stack.length - 2];
|
||||||
buf2 = this.stack[this.stack.length - 1];
|
buf2 = this.stack[this.stack.length - 1];
|
||||||
var fEqual = buf1.toString('hex') === buf2.toString('hex');
|
var fEqual = buf1.toString('hex') === buf2.toString('hex');
|
||||||
// Opcode.OP_NOTEQUAL is disabled because it would be too easy to say
|
|
||||||
// something like n != 1 and have some wiseguy pass in 1 with extra
|
|
||||||
// zero bytes after it (numerically, 0x01 == 0x0001 == 0x000001)
|
|
||||||
//if (opcode == Opcode.OP_NOTEQUAL)
|
|
||||||
// fEqual = !fEqual;
|
|
||||||
this.stack.pop();
|
this.stack.pop();
|
||||||
this.stack.pop();
|
this.stack.pop();
|
||||||
this.stack.push(fEqual ? Interpreter.true : Interpreter.false);
|
this.stack.push(fEqual ? Interpreter.true : Interpreter.false);
|
||||||
|
@ -805,7 +800,7 @@ Interpreter.prototype.step = function() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
buf = this.stack[this.stack.length - 1];
|
buf = this.stack[this.stack.length - 1];
|
||||||
bn = BN().fromScriptNumBuffer(buf, fRequireMinimal);
|
bn = BN.fromScriptNumBuffer(buf, fRequireMinimal);
|
||||||
switch (opcodenum) {
|
switch (opcodenum) {
|
||||||
case Opcode.OP_1ADD:
|
case Opcode.OP_1ADD:
|
||||||
bn = bn.add(1);
|
bn = bn.add(1);
|
||||||
|
@ -853,8 +848,8 @@ Interpreter.prototype.step = function() {
|
||||||
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bn1 = BN().fromScriptNumBuffer(this.stack[this.stack.length - 2], fRequireMinimal);
|
bn1 = BN.fromScriptNumBuffer(this.stack[this.stack.length - 2], fRequireMinimal);
|
||||||
bn2 = BN().fromScriptNumBuffer(this.stack[this.stack.length - 1], fRequireMinimal);
|
bn2 = BN.fromScriptNumBuffer(this.stack[this.stack.length - 1], fRequireMinimal);
|
||||||
bn = BN(0);
|
bn = BN(0);
|
||||||
|
|
||||||
switch (opcodenum) {
|
switch (opcodenum) {
|
||||||
|
@ -933,9 +928,9 @@ Interpreter.prototype.step = function() {
|
||||||
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bn1 = BN().fromScriptNumBuffer(this.stack[this.stack.length - 3], fRequireMinimal);
|
bn1 = BN.fromScriptNumBuffer(this.stack[this.stack.length - 3], fRequireMinimal);
|
||||||
bn2 = BN().fromScriptNumBuffer(this.stack[this.stack.length - 2], fRequireMinimal);
|
bn2 = BN.fromScriptNumBuffer(this.stack[this.stack.length - 2], fRequireMinimal);
|
||||||
var bn3 = BN().fromScriptNumBuffer(this.stack[this.stack.length - 1], fRequireMinimal);
|
var bn3 = BN.fromScriptNumBuffer(this.stack[this.stack.length - 1], fRequireMinimal);
|
||||||
//bool fValue = (bn2 <= bn1 && bn1 < bn3);
|
//bool fValue = (bn2 <= bn1 && bn1 < bn3);
|
||||||
fValue = (bn2.cmp(bn1) <= 0) && (bn1.cmp(bn3) < 0);
|
fValue = (bn2.cmp(bn1) <= 0) && (bn1.cmp(bn3) < 0);
|
||||||
this.stack.pop();
|
this.stack.pop();
|
||||||
|
@ -1048,7 +1043,7 @@ Interpreter.prototype.step = function() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var nKeysCount = BN().fromScriptNumBuffer(this.stack[this.stack.length - i], fRequireMinimal).toNumber();
|
var nKeysCount = BN.fromScriptNumBuffer(this.stack[this.stack.length - i], fRequireMinimal).toNumber();
|
||||||
if (nKeysCount < 0 || nKeysCount > 20) {
|
if (nKeysCount < 0 || nKeysCount > 20) {
|
||||||
this.errstr = 'SCRIPT_ERR_PUBKEY_COUNT';
|
this.errstr = 'SCRIPT_ERR_PUBKEY_COUNT';
|
||||||
return false;
|
return false;
|
||||||
|
@ -1066,7 +1061,7 @@ Interpreter.prototype.step = function() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var nSigsCount = BN().fromScriptNumBuffer(this.stack[this.stack.length - i], fRequireMinimal).toNumber();
|
var nSigsCount = BN.fromScriptNumBuffer(this.stack[this.stack.length - i], fRequireMinimal).toNumber();
|
||||||
if (nSigsCount < 0 || nSigsCount > nKeysCount) {
|
if (nSigsCount < 0 || nSigsCount > nKeysCount) {
|
||||||
this.errstr = 'SCRIPT_ERR_SIG_COUNT';
|
this.errstr = 'SCRIPT_ERR_SIG_COUNT';
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -38,7 +38,7 @@ Object.defineProperty(Output.prototype, 'satoshis', {
|
||||||
if (num instanceof BN) {
|
if (num instanceof BN) {
|
||||||
this._satoshis = num;
|
this._satoshis = num;
|
||||||
} else {
|
} else {
|
||||||
this._satoshis = BN().fromNumber(num);
|
this._satoshis = BN.fromNumber(num);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -73,7 +73,7 @@ var sighash = function sighash(transaction, sighashType, inputNumber, subscript)
|
||||||
|
|
||||||
for (i = 0; i < inputNumber; i++) {
|
for (i = 0; i < inputNumber; i++) {
|
||||||
txcopy.outputs[i] = new Output({
|
txcopy.outputs[i] = new Output({
|
||||||
satoshis: BN().fromBuffer(new buffer.Buffer(BITS_64_ON, 'hex')),
|
satoshis: BN.fromBuffer(new buffer.Buffer(BITS_64_ON, 'hex')),
|
||||||
script: Script.empty()
|
script: Script.empty()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ var sighash = function sighash(transaction, sighashType, inputNumber, subscript)
|
||||||
txcopy.inputs = [txcopy.inputs[inputNumber]];
|
txcopy.inputs = [txcopy.inputs[inputNumber]];
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf = BufferWriter()
|
var buf = new BufferWriter()
|
||||||
.write(txcopy.toBuffer())
|
.write(txcopy.toBuffer())
|
||||||
.writeInt32LE(sighashType)
|
.writeInt32LE(sighashType)
|
||||||
.toBuffer();
|
.toBuffer();
|
||||||
|
|
|
@ -67,45 +67,47 @@ describe('BN', function() {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#fromString', function() {
|
describe('to/from ScriptNumBuffer', function() {
|
||||||
|
[0, 1, 10, 256, 1000, 65536, 65537, -1, -1000, -65536, -65537].forEach(function(n) {
|
||||||
it('should make BN from a string', function() {
|
it('rountrips correctly for ' + n, function() {
|
||||||
BN().fromString('5').toString().should.equal('5');
|
BN.fromScriptNumBuffer(BN(n).toScriptNumBuffer()).toNumber().should.equal(n);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#fromString', function() {
|
||||||
|
it('should make BN from a string', function() {
|
||||||
|
BN.fromString('5').toString().should.equal('5');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#toString', function() {
|
describe('#toString', function() {
|
||||||
|
|
||||||
it('should make a string', function() {
|
it('should make a string', function() {
|
||||||
BN(5).toString().should.equal('5');
|
BN(5).toString().should.equal('5');
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('@fromBuffer', function() {
|
describe('@fromBuffer', function() {
|
||||||
|
|
||||||
it('should work with big endian', function() {
|
it('should work with big endian', function() {
|
||||||
var bn = BN.fromBuffer(new Buffer('0001', 'hex'), {endian: 'big'});
|
var bn = BN.fromBuffer(new Buffer('0001', 'hex'), {
|
||||||
|
endian: 'big'
|
||||||
|
});
|
||||||
bn.toString().should.equal('1');
|
bn.toString().should.equal('1');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should work with big endian 256', function() {
|
it('should work with big endian 256', function() {
|
||||||
var bn = BN.fromBuffer(new Buffer('0100', 'hex'), {endian: 'big'});
|
var bn = BN.fromBuffer(new Buffer('0100', 'hex'), {
|
||||||
|
endian: 'big'
|
||||||
|
});
|
||||||
bn.toString().should.equal('256');
|
bn.toString().should.equal('256');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should work with little endian if we specify the size', function() {
|
it('should work with little endian if we specify the size', function() {
|
||||||
var bn = BN.fromBuffer(new Buffer('0100', 'hex'), {size: 2, endian: 'little'});
|
var bn = BN.fromBuffer(new Buffer('0100', 'hex'), {
|
||||||
bn.toString().should.equal('1');
|
size: 2,
|
||||||
});
|
endian: 'little'
|
||||||
|
});
|
||||||
});
|
|
||||||
|
|
||||||
describe('#fromBuffer', function() {
|
|
||||||
|
|
||||||
it('should work as a prototype method', function() {
|
|
||||||
var bn = BN().fromBuffer(new Buffer('0100', 'hex'), {size: 2, endian: 'little'});
|
|
||||||
bn.toString().should.equal('1');
|
bn.toString().should.equal('1');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -115,22 +117,31 @@ describe('BN', function() {
|
||||||
|
|
||||||
it('should create a 4 byte buffer', function() {
|
it('should create a 4 byte buffer', function() {
|
||||||
var bn = new BN(1);
|
var bn = new BN(1);
|
||||||
bn.toBuffer({size: 4}).toString('hex').should.equal('00000001');
|
bn.toBuffer({
|
||||||
|
size: 4
|
||||||
|
}).toString('hex').should.equal('00000001');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create a 4 byte buffer in little endian', function() {
|
it('should create a 4 byte buffer in little endian', function() {
|
||||||
var bn = new BN(1);
|
var bn = new BN(1);
|
||||||
bn.toBuffer({size: 4, endian: 'little'}).toString('hex').should.equal('01000000');
|
bn.toBuffer({
|
||||||
|
size: 4,
|
||||||
|
endian: 'little'
|
||||||
|
}).toString('hex').should.equal('01000000');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create a 2 byte buffer even if you ask for a 1 byte', function() {
|
it('should create a 2 byte buffer even if you ask for a 1 byte', function() {
|
||||||
var bn = new BN('ff00', 16);
|
var bn = new BN('ff00', 16);
|
||||||
bn.toBuffer({size: 1}).toString('hex').should.equal('ff00');
|
bn.toBuffer({
|
||||||
|
size: 1
|
||||||
|
}).toString('hex').should.equal('ff00');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create a 4 byte buffer even if you ask for a 1 byte', function() {
|
it('should create a 4 byte buffer even if you ask for a 1 byte', function() {
|
||||||
var bn = new BN('ffffff00', 16);
|
var bn = new BN('ffffff00', 16);
|
||||||
bn.toBuffer({size: 4}).toString('hex').should.equal('ffffff00');
|
bn.toBuffer({
|
||||||
|
size: 4
|
||||||
|
}).toString('hex').should.equal('ffffff00');
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,42 +10,42 @@ var point = require('../../lib/crypto/point');
|
||||||
var should = require('chai').should();
|
var should = require('chai').should();
|
||||||
var vectors = require('../data/ecdsa');
|
var vectors = require('../data/ecdsa');
|
||||||
|
|
||||||
describe("ECDSA", function() {
|
describe('ECDSA', function() {
|
||||||
|
|
||||||
it('should create a blank ecdsa', function() {
|
it('instantiation', function() {
|
||||||
var ecdsa = new ECDSA();
|
var ecdsa = new ECDSA();
|
||||||
|
should.exist(ecdsa);
|
||||||
});
|
});
|
||||||
|
|
||||||
var ecdsa = new ECDSA();
|
var ecdsa = new ECDSA();
|
||||||
ecdsa.hashbuf = Hash.sha256(new Buffer('test data'));
|
ecdsa.hashbuf = Hash.sha256(new Buffer('test data'));
|
||||||
ecdsa.privkey = new Privkey(BN().fromBuffer(new Buffer('fee0a1f7afebf9d2a5a80c0c98a31c709681cce195cbcd06342b517970c0be1e', 'hex')));
|
ecdsa.privkey = new Privkey(BN.fromBuffer(
|
||||||
|
new Buffer('fee0a1f7afebf9d2a5a80c0c98a31c709681cce195cbcd06342b517970c0be1e', 'hex')
|
||||||
|
));
|
||||||
ecdsa.privkey2pubkey();
|
ecdsa.privkey2pubkey();
|
||||||
|
|
||||||
describe('#set', function() {
|
describe('#set', function() {
|
||||||
|
it('sets hashbuf', function() {
|
||||||
it('should set hashbuf', function() {
|
|
||||||
should.exist(ECDSA().set({
|
should.exist(ECDSA().set({
|
||||||
hashbuf: ecdsa.hashbuf
|
hashbuf: ecdsa.hashbuf
|
||||||
}).hashbuf);
|
}).hashbuf);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#calci', function() {
|
describe('#calci', function() {
|
||||||
|
it('calculates i correctly', function() {
|
||||||
it('should calculate i', function() {
|
|
||||||
ecdsa.randomK();
|
ecdsa.randomK();
|
||||||
ecdsa.sign();
|
ecdsa.sign();
|
||||||
ecdsa.calci();
|
ecdsa.calci();
|
||||||
should.exist(ecdsa.sig.i);
|
should.exist(ecdsa.sig.i);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should calulate this known i', function() {
|
it('calulates this known i', function() {
|
||||||
var hashbuf = Hash.sha256(new Buffer('some data'));
|
var hashbuf = Hash.sha256(new Buffer('some data'));
|
||||||
var r = BN('71706645040721865894779025947914615666559616020894583599959600180037551395766', 10);
|
var r = BN('71706645040721865894779025947914615666559616020894583599959600180037551395766', 10);
|
||||||
var s = BN('109412465507152403114191008482955798903072313614214706891149785278625167723646', 10);
|
var s = BN('109412465507152403114191008482955798903072313614214706891149785278625167723646', 10);
|
||||||
var ecdsa = new ECDSA({
|
var ecdsa = new ECDSA({
|
||||||
privkey: Privkey(BN().fromBuffer(Hash.sha256(new Buffer('test')))),
|
privkey: new Privkey(BN.fromBuffer(Hash.sha256(new Buffer('test')))),
|
||||||
hashbuf: hashbuf,
|
hashbuf: hashbuf,
|
||||||
sig: new Signature({
|
sig: new Signature({
|
||||||
r: r,
|
r: r,
|
||||||
|
@ -61,12 +61,11 @@ describe("ECDSA", function() {
|
||||||
|
|
||||||
describe('#fromString', function() {
|
describe('#fromString', function() {
|
||||||
|
|
||||||
it('should to a round trip with to string', function() {
|
it('round trip with fromString', function() {
|
||||||
var str = ecdsa.toString();
|
var str = ecdsa.toString();
|
||||||
var ecdsa2 = new ECDSA();
|
var ecdsa2 = new ECDSA.fromString(str);
|
||||||
ecdsa2.fromString(str);
|
should.exist(ecdsa2.hashbuf);
|
||||||
should.exist(ecdsa.hashbuf);
|
should.exist(ecdsa2.privkey);
|
||||||
should.exist(ecdsa.privkey);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -91,60 +90,64 @@ describe("ECDSA", function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#deterministicK', function() {
|
describe('#deterministicK', function() {
|
||||||
|
|
||||||
it('should generate the same deterministic k', function() {
|
it('should generate the same deterministic k', function() {
|
||||||
ecdsa.deterministicK();
|
ecdsa.deterministicK();
|
||||||
ecdsa.k.toBuffer().toString('hex').should.equal('fcce1de7a9bcd6b2d3defade6afa1913fb9229e3b7ddf4749b55c4848b2a196e');
|
ecdsa.k.toBuffer().toString('hex')
|
||||||
|
.should.equal('fcce1de7a9bcd6b2d3defade6afa1913fb9229e3b7ddf4749b55c4848b2a196e');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should generate the same deterministic k if badrs is set', function() {
|
it('should generate the same deterministic k if badrs is set', function() {
|
||||||
ecdsa.deterministicK(0);
|
ecdsa.deterministicK(0);
|
||||||
ecdsa.k.toBuffer().toString('hex').should.equal('fcce1de7a9bcd6b2d3defade6afa1913fb9229e3b7ddf4749b55c4848b2a196e');
|
ecdsa.k.toBuffer().toString('hex')
|
||||||
|
.should.equal('fcce1de7a9bcd6b2d3defade6afa1913fb9229e3b7ddf4749b55c4848b2a196e');
|
||||||
ecdsa.deterministicK(1);
|
ecdsa.deterministicK(1);
|
||||||
ecdsa.k.toBuffer().toString('hex').should.not.equal('fcce1de7a9bcd6b2d3defade6afa1913fb9229e3b7ddf4749b55c4848b2a196e');
|
ecdsa.k.toBuffer().toString('hex')
|
||||||
ecdsa.k.toBuffer().toString('hex').should.equal('6f4dcca6fa7a137ae9d110311905013b3c053c732ad18611ec2752bb3dcef9d8');
|
.should.not.equal('fcce1de7a9bcd6b2d3defade6afa1913fb9229e3b7ddf4749b55c4848b2a196e');
|
||||||
|
ecdsa.k.toBuffer().toString('hex')
|
||||||
|
.should.equal('6f4dcca6fa7a137ae9d110311905013b3c053c732ad18611ec2752bb3dcef9d8');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should compute this test vector correctly', function() {
|
it('should compute this test vector correctly', function() {
|
||||||
// test fixture from bitcoinjs
|
// test fixture from bitcoinjs
|
||||||
// https://github.com/bitcoinjs/bitcoinjs-lib/blob/10630873ebaa42381c5871e20336fbfb46564ac8/test/fixtures/ecdsa.json#L6
|
// https://github.com/bitcoinjs/bitcoinjs-lib/blob/10630873ebaa42381c5871e20336fbfb46564ac8/test/fixtures/ecdsa.json#L6
|
||||||
var ecdsa = new ECDSA();
|
var ecdsa = new ECDSA();
|
||||||
ecdsa.hashbuf = Hash.sha256(new Buffer('Everything should be made as simple as possible, but not simpler.'));
|
ecdsa.hashbuf = Hash.sha256(new Buffer('Everything should be made as simple as possible, but not simpler.'));
|
||||||
ecdsa.privkey = Privkey(BN(1));
|
ecdsa.privkey = new Privkey(BN(1));
|
||||||
ecdsa.privkey2pubkey();
|
ecdsa.privkey2pubkey();
|
||||||
ecdsa.deterministicK();
|
ecdsa.deterministicK();
|
||||||
ecdsa.k.toBuffer().toString('hex').should.equal('ec633bd56a5774a0940cb97e27a9e4e51dc94af737596a0c5cbb3d30332d92a5');
|
ecdsa.k.toBuffer().toString('hex')
|
||||||
|
.should.equal('ec633bd56a5774a0940cb97e27a9e4e51dc94af737596a0c5cbb3d30332d92a5');
|
||||||
ecdsa.sign();
|
ecdsa.sign();
|
||||||
ecdsa.sig.r.toString().should.equal('23362334225185207751494092901091441011938859014081160902781146257181456271561');
|
ecdsa.sig.r.toString()
|
||||||
ecdsa.sig.s.toString().should.equal('50433721247292933944369538617440297985091596895097604618403996029256432099938');
|
.should.equal('23362334225185207751494092901091441011938859014081160902781146257181456271561');
|
||||||
|
ecdsa.sig.s.toString()
|
||||||
|
.should.equal('50433721247292933944369538617440297985091596895097604618403996029256432099938');
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#sig2pubkey', function() {
|
describe('#toPublicKey', function() {
|
||||||
|
|
||||||
it('should calculate the correct public key', function() {
|
it('should calculate the correct public key', function() {
|
||||||
ecdsa.k = BN('114860389168127852803919605627759231199925249596762615988727970217268189974335', 10);
|
ecdsa.k = BN('114860389168127852803919605627759231199925249596762615988727970217268189974335', 10);
|
||||||
ecdsa.sign();
|
ecdsa.sign();
|
||||||
ecdsa.sig.i = 0;
|
ecdsa.sig.i = 0;
|
||||||
var pubkey = ecdsa.sig2pubkey();
|
var pubkey = ecdsa.toPublicKey();
|
||||||
pubkey.point.eq(ecdsa.pubkey.point).should.equal(true);
|
pubkey.point.eq(ecdsa.pubkey.point).should.equal(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should calculate the correct public key for this signature with low s', function() {
|
it('should calculate the correct public key for this signature with low s', function() {
|
||||||
ecdsa.k = BN('114860389168127852803919605627759231199925249596762615988727970217268189974335', 10);
|
ecdsa.k = BN('114860389168127852803919605627759231199925249596762615988727970217268189974335', 10);
|
||||||
ecdsa.sig = Signature.fromString('3045022100ec3cfe0e335791ad278b4ec8eac93d0347a97877bb1d54d35d189e225c15f6650220278cf15b05ce47fb37d2233802899d94c774d5480bba9f0f2d996baa13370c43');
|
ecdsa.sig = Signature.fromString('3045022100ec3cfe0e335791ad278b4ec8eac93d0347' +
|
||||||
|
'a97877bb1d54d35d189e225c15f6650220278cf15b05ce47fb37d2233802899d94c774d5480bba9f0f2d996baa13370c43');
|
||||||
ecdsa.sig.i = 0;
|
ecdsa.sig.i = 0;
|
||||||
var pubkey = ecdsa.sig2pubkey();
|
var pubkey = ecdsa.toPublicKey();
|
||||||
pubkey.point.eq(ecdsa.pubkey.point).should.equal(true);
|
pubkey.point.eq(ecdsa.pubkey.point).should.equal(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should calculate the correct public key for this signature with high s', function() {
|
it('should calculate the correct public key for this signature with high s', function() {
|
||||||
ecdsa.k = BN('114860389168127852803919605627759231199925249596762615988727970217268189974335', 10);
|
ecdsa.k = BN('114860389168127852803919605627759231199925249596762615988727970217268189974335', 10);
|
||||||
ecdsa.sign();
|
ecdsa.sign();
|
||||||
ecdsa.sig = Signature.fromString('3046022100ec3cfe0e335791ad278b4ec8eac93d0347a97877bb1d54d35d189e225c15f665022100d8730ea4fa31b804c82ddcc7fd766269f33a079ea38e012c9238f2e2bcff34fe');
|
ecdsa.sig = Signature.fromString('3046022100ec3cfe0e335791ad278b4ec8eac93d0347' +
|
||||||
|
'a97877bb1d54d35d189e225c15f665022100d8730ea4fa31b804c82ddcc7fd766269f33a079ea38e012c9238f2e2bcff34fe');
|
||||||
ecdsa.sig.i = 1;
|
ecdsa.sig.i = 1;
|
||||||
var pubkey = ecdsa.sig2pubkey();
|
var pubkey = ecdsa.toPublicKey();
|
||||||
pubkey.point.eq(ecdsa.pubkey.point).should.equal(true);
|
pubkey.point.eq(ecdsa.pubkey.point).should.equal(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -160,18 +163,20 @@ describe("ECDSA", function() {
|
||||||
it('should return an error if r, s are invalid', function() {
|
it('should return an error if r, s are invalid', function() {
|
||||||
var ecdsa = new ECDSA();
|
var ecdsa = new ECDSA();
|
||||||
ecdsa.hashbuf = Hash.sha256(new Buffer('test'));
|
ecdsa.hashbuf = Hash.sha256(new Buffer('test'));
|
||||||
var pk = Pubkey.fromDER(new Buffer('041ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a7baad41d04514751e6851f5304fd243751703bed21b914f6be218c0fa354a341', 'hex'));
|
var pk = Pubkey.fromDER(new Buffer('041ff0fe0f7b15ffaa85ff9f4744d539139c252a49' +
|
||||||
|
'710fb053bb9f2b933173ff9a7baad41d04514751e6851f5304fd243751703bed21b914f6be218c0fa354a341', 'hex'));
|
||||||
ecdsa.pubkey = pk;
|
ecdsa.pubkey = pk;
|
||||||
ecdsa.sig = new Signature();
|
ecdsa.sig = new Signature();
|
||||||
ecdsa.sig.r = BN(0);
|
ecdsa.sig.r = BN(0);
|
||||||
ecdsa.sig.s = BN(0);
|
ecdsa.sig.s = BN(0);
|
||||||
ecdsa.sigError().should.equal("r and s not in range");
|
ecdsa.sigError().should.equal('r and s not in range');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return an error if the signature is incorrect', function() {
|
it('should return an error if the signature is incorrect', function() {
|
||||||
ecdsa.sig = new Signature.fromString('3046022100e9915e6236695f093a4128ac2a956c40ed971531de2f4f41ba05fac7e2bd019c02210094e6a4a769cc7f2a8ab3db696c7cd8d56bcdbfff860a8c81de4bc6a798b90827');
|
ecdsa.sig = Signature.fromString('3046022100e9915e6236695f093a4128ac2a956c40' +
|
||||||
|
'ed971531de2f4f41ba05fac7e2bd019c02210094e6a4a769cc7f2a8ab3db696c7cd8d56bcdbfff860a8c81de4bc6a798b90827');
|
||||||
ecdsa.sig.r = ecdsa.sig.r.add(BN(1));
|
ecdsa.sig.r = ecdsa.sig.r.add(BN(1));
|
||||||
ecdsa.sigError().should.equal("Invalid signature");
|
ecdsa.sigError().should.equal('Invalid signature');
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -190,9 +195,7 @@ describe("ECDSA", function() {
|
||||||
privkey: ecdsa.privkey
|
privkey: ecdsa.privkey
|
||||||
});
|
});
|
||||||
ecdsa2.randomK();
|
ecdsa2.randomK();
|
||||||
(function() {
|
ecdsa2.sign.bind(ecdsa2).should.throw('hashbuf must be a 32 byte buffer');
|
||||||
ecdsa2.sign();
|
|
||||||
}).should.throw('hashbuf must be a 32 byte buffer');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should default to deterministicK', function() {
|
it('should default to deterministicK', function() {
|
||||||
|
@ -210,106 +213,89 @@ describe("ECDSA", function() {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#signRandomK', function() {
|
|
||||||
|
|
||||||
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());
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('#toString', function() {
|
describe('#toString', function() {
|
||||||
|
|
||||||
it('should convert this to a string', function() {
|
it('should convert this to a string', function() {
|
||||||
var str = ecdsa.toString();
|
var str = ecdsa.toString();
|
||||||
(typeof str === 'string').should.equal(true);
|
(typeof str === 'string').should.equal(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#verify', function() {
|
describe('signing and verification', function() {
|
||||||
|
describe('@sign', function() {
|
||||||
it('should verify a signature that was just signed', function() {
|
it('should produce a signature', function() {
|
||||||
ecdsa.sig = new Signature.fromString('3046022100e9915e6236695f093a4128ac2a956c40ed971531de2f4f41ba05fac7e2bd019c02210094e6a4a769cc7f2a8ab3db696c7cd8d56bcdbfff860a8c81de4bc6a798b90827');
|
var sig = ECDSA.sign(ecdsa.hashbuf, ecdsa.privkey);
|
||||||
ecdsa.verify().verified.should.equal(true);
|
(sig instanceof Signature).should.equal(true);
|
||||||
});
|
});
|
||||||
|
it('should produce a signature, and be different when called twice', function() {
|
||||||
it('should verify this known good signature', function() {
|
ecdsa.signRandomK();
|
||||||
ecdsa.signRandomK();
|
should.exist(ecdsa.sig);
|
||||||
ecdsa.verify().verified.should.equal(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('@sign', function() {
|
|
||||||
|
|
||||||
it('should produce a signature', function() {
|
|
||||||
var sig = ECDSA.sign(ecdsa.hashbuf, ecdsa.privkey);
|
|
||||||
(sig instanceof Signature).should.equal(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('@verify', function() {
|
|
||||||
|
|
||||||
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 = Signature(sig.r.add(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('vectors', function() {
|
|
||||||
|
|
||||||
vectors.valid.forEach(function(obj, i) {
|
|
||||||
it('should validate valid vector ' + i, function() {
|
|
||||||
var ecdsa = ECDSA().set({
|
|
||||||
privkey: Privkey(BN().fromBuffer(new Buffer(obj.d, 'hex'))),
|
|
||||||
k: BN().fromBuffer(new Buffer(obj.k, 'hex')),
|
|
||||||
hashbuf: Hash.sha256(new Buffer(obj.message)),
|
|
||||||
sig: Signature().set({
|
|
||||||
r: BN(obj.signature.r),
|
|
||||||
s: BN(obj.signature.s),
|
|
||||||
i: obj.i
|
|
||||||
})
|
|
||||||
});
|
|
||||||
var ecdsa2 = ECDSA(ecdsa);
|
var ecdsa2 = ECDSA(ecdsa);
|
||||||
ecdsa2.k = undefined;
|
ecdsa2.signRandomK();
|
||||||
ecdsa2.sign();
|
ecdsa.sig.toString().should.not.equal(ecdsa2.sig.toString());
|
||||||
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);
|
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);
|
ecdsa.verify().verified.should.equal(true);
|
||||||
});
|
});
|
||||||
});
|
it('should verify this known good signature', function() {
|
||||||
|
ecdsa.signRandomK();
|
||||||
vectors.invalid.sigError.forEach(function(obj, i) {
|
ecdsa.verify().verified.should.equal(true);
|
||||||
it('should validate invalid.sigError vector ' + i + ': ' + obj.description, function() {
|
});
|
||||||
var ecdsa = ECDSA().set({
|
it('should verify a valid signature, and unverify an invalid signature', function() {
|
||||||
pubkey: Pubkey.fromPoint(point.fromX(true, 1)),
|
var sig = ECDSA.sign(ecdsa.hashbuf, ecdsa.privkey);
|
||||||
sig: Signature(BN(obj.signature.r), BN(obj.signature.s)),
|
ECDSA.verify(ecdsa.hashbuf, sig, ecdsa.pubkey).should.equal(true);
|
||||||
hashbuf: Hash.sha256(new Buffer(obj.message))
|
var fakesig = new Signature(sig.r.add(1), sig.s);
|
||||||
});
|
ECDSA.verify(ecdsa.hashbuf, fakesig, ecdsa.pubkey).should.equal(false);
|
||||||
ecdsa.sigError().should.equal(obj.exception);
|
});
|
||||||
|
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('vectors', function() {
|
||||||
|
|
||||||
|
vectors.valid.forEach(function(obj, i) {
|
||||||
|
it('should validate valid vector ' + i, function() {
|
||||||
|
var ecdsa = ECDSA().set({
|
||||||
|
privkey: new Privkey(BN.fromBuffer(new Buffer(obj.d, 'hex'))),
|
||||||
|
k: BN.fromBuffer(new Buffer(obj.k, 'hex')),
|
||||||
|
hashbuf: Hash.sha256(new Buffer(obj.message)),
|
||||||
|
sig: new Signature().set({
|
||||||
|
r: BN(obj.signature.r),
|
||||||
|
s: 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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
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(BN(obj.signature.r), BN(obj.signature.s)),
|
||||||
|
hashbuf: Hash.sha256(new Buffer(obj.message))
|
||||||
|
});
|
||||||
|
ecdsa.sigError().should.equal(obj.exception);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,121 +10,125 @@ describe('Hash', function() {
|
||||||
|
|
||||||
describe('@sha1', function() {
|
describe('@sha1', function() {
|
||||||
|
|
||||||
it('should calculate the hash of this buffer correctly', function() {
|
it('calculates the hash of this buffer correctly', function() {
|
||||||
var hash = Hash.sha1(buf);
|
var hash = Hash.sha1(buf);
|
||||||
hash.toString('hex').should.equal('de69b8a4a5604d0486e6420db81e39eb464a17b2');
|
hash.toString('hex').should.equal('de69b8a4a5604d0486e6420db81e39eb464a17b2');
|
||||||
hash = Hash.sha1(new Buffer(0));
|
hash = Hash.sha1(new Buffer(0));
|
||||||
hash.toString('hex').should.equal('da39a3ee5e6b4b0d3255bfef95601890afd80709');
|
hash.toString('hex').should.equal('da39a3ee5e6b4b0d3255bfef95601890afd80709');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error when the input is not a buffer', function() {
|
it('throws an error when the input is not a buffer', function() {
|
||||||
(function() {
|
Hash.sha1.bind(Hash, str).should.throw('Invalid Argument');
|
||||||
Hash.sha1(str);
|
|
||||||
}).should.throw('Invalid Argument');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#sha256', function() {
|
describe('#sha256', function() {
|
||||||
|
|
||||||
it('should calculate the hash of this buffer correctly', function() {
|
it('calculates the hash of this buffer correctly', function() {
|
||||||
var hash = Hash.sha256(buf);
|
var hash = Hash.sha256(buf);
|
||||||
hash.toString('hex').should.equal('6f2c7b22fd1626998287b3636089087961091de80311b9279c4033ec678a83e8');
|
hash.toString('hex').should.equal('6f2c7b22fd1626998287b3636089087961091de80311b9279c4033ec678a83e8');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error when the input is not a buffer', function() {
|
it('fails when the input is not a buffer', function() {
|
||||||
(function() {
|
Hash.sha256.bind(Hash, str).should.throw('Invalid Argument');
|
||||||
Hash.sha256(str);
|
|
||||||
}).should.throw('Invalid Argument');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#sha256hmac', function() {
|
describe('#sha256hmac', function() {
|
||||||
|
|
||||||
it('should compute this known empty test vector correctly', function() {
|
it('computes this known big key correctly', function() {
|
||||||
var key = new Buffer('');
|
var key = new Buffer('b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad' +
|
||||||
|
'b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad' +
|
||||||
|
'b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad' +
|
||||||
|
'b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad');
|
||||||
var data = new Buffer('');
|
var data = new Buffer('');
|
||||||
Hash.sha256hmac(data, key).toString('hex').should.equal('b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad');
|
Hash.sha256hmac(data, key).toString('hex')
|
||||||
|
.should.equal('fb1f87218671f1c0c4593a88498e02b6dfe8afd814c1729e89a1f1f6600faa23');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should compute this known non-empty test vector correctly', function() {
|
it('computes this known empty test vector correctly', function() {
|
||||||
|
var key = new Buffer('');
|
||||||
|
var data = new Buffer('');
|
||||||
|
Hash.sha256hmac(data, key).toString('hex')
|
||||||
|
.should.equal('b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('computes this known non-empty test vector correctly', function() {
|
||||||
var key = new Buffer('key');
|
var key = new Buffer('key');
|
||||||
var data = new Buffer('The quick brown fox jumps over the lazy dog');
|
var data = new Buffer('The quick brown fox jumps over the lazy dog');
|
||||||
Hash.sha256hmac(data, key).toString('hex').should.equal('f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8');
|
Hash.sha256hmac(data, key).toString('hex')
|
||||||
|
.should.equal('f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8');
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#sha256sha256', function() {
|
describe('#sha256sha256', function() {
|
||||||
|
|
||||||
it('should calculate the hash of this buffer correctly', function() {
|
it('calculates the hash of this buffer correctly', function() {
|
||||||
var hash = Hash.sha256sha256(buf);
|
var hash = Hash.sha256sha256(buf);
|
||||||
hash.toString('hex').should.equal('be586c8b20dee549bdd66018c7a79e2b67bb88b7c7d428fa4c970976d2bec5ba');
|
hash.toString('hex').should.equal('be586c8b20dee549bdd66018c7a79e2b67bb88b7c7d428fa4c970976d2bec5ba');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error when the input is not a buffer', function() {
|
it('fails when the input is not a buffer', function() {
|
||||||
(function() {
|
Hash.sha256sha256.bind(Hash, str).should.throw('Invalid Argument');
|
||||||
Hash.sha256sha256(str);
|
|
||||||
}).should.throw('Invalid Argument');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#sha256ripemd160', function() {
|
describe('#sha256ripemd160', function() {
|
||||||
|
|
||||||
it('should calculate the hash of this buffer correctly', function() {
|
it('calculates the hash of this buffer correctly', function() {
|
||||||
var hash = Hash.sha256ripemd160(buf);
|
var hash = Hash.sha256ripemd160(buf);
|
||||||
hash.toString('hex').should.equal('7322e2bd8535e476c092934e16a6169ca9b707ec');
|
hash.toString('hex').should.equal('7322e2bd8535e476c092934e16a6169ca9b707ec');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error when the input is not a buffer', function() {
|
it('fails when the input is not a buffer', function() {
|
||||||
(function() {
|
Hash.sha256ripemd160.bind(Hash, str).should.throw('Invalid Argument');
|
||||||
Hash.sha256ripemd160(str);
|
|
||||||
}).should.throw('Invalid Argument');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#ripemd160', function() {
|
describe('#ripemd160', function() {
|
||||||
|
|
||||||
it('should calculate the hash of this buffer correctly', function() {
|
it('calculates the hash of this buffer correctly', function() {
|
||||||
var hash = Hash.ripemd160(buf);
|
var hash = Hash.ripemd160(buf);
|
||||||
hash.toString('hex').should.equal('fa0f4565ff776fee0034c713cbf48b5ec06b7f5c');
|
hash.toString('hex').should.equal('fa0f4565ff776fee0034c713cbf48b5ec06b7f5c');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error when the input is not a buffer', function() {
|
it('fails when the input is not a buffer', function() {
|
||||||
(function() {
|
Hash.ripemd160.bind(Hash, str).should.throw('Invalid Argument');
|
||||||
Hash.ripemd160(str);
|
|
||||||
}).should.throw('Invalid Argument');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#sha512', function() {
|
describe('#sha512', function() {
|
||||||
|
|
||||||
it('should calculate the hash of this buffer correctly', function() {
|
it('calculates the hash of this buffer correctly', function() {
|
||||||
var hash = Hash.sha512(buf);
|
var hash = Hash.sha512(buf);
|
||||||
hash.toString('hex').should.equal('c0530aa32048f4904ae162bc14b9eb535eab6c465e960130005feddb71613e7d62aea75f7d3333ba06e805fc8e45681454524e3f8050969fe5a5f7f2392e31d0');
|
hash.toString('hex')
|
||||||
|
.should.equal('c0530aa32048f4904ae162bc14b9eb535eab6c465e960130005fedd' +
|
||||||
|
'b71613e7d62aea75f7d3333ba06e805fc8e45681454524e3f8050969fe5a5f7f2392e31d0');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error when the input is not a buffer', function() {
|
it('fails when the input is not a buffer', function() {
|
||||||
(function() {
|
Hash.sha512.bind(Hash, str).should.throw('Invalid Argument');
|
||||||
Hash.sha512(str);
|
|
||||||
}).should.throw('Invalid Argument');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#sha512hmac', function() {
|
describe('#sha512hmac', function() {
|
||||||
|
|
||||||
it('should calculate this known empty test vector correctly', function() {
|
it('calculates this known empty test vector correctly', function() {
|
||||||
var hex = 'b936cee86c9f87aa5d3c6f2e84cb5a4239a5fe50480a6ec66b70ab5b1f4ac6730c6c515421b327ec1d69402e53dfb49ad7381eb067b338fd7b0cb22247225d47';
|
var hex = 'b936cee86c9f87aa5d3c6f2e84cb5a4239a5fe50480a6ec66b70ab5b1f4a' +
|
||||||
|
'c6730c6c515421b327ec1d69402e53dfb49ad7381eb067b338fd7b0cb22247225d47';
|
||||||
Hash.sha512hmac(new Buffer([]), new Buffer([])).toString('hex').should.equal(hex);
|
Hash.sha512hmac(new Buffer([]), new Buffer([])).toString('hex').should.equal(hex);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should calculate this known non-empty test vector correctly', function() {
|
it('calculates this known non-empty test vector correctly', function() {
|
||||||
var hex = 'c40bd7c15aa493b309c940e08a73ffbd28b2e4cb729eb94480d727e4df577b13cc403a78e6150d83595f3b17c4cc331f12ca5952691de3735a63c1d4c69a2bac';
|
var hex = 'c40bd7c15aa493b309c940e08a73ffbd28b2e4cb729eb94480d727e4df577' +
|
||||||
|
'b13cc403a78e6150d83595f3b17c4cc331f12ca5952691de3735a63c1d4c69a2bac';
|
||||||
var data = new Buffer('test1');
|
var data = new Buffer('test1');
|
||||||
var key = new Buffer('test2');
|
var key = new Buffer('test2');
|
||||||
Hash.sha512hmac(data, key).toString('hex').should.equal(hex);
|
Hash.sha512hmac(data, key).toString('hex').should.equal(hex);
|
||||||
|
|
|
@ -21,11 +21,14 @@ describe('Random', function() {
|
||||||
|
|
||||||
it('should generate 100 8 byte buffers in a row that are not equal', function() {
|
it('should generate 100 8 byte buffers in a row that are not equal', function() {
|
||||||
var hexs = [];
|
var hexs = [];
|
||||||
for (var i = 0; i < 100; i++)
|
for (var i = 0; i < 100; i++) {
|
||||||
hexs[i] = Random.getRandomBuffer(8).toString('hex');
|
hexs[i] = Random.getRandomBuffer(8).toString('hex');
|
||||||
for (i = 0; i < 100; i++)
|
}
|
||||||
for (var j = i + 1; j < 100; j++)
|
for (i = 0; i < 100; i++) {
|
||||||
|
for (var j = i + 1; j < 100; j++) {
|
||||||
hexs[i].should.not.equal(hexs[j]);
|
hexs[i].should.not.equal(hexs[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -89,7 +89,7 @@ describe('Interpreter', function() {
|
||||||
})).should.equal(true);
|
})).should.equal(true);
|
||||||
|
|
||||||
var buf = new Buffer('00', 'hex');
|
var buf = new Buffer('00', 'hex');
|
||||||
var bool = BN().fromSM(buf, {
|
var bool = BN.fromSM(buf, {
|
||||||
endian: 'little'
|
endian: 'little'
|
||||||
}).cmp(0) !== 0;
|
}).cmp(0) !== 0;
|
||||||
Interpreter.castToBool(buf).should.equal(bool);
|
Interpreter.castToBool(buf).should.equal(bool);
|
||||||
|
@ -201,7 +201,7 @@ describe('Interpreter', function() {
|
||||||
|
|
||||||
var hashbuf = new Buffer(32);
|
var hashbuf = new Buffer(32);
|
||||||
hashbuf.fill(0);
|
hashbuf.fill(0);
|
||||||
var credtx = Transaction();
|
var credtx = new Transaction();
|
||||||
credtx.uncheckedAddInput(new Transaction.Input({
|
credtx.uncheckedAddInput(new Transaction.Input({
|
||||||
prevTxId: '0000000000000000000000000000000000000000000000000000000000000000',
|
prevTxId: '0000000000000000000000000000000000000000000000000000000000000000',
|
||||||
outputIndex: 0xffffffff,
|
outputIndex: 0xffffffff,
|
||||||
|
@ -214,7 +214,7 @@ describe('Interpreter', function() {
|
||||||
}));
|
}));
|
||||||
var idbuf = credtx.id;
|
var idbuf = credtx.id;
|
||||||
|
|
||||||
var spendtx = Transaction();
|
var spendtx = new Transaction();
|
||||||
spendtx.uncheckedAddInput(new Transaction.Input({
|
spendtx.uncheckedAddInput(new Transaction.Input({
|
||||||
prevTxId: idbuf.toString('hex'),
|
prevTxId: idbuf.toString('hex'),
|
||||||
outputIndex: 0,
|
outputIndex: 0,
|
||||||
|
@ -222,11 +222,11 @@ describe('Interpreter', function() {
|
||||||
script: scriptSig
|
script: scriptSig
|
||||||
}));
|
}));
|
||||||
spendtx.addOutput(new Transaction.Output({
|
spendtx.addOutput(new Transaction.Output({
|
||||||
script: Script(),
|
script: new Script(),
|
||||||
satoshis: 0
|
satoshis: 0
|
||||||
}));
|
}));
|
||||||
|
|
||||||
var interp = Interpreter();
|
var interp = new Interpreter();
|
||||||
var verified = interp.verify(scriptSig, scriptPubkey, spendtx, 0, flags);
|
var verified = interp.verify(scriptSig, scriptPubkey, spendtx, 0, flags);
|
||||||
verified.should.equal(expected);
|
verified.should.equal(expected);
|
||||||
};
|
};
|
||||||
|
@ -275,7 +275,7 @@ describe('Interpreter', function() {
|
||||||
map[txid + ':' + txoutnum] = Script.fromBitcoindString(scriptPubKeyStr);
|
map[txid + ':' + txoutnum] = Script.fromBitcoindString(scriptPubKeyStr);
|
||||||
});
|
});
|
||||||
|
|
||||||
var tx = Transaction(txhex);
|
var tx = new Transaction(txhex);
|
||||||
var allInputsVerified = true;
|
var allInputsVerified = true;
|
||||||
tx.inputs.forEach(function(txin, j) {
|
tx.inputs.forEach(function(txin, j) {
|
||||||
var scriptSig = txin.script;
|
var scriptSig = txin.script;
|
||||||
|
@ -284,7 +284,7 @@ describe('Interpreter', function() {
|
||||||
var scriptPubkey = map[txidhex + ':' + txoutnum];
|
var scriptPubkey = map[txidhex + ':' + txoutnum];
|
||||||
should.exist(scriptPubkey);
|
should.exist(scriptPubkey);
|
||||||
should.exist(scriptSig);
|
should.exist(scriptSig);
|
||||||
var interp = Interpreter();
|
var interp = new Interpreter();
|
||||||
var verified = interp.verify(scriptSig, scriptPubkey, tx, j, flags);
|
var verified = interp.verify(scriptSig, scriptPubkey, tx, j, flags);
|
||||||
if (!verified) {
|
if (!verified) {
|
||||||
allInputsVerified = false;
|
allInputsVerified = false;
|
||||||
|
|
Loading…
Reference in New Issue