From de7fc78ef0dcb5abe407e3ada932c88cd8f90b38 Mon Sep 17 00:00:00 2001 From: Chris Clark Date: Tue, 12 May 2015 11:39:18 -0700 Subject: [PATCH] Remove lint errors in sjcl-custom --- src/js/sjcl-custom/index.js | 1 + src/js/sjcl-custom/sjcl-ecc-pointextras.js | 16 +- src/js/sjcl-custom/sjcl-ecdsa-canonical.js | 5 +- src/js/sjcl-custom/sjcl-ecdsa-der.js | 21 +- .../sjcl-ecdsa-recoverablepublickey.js | 370 ++++++++++-------- src/js/sjcl-custom/sjcl-extramath.js | 69 ++-- src/js/sjcl-custom/sjcl-jacobi.js | 27 +- src/js/sjcl-custom/sjcl-montgomery.js | 2 + src/js/sjcl-custom/sjcl-ripemd160.js | 2 + src/js/sjcl-custom/sjcl-secp256k1.js | 49 +-- src/js/sjcl-custom/sjcl-validecc.js | 39 +- 11 files changed, 335 insertions(+), 266 deletions(-) diff --git a/src/js/sjcl-custom/index.js b/src/js/sjcl-custom/index.js index e49caabe..e807b2f4 100644 --- a/src/js/sjcl-custom/index.js +++ b/src/js/sjcl-custom/index.js @@ -1,3 +1,4 @@ +'use strict'; require('./sjcl-ecc-pointextras.js'); require('./sjcl-secp256k1.js'); require('./sjcl-ripemd160.js'); diff --git a/src/js/sjcl-custom/sjcl-ecc-pointextras.js b/src/js/sjcl-custom/sjcl-ecc-pointextras.js index 5bb277d9..36bd3241 100644 --- a/src/js/sjcl-custom/sjcl-ecc-pointextras.js +++ b/src/js/sjcl-custom/sjcl-ecc-pointextras.js @@ -1,11 +1,13 @@ +/* eslint new-cap: [2, {newIsCapExceptions: ["bn"]}] */ +'use strict'; var sjcl = require('sjcl'); /** * Check that the point is valid based on the method described in - * SEC 1: Elliptic Curve Cryptography, section 3.2.2.1: + * SEC 1: Elliptic Curve Cryptography, section 3.2.2.1: * Elliptic Curve Public Key Validation Primitive * http://www.secg.org/download/aid-780/sec1-v2.pdf * - * @returns {Boolean} + * @returns {Boolean} true if point is valid */ sjcl.ecc.point.prototype.isValidPoint = function() { @@ -49,19 +51,19 @@ sjcl.ecc.point.prototype.isValidPoint = function() { /** * Check that the point is on the curve * - * @returns {Boolean} + * @returns {Boolean} true if point is on the curve */ sjcl.ecc.point.prototype.isOnCurve = function() { var self = this; - var field_order = self.curve.r; var component_a = self.curve.a; var component_b = self.curve.b; var field_modulus = self.curve.field.modulus; var left_hand_side = self.y.mul(self.y).mod(field_modulus); - var right_hand_side = self.x.mul(self.x).mul(self.x).add(component_a.mul(self.x)).add(component_b).mod(field_modulus); + var right_hand_side = self.x.mul(self.x).mul(self.x).add( + component_a.mul(self.x)).add(component_b).mod(field_modulus); return left_hand_side.equals(right_hand_side); @@ -69,14 +71,14 @@ sjcl.ecc.point.prototype.isOnCurve = function() { sjcl.ecc.point.prototype.toString = function() { - return '(' + + return '(' + this.x.toString() + ', ' + this.y.toString() + ')'; }; sjcl.ecc.pointJac.prototype.toString = function() { - return '(' + + return '(' + this.x.toString() + ', ' + this.y.toString() + ', ' + this.z.toString() + diff --git a/src/js/sjcl-custom/sjcl-ecdsa-canonical.js b/src/js/sjcl-custom/sjcl-ecdsa-canonical.js index ca1b43d3..26c0502b 100644 --- a/src/js/sjcl-custom/sjcl-ecdsa-canonical.js +++ b/src/js/sjcl-custom/sjcl-ecdsa-canonical.js @@ -1,3 +1,4 @@ +'use strict'; var sjcl = require('sjcl'); sjcl.ecc.ecdsa.secretKey.prototype.canonicalizeSignature = function(rs) { @@ -5,8 +6,8 @@ sjcl.ecc.ecdsa.secretKey.prototype.canonicalizeSignature = function(rs) { R = this._curve.r, l = R.bitLength(); - var r = sjcl.bn.fromBits(w.bitSlice(rs,0,l)), - s = sjcl.bn.fromBits(w.bitSlice(rs,l,2*l)); + var r = sjcl.bn.fromBits(w.bitSlice(rs, 0, l)), + s = sjcl.bn.fromBits(w.bitSlice(rs, l, 2 * l)); // For a canonical signature we want the lower of two possible values for s // 0 < s <= n/2 diff --git a/src/js/sjcl-custom/sjcl-ecdsa-der.js b/src/js/sjcl-custom/sjcl-ecdsa-der.js index 1c13da49..111cebf7 100644 --- a/src/js/sjcl-custom/sjcl-ecdsa-der.js +++ b/src/js/sjcl-custom/sjcl-ecdsa-der.js @@ -1,3 +1,4 @@ +'use strict'; var sjcl = require('sjcl'); sjcl.ecc.ecdsa.secretKey.prototype.signDER = function(hash, paranoia) { @@ -9,16 +10,24 @@ sjcl.ecc.ecdsa.secretKey.prototype.encodeDER = function(rs) { R = this._curve.r, l = R.bitLength(); - var rb = sjcl.codec.bytes.fromBits(w.bitSlice(rs,0,l)), - sb = sjcl.codec.bytes.fromBits(w.bitSlice(rs,l,2*l)); + var rb = sjcl.codec.bytes.fromBits(w.bitSlice(rs, 0, l)), + sb = sjcl.codec.bytes.fromBits(w.bitSlice(rs, l, 2 * l)); // Drop empty leading bytes - while (!rb[0] && rb.length) rb.shift(); - while (!sb[0] && sb.length) sb.shift(); + while (!rb[0] && rb.length) { + rb.shift(); + } + while (!sb[0] && sb.length) { + sb.shift(); + } // If high bit is set, prepend an extra zero byte (DER signed integer) - if (rb[0] & 0x80) rb.unshift(0); - if (sb[0] & 0x80) sb.unshift(0); + if (rb[0] & 0x80) { + rb.unshift(0); + } + if (sb[0] & 0x80) { + sb.unshift(0); + } var buffer = [].concat( 0x30, diff --git a/src/js/sjcl-custom/sjcl-ecdsa-recoverablepublickey.js b/src/js/sjcl-custom/sjcl-ecdsa-recoverablepublickey.js index 65879237..3de08c3b 100644 --- a/src/js/sjcl-custom/sjcl-ecdsa-recoverablepublickey.js +++ b/src/js/sjcl-custom/sjcl-ecdsa-recoverablepublickey.js @@ -1,3 +1,7 @@ +/* eslint-disable valid-jsdoc */ +/* eslint new-cap: [2, {newIsCapExceptions: [ + "bn", "invalid", "point", "corrupt", "bug", "publicKey"]}] */ +'use strict'; var sjcl = require('sjcl'); /** @@ -7,121 +11,18 @@ var sjcl = require('sjcl'); * http://www.secg.org/download/aid-780/sec1-v2.pdf * * Implementation based on: - * https://github.com/bitcoinjs/bitcoinjs-lib/blob/89cf731ac7309b4f98994e3b4b67b7226020181f/src/ecdsa.js + * https://github.com/bitcoinjs/bitcoinjs-lib/blob/ + * 89cf731ac7309b4f98994e3b4b67b7226020181f/src/ecdsa.js */ // Defined here so that this value only needs to be calculated once var FIELD_MODULUS_PLUS_ONE_DIVIDED_BY_FOUR; /** - * Sign the given hash such that the public key, prepending an extra byte - * so that the public key will be recoverable from the signature + * Retrieve the r and s components of a signature * - * @param {bitArray} hash - * @param {Number} paranoia - * @returns {bitArray} Signature formatted as bitArray - */ -sjcl.ecc.ecdsa.secretKey.prototype.signWithRecoverablePublicKey = function(hash, paranoia, k_for_testing) { - - var self = this; - - // Convert hash to bits and determine encoding for output - var hash_bits; - if (typeof hash === 'object' && hash.length > 0 && typeof hash[0] === 'number') { - hash_bits = hash; - } else { - throw new sjcl.exception.invalid('hash. Must be a bitArray'); - } - - // Sign hash with standard, canonicalized method - var standard_signature = self.sign(hash_bits, paranoia, k_for_testing); - var canonical_signature = self.canonicalizeSignature(standard_signature); - - // Extract r and s signature components from canonical signature - var r_and_s = getRandSFromSignature(self._curve, canonical_signature); - - // Rederive public key - var public_key = self._curve.G.mult(sjcl.bn.fromBits(self.get())); - - // Determine recovery factor based on which possible value - // returns the correct public key - var recovery_factor = calculateRecoveryFactor(self._curve, r_and_s.r, r_and_s.s, hash_bits, public_key); - - // Prepend recovery_factor to signature and encode in DER - // The value_to_prepend should be 4 bytes total - var value_to_prepend = recovery_factor + 27; - - var final_signature_bits = sjcl.bitArray.concat([value_to_prepend], canonical_signature); - - // Return value in bits - return final_signature_bits; - -}; - - -/** - * Recover the public key from a signature created with the - * signWithRecoverablePublicKey method in this module - * - * @static - * - * @param {bitArray} hash - * @param {bitArray} signature - * @param {sjcl.ecc.curve} [sjcl.ecc.curves['k256']] curve - * @returns {sjcl.ecc.ecdsa.publicKey} Public key - */ -sjcl.ecc.ecdsa.publicKey.recoverFromSignature = function(hash, signature, curve) { - - if (!signature || signature instanceof sjcl.ecc.curve) { - throw new sjcl.exception.invalid('must supply hash and signature to recover public key'); - } - - if (!curve) { - curve = sjcl.ecc.curves['k256']; - } - - // Convert hash to bits and determine encoding for output - var hash_bits; - if (typeof hash === 'object' && hash.length > 0 && typeof hash[0] === 'number') { - hash_bits = hash; - } else { - throw new sjcl.exception.invalid('hash. Must be a bitArray'); - } - - var signature_bits; - if (typeof signature === 'object' && signature.length > 0 && typeof signature[0] === 'number') { - signature_bits = signature; - } else { - throw new sjcl.exception.invalid('signature. Must be a bitArray'); - } - - // Extract recovery_factor from first 4 bytes - var recovery_factor = signature_bits[0] - 27; - - if (recovery_factor < 0 || recovery_factor > 3) { - throw new sjcl.exception.invalid('signature. Signature must be generated with algorithm ' + - 'that prepends the recovery factor in order to recover the public key'); - } - - // Separate r and s values - var r_and_s = getRandSFromSignature(curve, signature_bits.slice(1)); - var signature_r = r_and_s.r; - var signature_s = r_and_s.s; - - // Recover public key using recovery_factor - var recovered_public_key_point = recoverPublicKeyPointFromSignature(curve, signature_r, signature_s, hash_bits, recovery_factor); - var recovered_public_key = new sjcl.ecc.ecdsa.publicKey(curve, recovered_public_key_point); - - return recovered_public_key; - -}; - - -/** - * Retrieve the r and s components of a signature - * - * @param {sjcl.ecc.curve} curve - * @param {bitArray} signature + * @param {sjcl.ecc.curve} curve - curve + * @param {bitArray} signature - signature * @returns {Object} Object with 'r' and 's' fields each as an sjcl.bn */ function getRandSFromSignature(curve, signature) { @@ -130,50 +31,51 @@ function getRandSFromSignature(curve, signature) { return { r: sjcl.bn.fromBits(sjcl.bitArray.bitSlice(signature, 0, r_length)), - s: sjcl.bn.fromBits(sjcl.bitArray.bitSlice(signature, r_length, sjcl.bitArray.bitLength(signature))) + s: sjcl.bn.fromBits(sjcl.bitArray.bitSlice( + signature, r_length, sjcl.bitArray.bitLength(signature))) }; -}; - +} /** - * Determine the recovery factor by trying all four - * possibilities and figuring out which results in the - * correct public key + * Verify a signature given the raw components + * using method defined in section 4.1.5: + * "Alternative Verifying Operation" * * @param {sjcl.ecc.curve} curve + * @param {sjcl.bn} e * @param {sjcl.bn} r * @param {sjcl.bn} s - * @param {bitArray} hash_bits - * @param {sjcl.ecc.point} original_public_key_point - * @returns {Number, 0-3} Recovery factor + * @param {sjcl.ecc.point} public_key_point + * @returns {Boolean} */ -function calculateRecoveryFactor(curve, r, s, hash_bits, original_public_key_point) { +function verify_raw(curve, e, r, s, public_key_point) { - var original_public_key_point_bits = original_public_key_point.toBits(); - - // TODO: verify that it is possible for the recovery_factor to be 2 or 3, - // we may only need 1 bit because the canonical signature might remove the - // possibility of us needing to "use the second candidate key" - for (var possible_factor = 0; possible_factor < 4; possible_factor++) { - - var resulting_public_key_point; - try { - resulting_public_key_point = recoverPublicKeyPointFromSignature(curve, r, s, hash_bits, possible_factor); - } catch (err) { - // console.log(err, err.stack); - continue; - } - - if (sjcl.bitArray.equal(resulting_public_key_point.toBits(), original_public_key_point_bits)) { - return possible_factor; - } + var field_order = curve.r; + // Return false if r is out of bounds + if ((new sjcl.bn(1)).greaterEquals(r) + || r.greaterEquals(new sjcl.bn(field_order))) { + return false; } - throw new sjcl.exception.bug('unable to calculate recovery factor from signature'); + // Return false if s is out of bounds + if ((new sjcl.bn(1)).greaterEquals(s) + || s.greaterEquals(new sjcl.bn(field_order))) { + return false; + } -}; + // Check that r = (u1 + u2)G + // u1 = e x s^-1 (mod field_order) + // u2 = r x s^-1 (mod field_order) + var s_mod_inverse_field_order = s.inverseMod(field_order); + var u1 = e.mul(s_mod_inverse_field_order).mod(field_order); + var u2 = r.mul(s_mod_inverse_field_order).mod(field_order); + var point_computed = curve.G.mult2(u1, u2, public_key_point); + + return r.equals(point_computed.x.mod(field_order)); + +} /** * Recover the public key from the signature. @@ -185,7 +87,8 @@ function calculateRecoveryFactor(curve, r, s, hash_bits, original_public_key_poi * @param {Number, 0-3} recovery_factor * @returns {sjcl.point} Public key corresponding to signature */ -function recoverPublicKeyPointFromSignature(curve, signature_r, signature_s, hash_bits, recovery_factor) { +function recoverPublicKeyPointFromSignature(curve, signature_r, signature_s, + hash_bits, recovery_factor) { var field_order = curve.r; var field_modulus = curve.field.modulus; @@ -218,9 +121,12 @@ function recoverPublicKeyPointFromSignature(curve, signature_r, signature_s, has } // step 1.2 and 1.3 convert x to an elliptic curve point - // Following formula in section 2.3.4 Octet-String-to-Elliptic-Curve-Point Conversion - var alpha = x.mul(x).mul(x).add(curve.a.mul(x)).add(curve.b).mod(field_modulus); - var beta = alpha.powermodMontgomery(FIELD_MODULUS_PLUS_ONE_DIVIDED_BY_FOUR, field_modulus); + // Following formula in section 2.3.4 Octet-String-to-Elliptic-Curve-Point + // Conversion + var alpha = x.mul(x).mul(x).add(curve.a.mul(x)).add(curve.b).mod( + field_modulus); + var beta = alpha.powermodMontgomery(FIELD_MODULUS_PLUS_ONE_DIVIDED_BY_FOUR, + field_modulus); // If beta is even but y isn't or // if beta is odd and y is even @@ -240,7 +146,8 @@ function recoverPublicKeyPointFromSignature(curve, signature_r, signature_s, has // step 1.4 check that R is valid and R x field_order !== infinity // TODO: add check for R x field_order === infinity if (!generated_point_R.isValidPoint()) { - throw new sjcl.exception.corrupt('point R. Not a valid point on the curve. Cannot recover public key'); + throw new sjcl.exception.corrupt( + 'point R. Not a valid point on the curve. Cannot recover public key'); } // step 1.5 Compute e from M @@ -250,59 +157,176 @@ function recoverPublicKeyPointFromSignature(curve, signature_r, signature_s, has // step 1.6 Compute Q = r^-1 (sR - eG) // console.log('r: ', signature_r); var signature_r_inv = signature_r.inverseMod(field_order); - var public_key_point = generated_point_R.mult2(signature_s, message_e_neg, curve.G).mult(signature_r_inv); + var public_key_point = generated_point_R.mult2(signature_s, message_e_neg, + curve.G).mult(signature_r_inv); // Validate public key point if (!public_key_point.isValidPoint()) { - throw new sjcl.exception.corrupt('public_key_point. Not a valid point on the curve. Cannot recover public key'); + throw new sjcl.exception.corrupt('public_key_point. Not a valid point' + + ' on the curve. Cannot recover public key'); } // Verify that this public key matches the signature - if (!verify_raw(curve, message_e, signature_r, signature_s, public_key_point)) { + if (!verify_raw(curve, message_e, signature_r, signature_s, + public_key_point)) { throw new sjcl.exception.corrupt('cannot recover public key'); } return public_key_point; +} + +/** + * Determine the recovery factor by trying all four + * possibilities and figuring out which results in the + * correct public key + * + * @param {sjcl.ecc.curve} curve + * @param {sjcl.bn} r + * @param {sjcl.bn} s + * @param {bitArray} hash_bits + * @param {sjcl.ecc.point} original_public_key_point + * @returns {Number, 0-3} Recovery factor + */ +function calculateRecoveryFactor(curve, r, s, hash_bits, + original_public_key_point) { + + var original_public_key_point_bits = original_public_key_point.toBits(); + + // TODO: verify that it is possible for the recovery_factor to be 2 or 3, + // we may only need 1 bit because the canonical signature might remove the + // possibility of us needing to "use the second candidate key" + for (var possible_factor = 0; possible_factor < 4; possible_factor++) { + + var resulting_public_key_point; + try { + resulting_public_key_point = recoverPublicKeyPointFromSignature( + curve, r, s, hash_bits, possible_factor); + } catch (err) { + // console.log(err, err.stack); + continue; + } + + if (sjcl.bitArray.equal(resulting_public_key_point.toBits(), + original_public_key_point_bits)) { + return possible_factor; + } + + } + + throw new sjcl.exception.bug( + 'unable to calculate recovery factor from signature'); +} + +/** + * Sign the given hash such that the public key, prepending an extra byte + * so that the public key will be recoverable from the signature + * + * @param {bitArray} hash - hash to sign + * @param {Number} paranoia - minimum entropy required + * @param {Number} k_for_testing - fixed k value to bypass PRNG + * @returns {bitArray} Signature formatted as bitArray + */ +sjcl.ecc.ecdsa.secretKey.prototype.signWithRecoverablePublicKey = function( + hash, paranoia, k_for_testing) { + + var self = this; + + // Convert hash to bits and determine encoding for output + var hash_bits; + if (typeof hash === 'object' && hash.length > 0 + && typeof hash[0] === 'number') { + hash_bits = hash; + } else { + throw new sjcl.exception.invalid('hash. Must be a bitArray'); + } + + // Sign hash with standard, canonicalized method + var standard_signature = self.sign(hash_bits, paranoia, k_for_testing); + var canonical_signature = self.canonicalizeSignature(standard_signature); + + // Extract r and s signature components from canonical signature + var r_and_s = getRandSFromSignature(self._curve, canonical_signature); + + // Rederive public key + var public_key = self._curve.G.mult(sjcl.bn.fromBits(self.get())); + + // Determine recovery factor based on which possible value + // returns the correct public key + var recovery_factor = calculateRecoveryFactor(self._curve, r_and_s.r, + r_and_s.s, hash_bits, public_key); + + // Prepend recovery_factor to signature and encode in DER + // The value_to_prepend should be 4 bytes total + var value_to_prepend = recovery_factor + 27; + + var final_signature_bits = sjcl.bitArray.concat([value_to_prepend], + canonical_signature); + + // Return value in bits + return final_signature_bits; }; /** - * Verify a signature given the raw components - * using method defined in section 4.1.5: - * "Alternative Verifying Operation" + * Recover the public key from a signature created with the + * signWithRecoverablePublicKey method in this module * - * @param {sjcl.ecc.curve} curve - * @param {sjcl.bn} e - * @param {sjcl.bn} r - * @param {sjcl.bn} s - * @param {sjcl.ecc.point} public_key_point - * @returns {Boolean} + * @static + * + * @param {bitArray} hash + * @param {bitArray} signature + * @param {sjcl.ecc.curve} [curve=sjcl.ecc.curves['k256']] + * @returns {sjcl.ecc.ecdsa.publicKey} Public key */ -function verify_raw(curve, e, r, s, public_key_point) { +sjcl.ecc.ecdsa.publicKey.recoverFromSignature = function( + hash, signature, curve) { - var field_order = curve.r; - - // Return false if r is out of bounds - if ((new sjcl.bn(1)).greaterEquals(r) || r.greaterEquals(new sjcl.bn(field_order))) { - return false; + if (!signature || signature instanceof sjcl.ecc.curve) { + throw new sjcl.exception.invalid( + 'must supply hash and signature to recover public key'); } - // Return false if s is out of bounds - if ((new sjcl.bn(1)).greaterEquals(s) || s.greaterEquals(new sjcl.bn(field_order))) { - return false; + if (!curve) { + curve = sjcl.ecc.curves.k256; } - // Check that r = (u1 + u2)G - // u1 = e x s^-1 (mod field_order) - // u2 = r x s^-1 (mod field_order) - var s_mod_inverse_field_order = s.inverseMod(field_order); - var u1 = e.mul(s_mod_inverse_field_order).mod(field_order); - var u2 = r.mul(s_mod_inverse_field_order).mod(field_order); + // Convert hash to bits and determine encoding for output + var hash_bits; + if (typeof hash === 'object' && hash.length > 0 + && typeof hash[0] === 'number') { + hash_bits = hash; + } else { + throw new sjcl.exception.invalid('hash. Must be a bitArray'); + } - var point_computed = curve.G.mult2(u1, u2, public_key_point); + var signature_bits; + if (typeof signature === 'object' && signature.length > 0 + && typeof signature[0] === 'number') { + signature_bits = signature; + } else { + throw new sjcl.exception.invalid('signature. Must be a bitArray'); + } - return r.equals(point_computed.x.mod(field_order)); + // Extract recovery_factor from first 4 bytes + var recovery_factor = signature_bits[0] - 27; + if (recovery_factor < 0 || recovery_factor > 3) { + throw new sjcl.exception.invalid( + 'signature. Signature must be generated with algorithm ' + + 'that prepends the recovery factor in order to recover the public key'); + } + + // Separate r and s values + var r_and_s = getRandSFromSignature(curve, signature_bits.slice(1)); + var signature_r = r_and_s.r; + var signature_s = r_and_s.s; + + // Recover public key using recovery_factor + var recovered_public_key_point = recoverPublicKeyPointFromSignature( + curve, signature_r, signature_s, hash_bits, recovery_factor); + var recovered_public_key = new sjcl.ecc.ecdsa.publicKey( + curve, recovered_public_key_point); + + return recovered_public_key; }; - diff --git a/src/js/sjcl-custom/sjcl-extramath.js b/src/js/sjcl-custom/sjcl-extramath.js index 3967ff80..11928f9f 100755 --- a/src/js/sjcl-custom/sjcl-extramath.js +++ b/src/js/sjcl-custom/sjcl-extramath.js @@ -1,10 +1,14 @@ +/* eslint new-cap: [2, {newIsCapExceptions: ["bn"]}] */ +'use strict'; var sjcl = require('sjcl'); sjcl.bn.ZERO = new sjcl.bn(0); -/** [ this / that , this % that ] */ -sjcl.bn.prototype.divRem = function (that) { - if (typeof(that) !== "object") { that = new this._class(that); } +/* [ this / that , this % that ] */ +sjcl.bn.prototype.divRem = function(that) { + if (typeof that !== 'object') { + that = new this._class(that); + } var thisa = this.abs(), thata = that.abs(), quot = new this._class(0), ci = 0; if (!thisa.greaterEquals(thata)) { @@ -27,8 +31,8 @@ sjcl.bn.prototype.divRem = function (that) { return [quot, thisa]; }; -/** this /= that (rounded to nearest int) */ -sjcl.bn.prototype.divRound = function (that) { +/* this /= that (rounded to nearest int) */ +sjcl.bn.prototype.divRound = function(that) { var dr = this.divRem(that), quot = dr[0], rem = dr[1]; if (rem.doubleM().greaterEquals(that)) { @@ -38,32 +42,33 @@ sjcl.bn.prototype.divRound = function (that) { return quot; }; -/** this /= that (rounded down) */ -sjcl.bn.prototype.div = function (that) { +/* this /= that (rounded down) */ +sjcl.bn.prototype.div = function(that) { var dr = this.divRem(that); return dr[0]; }; -sjcl.bn.prototype.sign = function () { +sjcl.bn.prototype.sign = function() { return this.greaterEquals(sjcl.bn.ZERO) ? 1 : -1; }; -/** -this */ -sjcl.bn.prototype.neg = function () { +/* -this */ +sjcl.bn.prototype.neg = function() { return sjcl.bn.ZERO.sub(this); }; -/** |this| */ -sjcl.bn.prototype.abs = function () { +/* |this| */ +sjcl.bn.prototype.abs = function() { if (this.sign() === -1) { return this.neg(); - } else return this; + } + return this; }; -/** this >> that */ -sjcl.bn.prototype.shiftRight = function (that) { - if ("number" !== typeof that) { - throw new Error("shiftRight expects a number"); +/* this >> that */ +sjcl.bn.prototype.shiftRight = function(that) { + if (typeof that !== 'number') { + throw new Error('shiftRight expects a number'); } that = +that; @@ -86,10 +91,10 @@ sjcl.bn.prototype.shiftRight = function (that) { return a; }; -/** this >> that */ -sjcl.bn.prototype.shiftLeft = function (that) { - if ("number" !== typeof that) { - throw new Error("shiftLeft expects a number"); +/* this >> that */ +sjcl.bn.prototype.shiftLeft = function(that) { + if (typeof that !== 'number') { + throw new Error('shiftLeft expects a number'); } that = +that; @@ -112,28 +117,32 @@ sjcl.bn.prototype.shiftLeft = function (that) { return a; }; -/** (int)this */ +/* (int)this */ // NOTE Truncates to 32-bit integer -sjcl.bn.prototype.toNumber = function () { +sjcl.bn.prototype.toNumber = function() { return this.limbs[0] | 0; }; -/** find n-th bit, 0 = LSB */ -sjcl.bn.prototype.testBit = function (bitIndex) { +/* find n-th bit, 0 = LSB */ +sjcl.bn.prototype.testBit = function(bitIndex) { var limbIndex = Math.floor(bitIndex / this.radix); var bitIndexInLimb = bitIndex % this.radix; - if (limbIndex >= this.limbs.length) return 0; + if (limbIndex >= this.limbs.length) { + return 0; + } return (this.limbs[limbIndex] >>> bitIndexInLimb) & 1; }; -/** set n-th bit, 0 = LSB */ -sjcl.bn.prototype.setBitM = function (bitIndex) { +/* set n-th bit, 0 = LSB */ +sjcl.bn.prototype.setBitM = function(bitIndex) { var limbIndex = Math.floor(bitIndex / this.radix); var bitIndexInLimb = bitIndex % this.radix; - while (limbIndex >= this.limbs.length) this.limbs.push(0); + while (limbIndex >= this.limbs.length) { + this.limbs.push(0); + } this.limbs[limbIndex] |= 1 << bitIndexInLimb; @@ -142,6 +151,6 @@ sjcl.bn.prototype.setBitM = function (bitIndex) { return this; }; -sjcl.bn.prototype.modInt = function (n) { +sjcl.bn.prototype.modInt = function(n) { return this.toNumber() % n; }; diff --git a/src/js/sjcl-custom/sjcl-jacobi.js b/src/js/sjcl-custom/sjcl-jacobi.js index eed72dd9..c99f62ff 100644 --- a/src/js/sjcl-custom/sjcl-jacobi.js +++ b/src/js/sjcl-custom/sjcl-jacobi.js @@ -1,23 +1,33 @@ +/* eslint new-cap: [2, {newIsCapExceptions: ["bn"]}] */ +'use strict'; var sjcl = require('sjcl'); -sjcl.bn.prototype.jacobi = function (that) { - var a = this; +sjcl.bn.prototype.jacobi = function(that) { + var self = this; that = new sjcl.bn(that); - if (that.sign() === -1) return; + if (that.sign() === -1) { + return undefined; + } // 1. If a = 0 then return(0). - if (a.equals(0)) { return 0; } + if (self.equals(0)) { + return 0; + } // 2. If a = 1 then return(1). - if (a.equals(1)) { return 1; } + if (self.equals(1)) { + return 1; + } var s = 0; // 3. Write a = 2^e * a1, where a1 is odd. var e = 0; - while (!a.testBit(e)) e++; - var a1 = a.shiftRight(e); + while (!self.testBit(e)) { + e++; + } + var a1 = self.shiftRight(e); // 4. If e is even then set s ← 1. if ((e & 1) === 0) { @@ -41,7 +51,6 @@ sjcl.bn.prototype.jacobi = function (that) { if (a1.equals(1)) { return s; - } else { - return s * that.mod(a1).jacobi(a1); } + return s * that.mod(a1).jacobi(a1); }; diff --git a/src/js/sjcl-custom/sjcl-montgomery.js b/src/js/sjcl-custom/sjcl-montgomery.js index 06a24844..f05ffb10 100644 --- a/src/js/sjcl-custom/sjcl-montgomery.js +++ b/src/js/sjcl-custom/sjcl-montgomery.js @@ -1,3 +1,5 @@ +/* eslint-disable */ +/* this is implemented in sjcl, but has not yet been released as of v1.0.2 */ var sjcl = require('sjcl'); sjcl.bn.prototype.invDigit = function () diff --git a/src/js/sjcl-custom/sjcl-ripemd160.js b/src/js/sjcl-custom/sjcl-ripemd160.js index 3c80178c..c434bd32 100755 --- a/src/js/sjcl-custom/sjcl-ripemd160.js +++ b/src/js/sjcl-custom/sjcl-ripemd160.js @@ -1,3 +1,5 @@ +/* eslint-disable */ +/* this is implemented in sjcl, but has not yet been released as of v1.0.2 */ var sjcl = require('sjcl'); /** @fileOverview Javascript RIPEMD-160 implementation. diff --git a/src/js/sjcl-custom/sjcl-secp256k1.js b/src/js/sjcl-custom/sjcl-secp256k1.js index ae54a6a1..60afd538 100755 --- a/src/js/sjcl-custom/sjcl-secp256k1.js +++ b/src/js/sjcl-custom/sjcl-secp256k1.js @@ -1,10 +1,12 @@ +/* eslint new-cap: [2, {newIsCapExceptions: ["pointJac"]}] */ +'use strict'; var sjcl = require('sjcl'); // ----- for secp256k1 ------ -sjcl.ecc.point.prototype.toBytesCompressed = function () { - var header = this.y.mod(2).toString() == "0x0" ? 0x02 : 0x03; - return [header].concat(sjcl.codec.bytes.fromBits(this.x.toBits())) +sjcl.ecc.point.prototype.toBytesCompressed = function() { + var header = this.y.mod(2).toString() === '0x0' ? 0x02 : 0x03; + return [header].concat(sjcl.codec.bytes.fromBits(this.x.toBits())); }; // Replace point addition and doubling algorithms @@ -14,49 +16,50 @@ sjcl.ecc.point.prototype.toBytesCompressed = function () { // only works for a=-3 Jacobian curve. It's much // faster than the generic implementation sjcl.ecc.pointJac.prototype.add = function(T) { - var S = this; - if (S.curve !== T.curve) { - throw("sjcl.ecc.add(): Points must be on the same curve to add them!"); + var self = this; + if (self.curve !== T.curve) { + throw ('sjcl.ecc.add(): Points must be on the same curve to add them!'); } - if (S.isIdentity) { + if (self.isIdentity) { return T.toJac(); } else if (T.isIdentity) { - return S; + return self; } - var z1z1 = S.z.square(); - var h = T.x.mul(z1z1).subM(S.x); - var s2 = T.y.mul(S.z).mul(z1z1); + var z1z1 = self.z.square(); + var h = T.x.mul(z1z1).subM(self.x); + var s2 = T.y.mul(self.z).mul(z1z1); if (h.equals(0)) { - if (S.y.equals(T.y.mul(z1z1.mul(S.z)))) { + if (self.y.equals(T.y.mul(z1z1.mul(self.z)))) { // same point - return S.doubl(); - } else { - // inverses - return new sjcl.ecc.pointJac(S.curve); + return self.doubl(); } + // inverses + return new sjcl.ecc.pointJac(self.curve); } var hh = h.square(); var i = hh.copy().doubleM().doubleM(); var j = h.mul(i); - var r = s2.sub(S.y).doubleM(); - var v = S.x.mul(i); + var r = s2.sub(self.y).doubleM(); + var v = self.x.mul(i); var x = r.square().subM(j).subM(v.copy().doubleM()); - var y = r.mul(v.sub(x)).subM(S.y.mul(j).doubleM()); - var z = S.z.add(h).square().subM(z1z1).subM(hh); + var y = r.mul(v.sub(x)).subM(self.y.mul(j).doubleM()); + var z = self.z.add(h).square().subM(z1z1).subM(hh); - return new sjcl.ecc.pointJac(this.curve,x,y,z); + return new sjcl.ecc.pointJac(this.curve, x, y, z); }; // This is a custom doubling algorithm that // only works for a=-3 Jacobian curve. It's much // faster than the generic implementation -sjcl.ecc.pointJac.prototype.doubl = function () { - if (this.isIdentity) { return this; } +sjcl.ecc.pointJac.prototype.doubl = function() { + if (this.isIdentity) { + return this; + } var a = this.x.square(); var b = this.y.square(); diff --git a/src/js/sjcl-custom/sjcl-validecc.js b/src/js/sjcl-custom/sjcl-validecc.js index 1e699d8b..07087a76 100644 --- a/src/js/sjcl-custom/sjcl-validecc.js +++ b/src/js/sjcl-custom/sjcl-validecc.js @@ -1,40 +1,47 @@ +/* eslint new-cap: [2, {newIsCapExceptions: ["corrupt"]}] */ +'use strict'; var sjcl = require('sjcl'); -sjcl.ecc.ecdsa.secretKey.prototype.sign = function(hash, paranoia, k_for_testing) { +sjcl.ecc.ecdsa.secretKey.prototype.sign = function(hash, paranoia, + k_for_testing) { var R = this._curve.r, l = R.bitLength(); // k_for_testing should ONLY BE SPECIFIED FOR TESTING // specifying it will make the signature INSECURE var k; - if (typeof k_for_testing === 'object' && k_for_testing.length > 0 && typeof k_for_testing[0] === 'number') { + if (typeof k_for_testing === 'object' && k_for_testing.length > 0 + && typeof k_for_testing[0] === 'number') { k = k_for_testing; - } else if (typeof k_for_testing === 'string' && /^[0-9a-fA-F]+$/.test(k_for_testing)) { - k = sjcl.bn.fromBits(sjcl.codec.hex.toBits(k_for_testing)); + } else if (typeof k_for_testing === 'string' + && /^[0-9a-fA-F]+$/.test(k_for_testing)) { + k = sjcl.bn.fromBits(sjcl.codec.hex.toBits(k_for_testing)); } else { // This is the only option that should be used in production k = sjcl.bn.random(R.sub(1), paranoia).add(1); } var r = this._curve.G.mult(k).x.mod(R); - var s = sjcl.bn.fromBits(hash).add(r.mul(this._exponent)).mul(k.inverseMod(R)).mod(R); + var s = sjcl.bn.fromBits(hash).add(r.mul(this._exponent)) + .mul(k.inverseMod(R)).mod(R); return sjcl.bitArray.concat(r.toBits(l), s.toBits(l)); }; sjcl.ecc.ecdsa.publicKey.prototype.verify = function(hash, rs) { - var w = sjcl.bitArray, - R = this._curve.r, - l = R.bitLength(), - r = sjcl.bn.fromBits(w.bitSlice(rs,0,l)), - s = sjcl.bn.fromBits(w.bitSlice(rs,l,2*l)), - sInv = s.inverseMod(R), - hG = sjcl.bn.fromBits(hash).mul(sInv).mod(R), - hA = r.mul(sInv).mod(R), - r2 = this._curve.G.mult2(hG, hA, this._point).x; + var w = sjcl.bitArray; + var R = this._curve.r; + var l = R.bitLength(); + var r = sjcl.bn.fromBits(w.bitSlice(rs, 0, l)); + var s = sjcl.bn.fromBits(w.bitSlice(rs, l, 2 * l)); + var sInv = s.inverseMod(R); + var hG = sjcl.bn.fromBits(hash).mul(sInv).mod(R); + var hA = r.mul(sInv).mod(R); + var r2 = this._curve.G.mult2(hG, hA, this._point).x; - if (r.equals(0) || s.equals(0) || r.greaterEquals(R) || s.greaterEquals(R) || !r2.equals(r)) { - throw (new sjcl.exception.corrupt("signature didn't check out")); + if (r.equals(0) || s.equals(0) || r.greaterEquals(R) || s.greaterEquals(R) + || !r2.equals(r)) { + throw (new sjcl.exception.corrupt('signature didn\'t check out')); } return true; };