Remove lint errors in sjcl-custom

This commit is contained in:
Chris Clark
2015-05-12 11:39:18 -07:00
parent 9a502580fd
commit de7fc78ef0
11 changed files with 335 additions and 266 deletions

View File

@@ -1,3 +1,4 @@
'use strict';
require('./sjcl-ecc-pointextras.js');
require('./sjcl-secp256k1.js');
require('./sjcl-ripemd160.js');

View File

@@ -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() +

View File

@@ -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

View File

@@ -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,

View File

@@ -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;
};

View File

@@ -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;
};

View File

@@ -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);
};

View File

@@ -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 ()

View File

@@ -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.

View File

@@ -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();

View File

@@ -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;
};