diff --git a/lib/crypto/ec-elliptic.js b/lib/crypto/ec-elliptic.js index 758b41ce..cd90002f 100644 --- a/lib/crypto/ec-elliptic.js +++ b/lib/crypto/ec-elliptic.js @@ -35,26 +35,27 @@ ec.binding = false; ec.generatePrivateKey = function generatePrivateKey() { var key = secp256k1.genKeyPair(); - var priv = key.getPrivate().toArrayLike(Buffer, 'be', 32); - return priv; + return key.getPrivate().toArrayLike(Buffer, 'be', 32); }; /** * Create a public key from a private key. * @param {Buffer} priv - * @param {Boolean?} compressed + * @param {Boolean?} compress * @returns {Buffer} */ -ec.publicKeyCreate = function publicKeyCreate(priv, compressed) { +ec.publicKeyCreate = function publicKeyCreate(priv, compress) { var key; assert(Buffer.isBuffer(priv)); - key = secp256k1.keyPair({ priv: priv }); - key = key.getPublic(compressed !== false, 'array'); + if (compress == null) + compress = true; - return Buffer.from(key); + key = secp256k1.keyPair({ priv: priv }); + + return Buffer.from(key.getPublic(compress, 'array')); }; /** @@ -63,9 +64,13 @@ ec.publicKeyCreate = function publicKeyCreate(priv, compressed) { * @returns {Buffer} */ -ec.publicKeyConvert = function publicKeyConvert(key, compressed) { +ec.publicKeyConvert = function publicKeyConvert(key, compress) { var point = curve.decodePoint(key); - return Buffer.from(point.encode('array', compressed !== false)); + + if (compress == null) + compress = true; + + return Buffer.from(point.encode('array', compress)); }; /** @@ -95,10 +100,15 @@ ec.privateKeyTweakAdd = function privateKeyTweakAdd(privateKey, tweak) { * @returns {Buffer} publicKey */ -ec.publicKeyTweakAdd = function publicKeyTweakAdd(publicKey, tweak, compressed) { +ec.publicKeyTweakAdd = function publicKeyTweakAdd(publicKey, tweak, compress) { var key = curve.decodePoint(publicKey); var point = curve.g.mul(new BN(tweak)).add(key); - var pub = Buffer.from(point.encode('array', compressed !== false)); + var pub; + + if (compress == null) + compress = true; + + pub = Buffer.from(point.encode('array', compress)); if (!ec.publicKeyVerify(pub)) throw new Error('Public key is invalid.'); @@ -124,25 +134,26 @@ ec.ecdh = function ecdh(pub, priv) { * @param {Buffer} msg * @param {Buffer} sig * @param {Number?} j - * @param {Boolean?} compressed + * @param {Boolean?} compress * @returns {Buffer[]|Buffer|null} */ -ec.recover = function recover(msg, sig, j, compressed) { - var point, key; +ec.recover = function recover(msg, sig, j, compress) { + var point; if (!j) j = 0; + if (compress == null) + compress = true; + try { point = secp256k1.recoverPubKey(msg, sig, j); } catch (e) { return; } - key = point.encode('array', compressed !== false); - - return Buffer.from(key); + return Buffer.from(point.encode('array', compress)); }; /** @@ -150,14 +161,10 @@ ec.recover = function recover(msg, sig, j, compressed) { * @param {Buffer} msg * @param {Buffer} sig - DER formatted. * @param {Buffer} key - * @param {Boolean?} - Whether this should be treated as a - * "historical" signature. This allows signatures to be of - * odd lengths. - * @param {Boolean?} high - Allow high S value. * @returns {Boolean} */ -ec.verify = function verify(msg, sig, key, historical, high) { +ec.verify = function verify(msg, sig, key) { assert(Buffer.isBuffer(msg)); assert(Buffer.isBuffer(sig)); assert(Buffer.isBuffer(key)); @@ -170,15 +177,8 @@ ec.verify = function verify(msg, sig, key, historical, high) { // Attempt to normalize the signature // length before passing to elliptic. - // Note: We only do this for historical data! // https://github.com/indutny/elliptic/issues/78 - if (historical) - sig = normalizeLength(sig); - - // Make elliptic mimic secp256k1's - // failure with high S values. - if (!high && !ec.isLowS(sig)) - return false; + sig = normalizeLength(sig); try { return secp256k1.verify(msg, sig, key); @@ -232,7 +232,7 @@ ec.sign = function sign(msg, key) { // Sign message and ensure low S value sig = secp256k1.sign(msg, key, { canonical: true }); - // Convert to DER array + // Convert to DER return Buffer.from(sig.toDER()); }; diff --git a/lib/crypto/ec-secp256k1.js b/lib/crypto/ec-secp256k1.js index 3b1ad4f4..8ec88d65 100644 --- a/lib/crypto/ec-secp256k1.js +++ b/lib/crypto/ec-secp256k1.js @@ -57,13 +57,13 @@ ec.generatePrivateKey = function generatePrivateKey() { /** * Create a public key from a private key. * @param {Buffer} priv - * @param {Boolean?} compressed + * @param {Boolean?} compress * @returns {Buffer} */ -ec.publicKeyCreate = function publicKeyCreate(priv, compressed) { +ec.publicKeyCreate = function publicKeyCreate(priv, compress) { assert(Buffer.isBuffer(priv)); - return secp256k1.publicKeyCreate(priv, compressed); + return secp256k1.publicKeyCreate(priv, compress); }; /** @@ -72,8 +72,8 @@ ec.publicKeyCreate = function publicKeyCreate(priv, compressed) { * @returns {Buffer} */ -ec.publicKeyConvert = function publicKeyConvert(key, compressed) { - return secp256k1.publicKeyConvert(key, compressed); +ec.publicKeyConvert = function publicKeyConvert(key, compress) { + return secp256k1.publicKeyConvert(key, compress); }; /** @@ -94,8 +94,8 @@ ec.privateKeyTweakAdd = function privateKeyTweakAdd(privateKey, tweak) { * @returns {Buffer} publicKey */ -ec.publicKeyTweakAdd = function publicKeyTweakAdd(publicKey, tweak, compressed) { - return secp256k1.publicKeyTweakAdd(publicKey, tweak, compressed); +ec.publicKeyTweakAdd = function publicKeyTweakAdd(publicKey, tweak, compress) { + return secp256k1.publicKeyTweakAdd(publicKey, tweak, compress); }; /** @@ -115,11 +115,11 @@ ec.ecdh = function ecdh(pub, priv) { * @param {Buffer} msg * @param {Buffer} sig * @param {Number?} j - * @param {Boolean?} compressed + * @param {Boolean?} compress * @returns {Buffer[]|Buffer|null} */ -ec.recover = function recover(msg, sig, j, compressed) { +ec.recover = function recover(msg, sig, j, compress) { var key; if (!j) @@ -132,7 +132,7 @@ ec.recover = function recover(msg, sig, j, compressed) { } try { - key = secp256k1.recover(msg, sig, j, compressed); + key = secp256k1.recover(msg, sig, j, compress); } catch (e) { return; } @@ -145,14 +145,10 @@ ec.recover = function recover(msg, sig, j, compressed) { * @param {Buffer} msg * @param {Buffer} sig - DER formatted. * @param {Buffer} key - * @param {Boolean?} - Whether this should be treated as a - * "historical" signature. This allows signatures to be of - * odd lengths. - * @param {Boolean?} high - Allow high S value. * @returns {Boolean} */ -ec.verify = function verify(msg, sig, key, historical, high) { +ec.verify = function verify(msg, sig, key) { assert(Buffer.isBuffer(msg)); assert(Buffer.isBuffer(sig)); assert(Buffer.isBuffer(key)); @@ -164,14 +160,8 @@ ec.verify = function verify(msg, sig, key, historical, high) { return false; try { - if (historical) - sig = secp256k1.signatureImportLax(sig); - else - sig = secp256k1.signatureImport(sig); - - if (high) - sig = secp256k1.signatureNormalize(sig); - + sig = secp256k1.signatureImportLax(sig); + sig = secp256k1.signatureNormalize(sig); return secp256k1.verify(msg, sig, key); } catch (e) { return false; @@ -217,7 +207,7 @@ ec.sign = function sign(msg, key) { // Ensure low S value sig = secp256k1.signatureNormalize(sig.signature); - // Convert to DER array + // Convert to DER return secp256k1.signatureExport(sig); }; diff --git a/lib/script/script.js b/lib/script/script.js index 227ce5b4..57bf0971 100644 --- a/lib/script/script.js +++ b/lib/script/script.js @@ -1117,7 +1117,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers if (sig.length > 0) { type = sig[sig.length - 1]; hash = tx.signatureHash(index, subscript, value, type, version); - res = Script.checksig(hash, sig, key, flags); + res = Script.checksig(hash, sig, key); } if (!res && (flags & Script.flags.VERIFY_NULLFAIL)) { @@ -1197,7 +1197,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers type = sig[sig.length - 1]; hash = tx.signatureHash(index, subscript, value, type, version); - if (Script.checksig(hash, sig, key, flags)) { + if (Script.checksig(hash, sig, key)) { isig++; m--; } @@ -3106,39 +3106,15 @@ Script.verifyMast = function verifyMast(program, stack, output, flags, tx, i, va }; /** - * Verify a signature, taking into account sighash type - * and whether the signature is historical. + * Verify a signature, taking into account sighash type. * @param {Buffer} msg - Signature hash. * @param {Buffer} sig * @param {Buffer} key - * @param {VerifyFlags?} flags - If none of VERIFY_DERSIG, - * VERIFY_LOW_S, or VERIFY_STRICTENC are enabled, the signature - * is treated as historical, allowing odd signature lengths - * and high S values. * @returns {Boolean} */ -Script.checksig = function checksig(msg, sig, key, flags) { - var historical = false; - var high = false; - - if (flags == null) - flags = Script.flags.STANDARD_VERIFY_FLAGS; - - // Attempt to normalize the signature - // length before passing to elliptic. - // Note: We only do this for historical data! - // https://github.com/indutny/elliptic/issues/78 - if (!((flags & Script.flags.VERIFY_DERSIG) - || (flags & Script.flags.VERIFY_LOW_S) - || (flags & Script.flags.VERIFY_STRICTENC))) { - historical = true; - } - - if (!(flags & Script.flags.VERIFY_LOW_S)) - high = true; - - return sigcache.verify(msg, sig.slice(0, -1), key, historical, high); +Script.checksig = function checksig(msg, sig, key) { + return sigcache.verify(msg, sig.slice(0, -1), key); }; /** diff --git a/lib/script/sigcache.js b/lib/script/sigcache.js index 688f86fc..f6da0eb2 100644 --- a/lib/script/sigcache.js +++ b/lib/script/sigcache.js @@ -14,7 +14,7 @@ var ec = require('../crypto/ec'); * Signature cache. * @alias module:script.SigCache * @constructor - * @param {Number} [size=50000] + * @param {Number} [size=10000] * @property {Number} size * @property {Hash[]} keys * @property {Object} valid @@ -98,23 +98,21 @@ SigCache.prototype.has = function has(hash, sig, key) { * @param {Buffer} msg * @param {Buffer} sig * @param {Buffer} key - * @param {Boolean?} historical - * @param {Boolean?} high * @returns {Boolean} */ -SigCache.prototype.verify = function verify(msg, sig, key, historical, high) { +SigCache.prototype.verify = function verify(msg, sig, key) { var hash, result; - if (historical || this.size === 0) - return ec.verify(msg, sig, key, historical, high); + if (this.size === 0) + return ec.verify(msg, sig, key); hash = msg.toString('hex'); if (this.has(hash, sig, key)) return true; - result = ec.verify(msg, sig, key, historical, high); + result = ec.verify(msg, sig, key); if (!result) return false; @@ -135,8 +133,8 @@ SigCache.prototype.verify = function verify(msg, sig, key, historical, high) { */ function SigCacheEntry(sig, key) { - this.sig = sig; - this.key = key; + this.sig = util.copy(sig); + this.key = util.copy(key); } /**