From 35ae968d9fe3d4cfcd4819e225a7bf836eec9dfb Mon Sep 17 00:00:00 2001 From: Nicholas Dudfield Date: Thu, 4 Jun 2015 16:19:31 +0700 Subject: [PATCH] Remove sjcl-custom in favor of sjcl-extended module in separate repo --- npm-shrinkwrap.json | 12 +- package.json | 3 +- src/core/sjcl-custom/index.js | 8 - src/core/sjcl-custom/sjcl-ecc-pointextras.js | 86 ----- src/core/sjcl-custom/sjcl-ecdsa-canonical.js | 20 -- src/core/sjcl-custom/sjcl-ecdsa-der.js | 45 --- .../sjcl-ecdsa-recoverablepublickey.js | 325 ------------------ src/core/sjcl-custom/sjcl-extramath.js | 156 --------- src/core/sjcl-custom/sjcl-secp256k1.js | 81 ----- src/core/sjcl-custom/sjcl-validecc.js | 47 --- src/core/utils.js | 3 +- test/sjcl-ecdsa-canonical-test.js | 27 -- test/sjcl-ecdsa-recoverablepublickey-test.js | 260 -------------- test/sjcl-extramath-test.js | 51 --- test/sjcl-montgomery.js | 100 ------ 15 files changed, 12 insertions(+), 1212 deletions(-) delete mode 100644 src/core/sjcl-custom/index.js delete mode 100644 src/core/sjcl-custom/sjcl-ecc-pointextras.js delete mode 100644 src/core/sjcl-custom/sjcl-ecdsa-canonical.js delete mode 100644 src/core/sjcl-custom/sjcl-ecdsa-der.js delete mode 100644 src/core/sjcl-custom/sjcl-ecdsa-recoverablepublickey.js delete mode 100755 src/core/sjcl-custom/sjcl-extramath.js delete mode 100755 src/core/sjcl-custom/sjcl-secp256k1.js delete mode 100644 src/core/sjcl-custom/sjcl-validecc.js delete mode 100644 test/sjcl-ecdsa-canonical-test.js delete mode 100644 test/sjcl-ecdsa-recoverablepublickey-test.js delete mode 100644 test/sjcl-extramath-test.js delete mode 100644 test/sjcl-montgomery.js diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index b284b2f6..e2acbdae 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -66,9 +66,17 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/simple-asyncify/-/simple-asyncify-0.1.0.tgz" }, - "sjcl": { + "sjcl-extended": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sjcl/-/sjcl-1.0.3.tgz" + "from": "ripple/sjcl-extended#1.0.3", + "resolved": "git://github.com/ripple/sjcl-extended.git#908218e0db4fccd08c4e3f1f7269b72f8d93c270", + "dependencies": { + "sjcl": { + "version": "1.0.3", + "from": "sjcl@>=1.0.3 <2.0.0", + "resolved": "https://registry.npmjs.org/sjcl/-/sjcl-1.0.3.tgz" + } + } }, "ws": { "version": "0.7.2", diff --git a/package.json b/package.json index dcc4a722..71d284a1 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "ripple-lib-transactionparser": "^0.3.2", "ripple-wallet-generator": "^1.0.3", "simple-asyncify": "^0.1.0", - "sjcl": "^1.0.3", + "sjcl-extended": "ripple/sjcl-extended#1.0.3", "ws": "~0.7.1" }, "devDependencies": { @@ -59,7 +59,6 @@ "compile": "babel -i runtime -d dist/npm/ src/", "compile-with-source-maps": "babel -i runtime -s -t -d dist/npm/ src/", "prepublish": "npm run compile", - "postinstall": "cd node_modules/sjcl; ./configure --with-all --compress=none; make", "test": "istanbul test _mocha", "coveralls": "cat ./coverage/lcov.info | coveralls", "lint": "if ! [ -f eslintrc ]; then curl -o eslintrc 'https://raw.githubusercontent.com/ripple/javascript-style-guide/es6/eslintrc'; fi; eslint --reset -c eslintrc src/*.js", diff --git a/src/core/sjcl-custom/index.js b/src/core/sjcl-custom/index.js deleted file mode 100644 index 7c0b9c2f..00000000 --- a/src/core/sjcl-custom/index.js +++ /dev/null @@ -1,8 +0,0 @@ -'use strict'; -require('./sjcl-ecc-pointextras.js'); -require('./sjcl-secp256k1.js'); -require('./sjcl-extramath.js'); -require('./sjcl-validecc.js'); -require('./sjcl-ecdsa-canonical.js'); -require('./sjcl-ecdsa-der.js'); -require('./sjcl-ecdsa-recoverablepublickey.js'); diff --git a/src/core/sjcl-custom/sjcl-ecc-pointextras.js b/src/core/sjcl-custom/sjcl-ecc-pointextras.js deleted file mode 100644 index 36bd3241..00000000 --- a/src/core/sjcl-custom/sjcl-ecc-pointextras.js +++ /dev/null @@ -1,86 +0,0 @@ -/* 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: - * Elliptic Curve Public Key Validation Primitive - * http://www.secg.org/download/aid-780/sec1-v2.pdf - * - * @returns {Boolean} true if point is valid - */ -sjcl.ecc.point.prototype.isValidPoint = function() { - - var self = this; - - var field_modulus = self.curve.field.modulus; - - if (self.isIdentity) { - return false; - } - - // Check that coordinatres are in bounds - // Return false if x < 1 or x > (field_modulus - 1) - if (((new sjcl.bn(1).greaterEquals(self.x)) && - !self.x.equals(1)) || - (self.x.greaterEquals(field_modulus.sub(1))) && - !self.x.equals(1)) { - - return false; - } - - // Return false if y < 1 or y > (field_modulus - 1) - if (((new sjcl.bn(1).greaterEquals(self.y)) && - !self.y.equals(1)) || - (self.y.greaterEquals(field_modulus.sub(1))) && - !self.y.equals(1)) { - - return false; - } - - if (!self.isOnCurve()) { - return false; - } - - // TODO check to make sure point is a scalar multiple of base_point - - return true; - -}; - -/** - * Check that the point is on the curve - * - * @returns {Boolean} true if point is on the curve - */ -sjcl.ecc.point.prototype.isOnCurve = function() { - - var self = this; - - 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); - - return left_hand_side.equals(right_hand_side); - -}; - - -sjcl.ecc.point.prototype.toString = function() { - return '(' + - this.x.toString() + ', ' + - this.y.toString() + - ')'; -}; - -sjcl.ecc.pointJac.prototype.toString = function() { - return '(' + - this.x.toString() + ', ' + - this.y.toString() + ', ' + - this.z.toString() + - ')'; -}; diff --git a/src/core/sjcl-custom/sjcl-ecdsa-canonical.js b/src/core/sjcl-custom/sjcl-ecdsa-canonical.js deleted file mode 100644 index 26c0502b..00000000 --- a/src/core/sjcl-custom/sjcl-ecdsa-canonical.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict'; -var sjcl = require('sjcl'); - -sjcl.ecc.ecdsa.secretKey.prototype.canonicalizeSignature = function(rs) { - var w = sjcl.bitArray, - 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)); - - // For a canonical signature we want the lower of two possible values for s - // 0 < s <= n/2 - if (!R.copy().halveM().greaterEquals(s)) { - s = R.sub(s); - } - - return w.concat(r.toBits(l), s.toBits(l)); -}; - diff --git a/src/core/sjcl-custom/sjcl-ecdsa-der.js b/src/core/sjcl-custom/sjcl-ecdsa-der.js deleted file mode 100644 index 111cebf7..00000000 --- a/src/core/sjcl-custom/sjcl-ecdsa-der.js +++ /dev/null @@ -1,45 +0,0 @@ -'use strict'; -var sjcl = require('sjcl'); - -sjcl.ecc.ecdsa.secretKey.prototype.signDER = function(hash, paranoia) { - return this.encodeDER(this.sign(hash, paranoia)); -}; - -sjcl.ecc.ecdsa.secretKey.prototype.encodeDER = function(rs) { - var w = sjcl.bitArray, - 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)); - - // Drop empty leading bytes - 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); - } - - var buffer = [].concat( - 0x30, - 4 + rb.length + sb.length, - 0x02, - rb.length, - rb, - 0x02, - sb.length, - sb - ); - - return sjcl.codec.bytes.toBits(buffer); -}; - diff --git a/src/core/sjcl-custom/sjcl-ecdsa-recoverablepublickey.js b/src/core/sjcl-custom/sjcl-ecdsa-recoverablepublickey.js deleted file mode 100644 index 8b5e338c..00000000 --- a/src/core/sjcl-custom/sjcl-ecdsa-recoverablepublickey.js +++ /dev/null @@ -1,325 +0,0 @@ -/* eslint-disable valid-jsdoc */ -/* eslint new-cap: [2, {newIsCapExceptions: [ - "bn", "invalid", "point", "corrupt", "bug", "publicKey"]}] */ -'use strict'; -const sjcl = require('sjcl'); - -/** - * This module uses the public key recovery method - * described in SEC 1: Elliptic Curve Cryptography, - * section 4.1.6, "Public Key Recovery Operation". - * http://www.secg.org/download/aid-780/sec1-v2.pdf - * - * Implementation based on: - * https://github.com/bitcoinjs/bitcoinjs-lib/blob/ - * 89cf731ac7309b4f98994e3b4b67b7226020181f/src/ecdsa.js - */ - -// Defined here so that this value only needs to be calculated once -let FIELD_MODULUS_PLUS_ONE_DIVIDED_BY_FOUR; - -/** - * Retrieve the r and s components of a 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) { - - const r_length = curve.r.bitLength(); - - 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))) - }; -} - -/** - * 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 {sjcl.ecc.point} public_key_point - * @returns {Boolean} - */ -function verify_raw(curve, e, r, s, public_key_point) { - - const 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; - } - - // 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) - const s_mod_inverse_field_order = s.inverseMod(field_order); - const u1 = e.mul(s_mod_inverse_field_order).mod(field_order); - const u2 = r.mul(s_mod_inverse_field_order).mod(field_order); - - const 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. - * - * @param {sjcl.ecc.curve} curve - * @param {sjcl.bn} r - * @param {sjcl.bn} s - * @param {bitArray} hash_bits - * @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) { - - const field_order = curve.r; - const field_modulus = curve.field.modulus; - - // The less significant bit specifies whether the y coordinate - // of the compressed point is even or not. - const compressed_point_y_coord_is_even = recovery_factor & 1; - - // The more significant bit specifies whether we should use the - // first or second candidate key. - const use_second_candidate_key = (recovery_factor & 2) >> 1; - - // Calculate (field_order + 1) / 4 - if (!FIELD_MODULUS_PLUS_ONE_DIVIDED_BY_FOUR) { - FIELD_MODULUS_PLUS_ONE_DIVIDED_BY_FOUR = field_modulus.add(1).div(4); - } - - // In the paper they write "1. For j from 0 to h do the following..." - // That is not necessary here because we are given the recovery_factor - // step 1.1 Let x = r + jn - // Here "j" is either 0 or 1 - let x; - if (use_second_candidate_key) { - x = signature_r.add(field_order); - } else { - x = signature_r; - } - - // 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 - const alpha = x.mul(x).mul(x).add(curve.a.mul(x)).add(curve.b).mod( - field_modulus); - const beta = alpha.powermod(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 - // then subtract beta from the field_modulus - let y; - const beta_is_even = beta.mod(2).equals(0); - if (beta_is_even && !compressed_point_y_coord_is_even || - !beta_is_even && compressed_point_y_coord_is_even) { - y = beta; - } else { - y = field_modulus.sub(beta); - } - - // generated_point_R is the point generated from x and y - const generated_point_R = new sjcl.ecc.point(curve, x, y); - - // 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'); - } - - // step 1.5 Compute e from M - const message_e = sjcl.bn.fromBits(hash_bits); - const message_e_neg = new sjcl.bn(0).sub(message_e).mod(field_order); - - // step 1.6 Compute Q = r^-1 (sR - eG) - // console.log('r: ', signature_r); - const signature_r_inv = signature_r.inverseMod(field_order); - const 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'); - } - - // Verify that this public key matches the signature - 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) { - - const 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 (let possible_factor = 0; possible_factor < 4; possible_factor++) { - - let 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) { - - const self = this; - - // Convert hash to bits and determine encoding for output - let 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 - const standard_signature = self.sign(hash_bits, paranoia, k_for_testing); - const canonical_signature = self.canonicalizeSignature(standard_signature); - - // Extract r and s signature components from canonical signature - const r_and_s = getRandSFromSignature(self._curve, canonical_signature); - - // Rederive public key - const public_key = self._curve.G.mult(sjcl.bn.fromBits(self.get())); - - // Determine recovery factor based on which possible value - // returns the correct public key - const 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 - const value_to_prepend = recovery_factor + 27; - - const 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} [curve=sjcl.ecc.curves['k256']] - * @returns {sjcl.ecc.ecdsa.publicKey} Public key - */ -sjcl.ecc.ecdsa.publicKey.recoverFromSignature = function( - hash, signature, curve=sjcl.ecc.curves.k256) { - - if (!signature || signature instanceof sjcl.ecc.curve) { - throw new sjcl.exception.invalid( - 'must supply hash and signature to recover public key'); - } - - // Convert hash to bits and determine encoding for output - let 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'); - } - - let 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 - const 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 - const r_and_s = getRandSFromSignature(curve, signature_bits.slice(1)); - const signature_r = r_and_s.r; - const signature_s = r_and_s.s; - - // Recover public key using recovery_factor - const recovered_public_key_point = recoverPublicKeyPointFromSignature( - curve, signature_r, signature_s, hash_bits, recovery_factor); - const recovered_public_key = new sjcl.ecc.ecdsa.publicKey( - curve, recovered_public_key_point); - - return recovered_public_key; -}; diff --git a/src/core/sjcl-custom/sjcl-extramath.js b/src/core/sjcl-custom/sjcl-extramath.js deleted file mode 100755 index 11928f9f..00000000 --- a/src/core/sjcl-custom/sjcl-extramath.js +++ /dev/null @@ -1,156 +0,0 @@ -/* 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); - } - var thisa = this.abs(), thata = that.abs(), quot = new this._class(0), - ci = 0; - if (!thisa.greaterEquals(thata)) { - return [new sjcl.bn(0), this.copy()]; - } else if (thisa.equals(thata)) { - return [new sjcl.bn(1), new sjcl.bn(0)]; - } - - for (; thisa.greaterEquals(thata); ci++) { - thata.doubleM(); - } - for (; ci > 0; ci--) { - quot.doubleM(); - thata.halveM(); - if (thisa.greaterEquals(thata)) { - quot.addM(1); - thisa.subM(that).normalize(); - } - } - return [quot, thisa]; -}; - -/* 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)) { - quot.addM(1); - } - - return quot; -}; - -/* this /= that (rounded down) */ -sjcl.bn.prototype.div = function(that) { - var dr = this.divRem(that); - return dr[0]; -}; - -sjcl.bn.prototype.sign = function() { - return this.greaterEquals(sjcl.bn.ZERO) ? 1 : -1; -}; - -/* -this */ -sjcl.bn.prototype.neg = function() { - return sjcl.bn.ZERO.sub(this); -}; - -/* |this| */ -sjcl.bn.prototype.abs = function() { - if (this.sign() === -1) { - return this.neg(); - } - return this; -}; - -/* this >> that */ -sjcl.bn.prototype.shiftRight = function(that) { - if (typeof that !== 'number') { - throw new Error('shiftRight expects a number'); - } - - that = +that; - - if (that < 0) { - return this.shiftLeft(that); - } - - var a = new sjcl.bn(this); - - while (that >= this.radix) { - a.limbs.shift(); - that -= this.radix; - } - - while (that--) { - a.halveM(); - } - - return a; -}; - -/* this >> that */ -sjcl.bn.prototype.shiftLeft = function(that) { - if (typeof that !== 'number') { - throw new Error('shiftLeft expects a number'); - } - - that = +that; - - if (that < 0) { - return this.shiftRight(that); - } - - var a = new sjcl.bn(this); - - while (that >= this.radix) { - a.limbs.unshift(0); - that -= this.radix; - } - - while (that--) { - a.doubleM(); - } - - return a; -}; - -/* (int)this */ -// NOTE Truncates to 32-bit integer -sjcl.bn.prototype.toNumber = function() { - return this.limbs[0] | 0; -}; - -/* 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; - } - - return (this.limbs[limbIndex] >>> bitIndexInLimb) & 1; -}; - -/* 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); - } - - this.limbs[limbIndex] |= 1 << bitIndexInLimb; - - this.cnormalize(); - - return this; -}; - -sjcl.bn.prototype.modInt = function(n) { - return this.toNumber() % n; -}; diff --git a/src/core/sjcl-custom/sjcl-secp256k1.js b/src/core/sjcl-custom/sjcl-secp256k1.js deleted file mode 100755 index 60afd538..00000000 --- a/src/core/sjcl-custom/sjcl-secp256k1.js +++ /dev/null @@ -1,81 +0,0 @@ -/* 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())); -}; - -// Replace point addition and doubling algorithms -// NIST-P256 is a=-3, we need algorithms for a=0 -// -// This is a custom point addition formula that -// only works for a=-3 Jacobian curve. It's much -// faster than the generic implementation -sjcl.ecc.pointJac.prototype.add = function(T) { - var self = this; - if (self.curve !== T.curve) { - throw ('sjcl.ecc.add(): Points must be on the same curve to add them!'); - } - - if (self.isIdentity) { - return T.toJac(); - } else if (T.isIdentity) { - return self; - } - - 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 (self.y.equals(T.y.mul(z1z1.mul(self.z)))) { - // same point - 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(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(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); -}; - -// 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; - } - - var a = this.x.square(); - var b = this.y.square(); - var c = b.square(); - var d = this.x.add(b).square().subM(a).subM(c).doubleM(); - var e = a.mul(3); - var f = e.square(); - var x = f.sub(d.copy().doubleM()); - var y = e.mul(d.sub(x)).subM(c.doubleM().doubleM().doubleM()); - var z = this.z.mul(this.y).doubleM(); - return new sjcl.ecc.pointJac(this.curve, x, y, z); -}; - -// DEPRECATED: -// previously the c256 curve was overridden with the secp256k1 curve -// since then, sjcl has been updated to support k256 -// this override exist to keep supporting the old c256 with k256 behavior -// this will be removed in future release -sjcl.ecc.curves.c256 = sjcl.ecc.curves.k256; diff --git a/src/core/sjcl-custom/sjcl-validecc.js b/src/core/sjcl-custom/sjcl-validecc.js deleted file mode 100644 index 07087a76..00000000 --- a/src/core/sjcl-custom/sjcl-validecc.js +++ /dev/null @@ -1,47 +0,0 @@ -/* eslint new-cap: [2, {newIsCapExceptions: ["corrupt"]}] */ -'use strict'; -var sjcl = require('sjcl'); - -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') { - 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 { - // 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); - - return sjcl.bitArray.concat(r.toBits(l), s.toBits(l)); -}; - -sjcl.ecc.ecdsa.publicKey.prototype.verify = function(hash, rs) { - 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')); - } - return true; -}; diff --git a/src/core/utils.js b/src/core/utils.js index df5fa1c3..e8fe8f3c 100644 --- a/src/core/utils.js +++ b/src/core/utils.js @@ -157,7 +157,6 @@ exports.toTimestamp = toTimestamp; exports.fromTimestamp = fromTimestamp; exports.getMantissaDecimalString = getMantissaDecimalString; -exports.sjcl = require('sjcl'); -require('./sjcl-custom'); +exports.sjcl = require('sjcl-extended'); // vim:sw=2:sts=2:ts=8:et diff --git a/test/sjcl-ecdsa-canonical-test.js b/test/sjcl-ecdsa-canonical-test.js deleted file mode 100644 index 92d0fab2..00000000 --- a/test/sjcl-ecdsa-canonical-test.js +++ /dev/null @@ -1,27 +0,0 @@ -var assert = require('assert'); -var sjcl = require('ripple-lib').sjcl; -var Seed = require('ripple-lib').Seed; - -describe('SJCL ECDSA Canonicalization', function() { - describe('canonicalizeSignature', function() { - it('should canonicalize non-canonical signatures', function () { - var seed = Seed.from_json('saESc82Vun7Ta5EJRzGJbrXb5HNYk'); - var key = seed.get_key('rBZ4j6MsoctipM6GEyHSjQKzXG3yambDnZ'); - - var rs = sjcl.codec.hex.toBits("27ce1b914045ba7e8c11a2f2882cb6e07a19d4017513f12e3e363d71dc3fff0fb0a0747ecc7b4ca46e45b3b32b6b2a066aa0249c027ef11e5bce93dab756549c"); - rs = sjcl.ecc.ecdsa.secretKey.prototype.canonicalizeSignature.call(key._secret, rs); - assert.strictEqual(sjcl.codec.hex.fromBits(rs), "27ce1b914045ba7e8c11a2f2882cb6e07a19d4017513f12e3e363d71dc3fff0f4f5f8b813384b35b91ba4c4cd494d5f8500eb84aacc9af1d6403cab218dfeca5"); - }); - - it('should not touch canonical signatures', function () { - var seed = Seed.from_json('saESc82Vun7Ta5EJRzGJbrXb5HNYk'); - var key = seed.get_key('rBZ4j6MsoctipM6GEyHSjQKzXG3yambDnZ'); - - var rs = sjcl.codec.hex.toBits("5c32bc2b4d34e27af9fb66eeea0f47f6afb3d433658af0f649ebae7b872471ab7d23860688aaf9d8131f84cfffa6c56bf9c32fd8b315b2ef9d6bcb243f7a686c"); - rs = sjcl.ecc.ecdsa.secretKey.prototype.canonicalizeSignature.call(key._secret, rs); - assert.strictEqual(sjcl.codec.hex.fromBits(rs), "5c32bc2b4d34e27af9fb66eeea0f47f6afb3d433658af0f649ebae7b872471ab7d23860688aaf9d8131f84cfffa6c56bf9c32fd8b315b2ef9d6bcb243f7a686c"); - }); - }); -}); - -// vim:sw=2:sts=2:ts=8:et diff --git a/test/sjcl-ecdsa-recoverablepublickey-test.js b/test/sjcl-ecdsa-recoverablepublickey-test.js deleted file mode 100644 index fa53c5dd..00000000 --- a/test/sjcl-ecdsa-recoverablepublickey-test.js +++ /dev/null @@ -1,260 +0,0 @@ -var assert = require('assert'); -var sjcl = require('ripple-lib').sjcl; - -describe('ECDSA signing with recoverable public key', function(){ - - describe('Sign and recover public key from signature', function(){ - - it('should recover public keys from signatures it generates', function(){ - - var messages = [{ - message: 'Hello world!', - secret_hex: '9931c08f61f127d5735fa3c60e702212ce7ed9a2ac90d5dbade99c689728cd9b', - random_value: '5473a3dbdc13ec9efbad7f7f929fbbea404af556a48041dd9d41d29fdbc989ad', - hash_function: sjcl.hash.sha512.hash - // signature: 'AAAAGzFa1pYjhssCpDFZgFSnYQ8qCnMkLaZrg0mXZyNQ2NxgMQ8z9U3ngYerxSZCEt3Q4raMIpt03db7jDNGbfmHy8I=' - }, { - // Correct recovery value for this one is 0 - message: 'ua5pdcG0I1JuhSr9Fwai2UoZ9ll5leUtHE5NzSSNnPkw8nSPH5mT1gE1fe0sn', - secret_hex: '84814318ffe6e612694ad59b9084b7b66d68b6979567c619171a67b05e2b654b', - random_value: '14261d30b319709c10ab13cabe595313b99dd2d5c76b8b38d7eb445f0b81cc9a', - hash_function: sjcl.hash.sha512.hash - // signature: 'AAAAHGjpBM7wnTHbPGo0TXsxKbr+d7KvACuJ/eGQsp3ZJfOOQHszaciRo3ClenwKixcquFcBlaVfHlOc3JWOZq1RjpQ=' - }, { - // Correct recovery value for this one is 1 - message: 'rxc76UnmVTp', - secret_hex: '37eac47c212be8ea8372f506b11673c281cd9ea29a035c2c9e90d027c3dbecc6', - random_value: '61b53ca6de0543f911765ae216a3a4d851918a0733fba9ac80cf29de5bec8032', - hash_function: sjcl.hash.sha256.hash - // signature: 'AAAAG8L/yOA3nNqK4aOiQWJmOaWvkvr3NoTk6wCdX97U3qowdgFd98UK3evWV16qO3RHgFMEnUW/Vt4+kcidqW6hMo0=' - }]; - - var curve = sjcl.ecc.curves['k256']; - - for (var m = 0; m < messages.length; m++) { - - var message = messages[m].message; - var secret_hex = messages[m].secret_hex; - var random_value = messages[m].random_value; - var hash_function = messages[m].hash_function; - - var secret_bn = sjcl.bn.fromBits(sjcl.codec.hex.toBits(secret_hex)); - var secret_key = new sjcl.ecc.ecdsa.secretKey(curve, secret_bn); - - var pub_val_point = secret_key._curve.G.mult(secret_key._exponent); - var public_key = new sjcl.ecc.ecdsa.publicKey(curve, pub_val_point); - var hash = hash_function(message); - - var recoverable_signature = secret_key.signWithRecoverablePublicKey(hash, 0, random_value); - var recovered_public_key = sjcl.ecc.ecdsa.publicKey.recoverFromSignature(hash, recoverable_signature); - - assert.deepEqual(public_key.get().x, recovered_public_key.get().x, 'The x value for the recovered public key did not match for message: ' + message + '. Expected: ' + public_key.get().x.toString() + '. Actual: ' + recovered_public_key.get().x.toString()); - assert.deepEqual(public_key.get().y, recovered_public_key.get().y, 'The y value for the recovered public key did not match for message: ' + message + '. Expected: ' + public_key.get().y.toString() + '. Actual: ' + recovered_public_key.get().y.toString()); - - } - - }); - - }); - - describe('signWithRecoverablePublicKey', function(){ - - // it('should produce the same values as bitcoinjs-lib\'s implementation', function(){ - - // // TODO: figure out why bitcoinjs-lib and this produce different signature values - - // var curve = sjcl.ecc.curves['k256']; - - // var secret_hex = '9e623166ac44d4e75fa842f3443485b9c8380551132a8ffaa898b5c93bb18b7d'; - // var secret_bn = sjcl.bn.fromBits(sjcl.codec.hex.toBits(secret_hex)); - // var secret_key = new sjcl.ecc.ecdsa.secretKey(curve, secret_bn); - - // // var public_key = '0217b9f5b3ba8d550f19fdfb5233818cd27d19aaea029b667f547f5918c307ed3b'; - // var random_value = 'c3aa71cecb965bbbc96083d868b4955d77adb4e02ce229fe60869f745dfcd4e4a4d0f17a15a353d7592dca1baba2824e45c8e7a8f9faad3ce2c2d3792799f27a'; - // var hash = sjcl.codec.hex.toBits('e865bcc63a86ef21585ac8340a7cc8590ed85175a2a718c6fb2bfb2715d13778'); - - // var bitcoin_signature_base64 = 'IJPzXewhO1CORRx14FROzZC8ne4v0Me94UZoBKH15e4pcSgeYiYeKZ4PJOBI/D5yqUOhemO+rKKHhE0HL66kAcM='; - - // var signature = secret_key.signWithRecoverablePublicKey(hash, 0, random_value); - // var signature_base64 = sjcl.codec.base64.fromBits(signature); - - // assert.equal(signature_base64, bitcoin_signature_base64); - - // }); - - it('should produce an error if the hash is not given as a bitArray', function(){ - - var curve = sjcl.ecc.curves['k256']; - var secret_hex = '9e623166ac44d4e75fa842f3443485b9c8380551132a8ffaa898b5c93bb18b7d'; - var secret_bn = sjcl.bn.fromBits(sjcl.codec.hex.toBits(secret_hex)); - var secret_key = new sjcl.ecc.ecdsa.secretKey(curve, secret_bn); - var random_value = 'c3aa71cecb965bbbc96083d868b4955d77adb4e02ce229fe60869f745dfcd4e4a4d0f17a15a353d7592dca1baba2824e45c8e7a8f9faad3ce2c2d3792799f27a'; - var hash = 'e865bcc63a86ef21585ac8340a7cc8590ed85175a2a718c6fb2bfb2715d13778'; - - assert.throws(function(){ - secret_key.signWithRecoverablePublicKey(hash, 0, random_value); - }, /(?=.*hash)(?=.*bitArray).+/); - - }); - - it('should return a bitArray', function(){ - - var curve = sjcl.ecc.curves['k256']; - var secret_hex = '9e623166ac44d4e75fa842f3443485b9c8380551132a8ffaa898b5c93bb18b7d'; - var secret_bn = sjcl.bn.fromBits(sjcl.codec.hex.toBits(secret_hex)); - var secret_key = new sjcl.ecc.ecdsa.secretKey(curve, secret_bn); - var random_value = 'c3aa71cecb965bbbc96083d868b4955d77adb4e02ce229fe60869f745dfcd4e4a4d0f17a15a353d7592dca1baba2824e45c8e7a8f9faad3ce2c2d3792799f27a'; - var hash = sjcl.codec.hex.toBits('e865bcc63a86ef21585ac8340a7cc8590ed85175a2a718c6fb2bfb2715d13778'); - - var signature = secret_key.signWithRecoverablePublicKey(hash, 0, random_value); - assert(typeof signature === 'object' && signature.length > 0 && typeof signature[0] === 'number'); - - }); - - it('should return a bitArray where the first word contains the recovery factor', function(){ - - var curve = sjcl.ecc.curves['k256']; - var secret_hex = '9e623166ac44d4e75fa842f3443485b9c8380551132a8ffaa898b5c93bb18b7d'; - var secret_bn = sjcl.bn.fromBits(sjcl.codec.hex.toBits(secret_hex)); - var secret_key = new sjcl.ecc.ecdsa.secretKey(curve, secret_bn); - var random_value = 'c3aa71cecb965bbbc96083d868b4955d77adb4e02ce229fe60869f745dfcd4e4a4d0f17a15a353d7592dca1baba2824e45c8e7a8f9faad3ce2c2d3792799f27a'; - var hash = sjcl.codec.hex.toBits('e865bcc63a86ef21585ac8340a7cc8590ed85175a2a718c6fb2bfb2715d13778'); - - var signature = secret_key.signWithRecoverablePublicKey(hash, 0, random_value); - var recovery_factor = signature[0] - 27; - - assert(recovery_factor >= 0 && recovery_factor < 4); - - }); - - }); - - describe('recoverFromSignature', function(){ - - // it('should be able to recover public keys from bitcoinjs-lib\'s implementation', function(){ - - // // TODO: figure out why bitcoinjs-lib and this produce different signature values - - // var hash = sjcl.codec.hex.toBits('e865bcc63a86ef21585ac8340a7cc8590ed85175a2a718c6fb2bfb2715d13778'); - // var signature = sjcl.codec.base64.toBits('IJPzXewhO1CORRx14FROzZC8ne4v0Me94UZoBKH15e4pcSgeYiYeKZ4PJOBI/D5yqUOhemO+rKKHhE0HL66kAcM='); - - // var public_key = sjcl.ecc.ecdsa.publicKey.recoverFromSignature(hash, signature); - - // }); - - it('should produce an error if the signature given does not have the recovery factor prefix', function(){ - - var curve = sjcl.ecc.curves['k256']; - var secret_hex = '9e623166ac44d4e75fa842f3443485b9c8380551132a8ffaa898b5c93bb18b7d'; - var secret_bn = sjcl.bn.fromBits(sjcl.codec.hex.toBits(secret_hex)); - var secret_key = new sjcl.ecc.ecdsa.secretKey(curve, secret_bn); - var random_value = 'c3aa71cecb965bbbc96083d868b4955d77adb4e02ce229fe60869f745dfcd4e4a4d0f17a15a353d7592dca1baba2824e45c8e7a8f9faad3ce2c2d3792799f27a'; - var hash = sjcl.codec.hex.toBits('e865bcc63a86ef21585ac8340a7cc8590ed85175a2a718c6fb2bfb2715d13778'); - - var signature = secret_key.sign(hash, 0, random_value); - - assert.throws(function(){ - sjcl.ecc.ecdsa.publicKey.recoverFromSignature(hash, signature); - }, /(?=.*signature)(?=.*recovery factor)(?=.*public key).*/); - - }); - - it('should produce an error if it is not given both the hash and the signature', function(){ - - var curve = sjcl.ecc.curves['k256']; - var secret_hex = '9e623166ac44d4e75fa842f3443485b9c8380551132a8ffaa898b5c93bb18b7d'; - var secret_bn = sjcl.bn.fromBits(sjcl.codec.hex.toBits(secret_hex)); - var secret_key = new sjcl.ecc.ecdsa.secretKey(curve, secret_bn); - var random_value = 'c3aa71cecb965bbbc96083d868b4955d77adb4e02ce229fe60869f745dfcd4e4a4d0f17a15a353d7592dca1baba2824e45c8e7a8f9faad3ce2c2d3792799f27a'; - var hash = sjcl.codec.hex.toBits('e865bcc63a86ef21585ac8340a7cc8590ed85175a2a718c6fb2bfb2715d13778'); - - var signature = secret_key.signWithRecoverablePublicKey(hash, 0, random_value); - - assert.throws(function(){ - sjcl.ecc.ecdsa.publicKey.recoverFromSignature(hash); - }, /(?=.*hash\ and\ signature)(?=.*recover\ public\ key).*/); - - assert.throws(function(){ - sjcl.ecc.ecdsa.publicKey.recoverFromSignature(signature); - }, /(?=.*hash\ and\ signature)(?=.*recover\ public\ key).*/); - - }); - - it('should produce an error if it cannot generate a valid public key from the the signature', function(){ - - var curve = sjcl.ecc.curves['k256']; - var secret_hex = '9e623166ac44d4e75fa842f3443485b9c8380551132a8ffaa898b5c93bb18b7d'; - var secret_bn = sjcl.bn.fromBits(sjcl.codec.hex.toBits(secret_hex)); - var secret_key = new sjcl.ecc.ecdsa.secretKey(curve, secret_bn); - var random_value = 'c3aa71cecb965bbbc96083d868b4955d77adb4e02ce229fe60869f745dfcd4e4a4d0f17a15a353d7592dca1baba2824e45c8e7a8f9faad3ce2c2d3792799f27a'; - var hash = sjcl.codec.hex.toBits('e865bcc63a86ef21585ac8340a7cc8590ed85175a2a718c6fb2bfb2715d13778'); - - var signature = sjcl.codec.base64.toBits('IJPzXewhO1CORRx14FROzZC8ne4v0Me94UZoBKH15e4pcSgeYiYeKZ4PJOBI/D5yqUOhemO+rKKHhE0HL66kAcM='); - signature[0] = 27; - - signature[3] = 0 - signature[3]; - - assert.throws(function(){ - sjcl.ecc.ecdsa.publicKey.recoverFromSignature(hash, signature); - }, /(?=.*Cannot\ recover\ public\ key).*/); - - }); - - it('should return a publicKey object', function(){ - - var curve = sjcl.ecc.curves['k256']; - var secret_hex = '9e623166ac44d4e75fa842f3443485b9c8380551132a8ffaa898b5c93bb18b7d'; - var secret_bn = sjcl.bn.fromBits(sjcl.codec.hex.toBits(secret_hex)); - var secret_key = new sjcl.ecc.ecdsa.secretKey(curve, secret_bn); - var random_value = 'c3aa71cecb965bbbc96083d868b4955d77adb4e02ce229fe60869f745dfcd4e4a4d0f17a15a353d7592dca1baba2824e45c8e7a8f9faad3ce2c2d3792799f27a'; - var hash = sjcl.codec.hex.toBits('e865bcc63a86ef21585ac8340a7cc8590ed85175a2a718c6fb2bfb2715d13778'); - var signature = secret_key.signWithRecoverablePublicKey(hash, 0, random_value); - - var key = sjcl.ecc.ecdsa.publicKey.recoverFromSignature(hash, signature); - - assert(key instanceof sjcl.ecc.ecdsa.publicKey); - - }); - - it('tampering with the signature should produce a different public key, if it produces a valid one at all', function(){ - - var curve = sjcl.ecc.curves['k256']; - var secret_hex = '9e623166ac44d4e75fa842f3443485b9c8380551132a8ffaa898b5c93bb18b7d'; - var secret_bn = sjcl.bn.fromBits(sjcl.codec.hex.toBits(secret_hex)); - var secret_key = new sjcl.ecc.ecdsa.secretKey(curve, secret_bn); - var random_value = 'c3aa71cecb965bbbc96083d868b4955d77adb4e02ce229fe60869f745dfcd4e4a4d0f17a15a353d7592dca1baba2824e45c8e7a8f9faad3ce2c2d3792799f27a'; - var hash = sjcl.codec.hex.toBits('e865bcc63a86ef21585ac8340a7cc8590ed85175a2a718c6fb2bfb2715d13778'); - - var signature = secret_key.signWithRecoverablePublicKey(hash, 0, random_value); - - signature[3]++; - - var original_public_key = new sjcl.ecc.ecdsa.publicKey(curve, curve.G.mult(secret_key._exponent)); - var recovered_public_key = sjcl.ecc.ecdsa.publicKey.recoverFromSignature(hash, signature); - - assert.notDeepEqual(original_public_key.get().x, recovered_public_key.get().x); - assert.notDeepEqual(original_public_key.get().y, recovered_public_key.get().y); - - }); - - it('should return a publicKey object, while using the overridden c256 curve', function(){ - - var curve = sjcl.ecc.curves['c256']; - var secret_hex = '9e623166ac44d4e75fa842f3443485b9c8380551132a8ffaa898b5c93bb18b7d'; - var secret_bn = sjcl.bn.fromBits(sjcl.codec.hex.toBits(secret_hex)); - var secret_key = new sjcl.ecc.ecdsa.secretKey(curve, secret_bn); - var random_value = 'c3aa71cecb965bbbc96083d868b4955d77adb4e02ce229fe60869f745dfcd4e4a4d0f17a15a353d7592dca1baba2824e45c8e7a8f9faad3ce2c2d3792799f27a'; - var hash = sjcl.codec.hex.toBits('e865bcc63a86ef21585ac8340a7cc8590ed85175a2a718c6fb2bfb2715d13778'); - var signature = secret_key.signWithRecoverablePublicKey(hash, 0, random_value); - - var key = sjcl.ecc.ecdsa.publicKey.recoverFromSignature(hash, signature); - - assert(key instanceof sjcl.ecc.ecdsa.publicKey); - - }); - - }); - -}); - - diff --git a/test/sjcl-extramath-test.js b/test/sjcl-extramath-test.js deleted file mode 100644 index 60090bc0..00000000 --- a/test/sjcl-extramath-test.js +++ /dev/null @@ -1,51 +0,0 @@ -var assert = require('assert'); -var sjcl = require('ripple-lib').sjcl; - -describe('SJCL Extramath', function() { - describe('setBitM', function() { - it('0x0f set bit 4 => 0x1f', function () { - var val = new sjcl.bn("0f"); - val.setBitM(4); - assert.strictEqual(val.toString(), '0x1f'); - }); - it('0x0f set bit 23 => 0x80000f', function () { - var val = new sjcl.bn("0f"); - val.setBitM(23); - assert.strictEqual(val.toString(), '0x80000f'); - }); - it('0x0f set bit 24 => 0x100000f', function () { - var val = new sjcl.bn("0f"); - val.setBitM(24); - assert.strictEqual(val.toString(), '0x100000f'); - }); - }); - describe('testBit', function() { - it('0x03', function () { - var val = new sjcl.bn("03"); - assert.strictEqual(val.testBit(0), 1); - assert.strictEqual(val.testBit(1), 1); - assert.strictEqual(val.testBit(2), 0); - }); - it('0x1000000', function () { - var val = new sjcl.bn("1000000"); - assert.strictEqual(val.testBit(25), 0); - assert.strictEqual(val.testBit(24), 1); - assert.strictEqual(val.testBit(23), 0); - assert.strictEqual(val.testBit( 1), 0); - assert.strictEqual(val.testBit( 0), 0); - }); - it('0xff7fffffff', function () { - var val = new sjcl.bn("ff7fffffff"); - assert.strictEqual(val.testBit(32), 1); - assert.strictEqual(val.testBit(31), 0); - assert.strictEqual(val.testBit(30), 1); - assert.strictEqual(val.testBit(24), 1); - assert.strictEqual(val.testBit(23), 1); - assert.strictEqual(val.testBit(22), 1); - assert.strictEqual(val.testBit( 1), 1); - assert.strictEqual(val.testBit( 0), 1); - }); - }); -}); - -// vim:sw=2:sts=2:ts=8:et diff --git a/test/sjcl-montgomery.js b/test/sjcl-montgomery.js deleted file mode 100644 index 5ec9cbf2..00000000 --- a/test/sjcl-montgomery.js +++ /dev/null @@ -1,100 +0,0 @@ -/* eslint-disable max-len */ -/* eslint new-cap: [2, {newIsCapExceptions: ["bn"]}] */ -'use strict'; -const assert = require('assert'); -const sjcl = require('ripple-lib').sjcl; - -// fix normalize bug in scjl: -// https://github.com/bitwiseshiftleft/sjcl/pull/221 -function normalizeFix(bn) { - while (bn.limbs.length > 0 && bn.limbs[bn.limbs.length - 1] === 0) { - bn.limbs.pop(); - } - return bn; -} - -function testExp(vec) { - const actual = normalizeFix(new sjcl.bn(vec.g).powermod( - new sjcl.bn(vec.e), new sjcl.bn(vec.m))); - const expected = new sjcl.bn(vec.r); - assert.strictEqual(actual.toString(), expected.toString()); -} - -describe('SJCL Montgomery Exponentiation', function() { - describe('powermod', function() { - it('test 1', function() { - testExp({ - g: 2, - e: 3, - m: 3, - r: 2 - }); - }); - it('test 2', function() { - testExp({ - g: 2, - e: '10000000000000000000000000', - m: 1337, - r: 1206 - }); - }); - it('test 3', function() { - testExp({ - g: 17, - e: 90, - m: 34717861147, - r: 28445204336 - }); - }); - it('test 4', function() { - testExp({ - g: 2, - e: '0x844A000000000000000000000', - m: 13, - r: 9 - }); - }); - it('test 5', function() { - testExp({ - g: 2, - e: 0x1010, - m: 131, - r: 59 - }); - }); - it('test 6', function() { - testExp({ - g: 2, - e: '43207437777777877617151', - m: 13, - r: 2 - }); - }); - it('test 7', function() { - testExp({ - g: 2, - e: '389274238947216444871600001871964319565192765874149', - m: 117, - r: 44 - }); - }); - it('test 8', function() { - testExp({ - g: 2, - e: '89457115510016156219817846189181057618965150496979174671534084187', - m: '1897166415676096761', - r: '16840615e646a4c5c8d' - }); - }); - it('test 9', function() { - testExp({ - g: '4c3399bebab284bc7f9056efe17ea39db324ffa1d52dc1542eb16a749570789359f192535b7bcb514b36be9cdb4fb2a6ba3ad6b4248034e9a1d2a8612cd9d885242b4f679524121b74f79d7db14859fccde1c0dfe6ef002dcbc777ab5fcf4432', - e: '000322e6b6dafe138ccd6a991977d19', - m: 'a5091daa41997943e3c98469e93377f668d05d8059bc53f72aaacdac3729a3070dc7439a5171160bf9ec2826b7191b03b0e84b28e14dd376de35d29a96f686666e053ab62a41ebc2b5f52e8cf06254100fd153a1cda4485f170c39c54689e52d', - r: '554336ea044782d29f091117cfeaeee2334b4242bd7428d0bba3ce5325781dc219e891e54698cb0193ffe7c6fc07f1808f6685e64b6a082815f6afd2e16c7a61316b5e3e59cd8b3984d5a76c8e173f8615f7dceac0c99e27e4abfb1278dfa67f' - }); - }); - }); -}); - -// vim:sw=2:sts=2:ts=8:et