From 960d144455e1012010535dfaae03c97d5cfeefe4 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Sat, 24 Sep 2016 19:28:59 -0700 Subject: [PATCH] ec: start migrating towards secp256k1. --- lib/crypto/ec.js | 97 +++++++++++++++++++++++++++--------------------- 1 file changed, 55 insertions(+), 42 deletions(-) diff --git a/lib/crypto/ec.js b/lib/crypto/ec.js index d159151e..723387d8 100644 --- a/lib/crypto/ec.js +++ b/lib/crypto/ec.js @@ -21,6 +21,19 @@ try { ; } +/* + * Constants + */ + +var ZERO_S = new Buffer( + '0000000000000000000000000000000000000000000000000000000000000000', + 'hex' +); + +var HALF_ORDER = new Buffer( + '7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0', + 'hex'); + /** * @exports ec */ @@ -173,8 +186,7 @@ ec.ecdh = function ecdh(pub, priv) { if (secp256k1) { point = secp256k1.ecdhUnsafe(pub, priv, true); - point = ec.curve.decodePoint(point); - return point.getX().toArrayLike(Buffer, 'be', 32); + return point.slice(1, 33); } priv = ec.elliptic.keyPair({ priv: priv }); @@ -204,11 +216,13 @@ ec.recover = function recover(msg, sig, j, compressed) { } catch (e) { return; } + try { key = secp256k1.recover(msg, sig, j, compressed); } catch (e) { return; } + return key; } @@ -248,22 +262,16 @@ ec.verify = function verify(msg, sig, key, historical, high) { if (key.length === 0) return false; - // 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 = ec.normalizeLength(sig); - if (secp256k1) { - // secp256k1 fails on high s values. This is - // bad for verifying historical data. - if (high) - sig = ec.toLowS(sig); - try { - // Import from DER. - sig = secp256k1.signatureImport(sig); + if (historical) + sig = secp256k1.signatureImportLax(sig); + else + sig = secp256k1.signatureImport(sig); + + if (high) + sig = secp256k1.signatureNormalize(sig); + result = secp256k1.verify(msg, sig, key); } catch (e) { result = false; @@ -272,6 +280,13 @@ ec.verify = function verify(msg, sig, key, historical, high) { return result; } + // 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 = ec.normalizeLength(sig); + // Make elliptic mimic secp256k1's // failure with high S values. if (!high && !ec.isLowS(sig)) @@ -446,14 +461,36 @@ ec.normalizeLength = function normalizeLength(sig) { */ ec.isLowS = function isLowS(sig) { - if (Buffer.isBuffer(sig)) { + var rs, s; + + if (secp256k1) { try { - sig = new ec.signature(sig); + rs = secp256k1.signatureImport(sig); + s = rs.slice(32, 64); } catch (e) { return false; } + + if (utils.equal(s, ZERO_S)) + return false; + + // If S is greater than half the order, + // it's too high. + if (utils.cmp(s, HALF_ORDER) > 0) + return false; + + return true; } + try { + sig = new ec.signature(sig); + } catch (e) { + return false; + } + + if (sig.s.cmpn(0) === 0) + return false; + // If S is greater than half the order, // it's too high. if (sig.s.cmp(ec.elliptic.nh) > 0) @@ -462,30 +499,6 @@ ec.isLowS = function isLowS(sig) { return true; }; -/** - * Lower the S value of a signature (used - * for verifying historical data). - * @param {Buffer} sig - DER formatted. - * @returns {Buffer} - */ - -ec.toLowS = function toLowS(sig) { - if (Buffer.isBuffer(sig)) { - try { - sig = new ec.signature(sig); - } catch (e) { - return sig; - } - } - - // If S is greater than half the order, - // it's too high. - if (sig.s.cmp(ec.elliptic.nh) > 0) - sig.s = ec.curve.n.sub(sig.s); - - return new Buffer(sig.toDER()); -}; - /* * Helpers */