diff --git a/core/ecc.js b/core/ecc.js deleted file mode 100644 index 504288f..0000000 --- a/core/ecc.js +++ /dev/null @@ -1,380 +0,0 @@ -sjcl.ecc = {}; - -/** - * Represents a point on a curve in affine coordinates. - * @constructor - * @param {sjcl.ecc.curve} curve The curve that this point lies on. - * @param {bigInt} x The x coordinate. - * @param {bigInt} y The y coordinate. - */ -sjcl.ecc.point = function(curve,x,y) { - if (x === undefined) { - this.isIdentity = true; - } else { - this.x = x; - this.y = y; - this.isIdentity = false; - } - this.curve = curve; -}; - - - -sjcl.ecc.point.prototype = { - toJac: function() { - return new sjcl.ecc.pointJac(this.curve, this.x, this.y, new this.curve.field(1)); - }, - - mult: function(k) { - return this.toJac().mult(k, this).toAffine(); - }, - - /** - * Multiply this point by k, added to affine2*k2, and return the answer in Jacobian coordinates. - * @param {bigInt} k The coefficient to multiply this by. - * @param {bigInt} k2 The coefficient to multiply affine2 this by. - * @param {sjcl.ecc.point} affine The other point in affine coordinates. - * @return {sjcl.ecc.pointJac} The result of the multiplication and addition, in Jacobian coordinates. - */ - mult2: function(k, k2, affine2) { - return this.toJac().mult2(k, this, k2, affine2).toAffine(); - }, - - multiples: function() { - var m, i, j; - if (this._multiples === undefined) { - j = this.toJac().doubl(); - m = this._multiples = [new sjcl.ecc.point(this.curve), this, j.toAffine()]; - for (i=3; i<16; i++) { - j = j.add(this); - m.push(j.toAffine()); - } - } - return this._multiples; - }, - - isValid: function() { - return this.y.square().equals(this.curve.b.add(this.x.mul(this.curve.a.add(this.x.square())))); - }, - - toBits: function() { - return sjcl.bitArray.concat(this.x.toBits(), this.y.toBits()); - } -}; - -/** - * Represents a point on a curve in Jacobian coordinates. Coordinates can be specified as bigInts or strings (which - * will be converted to bigInts). - * - * @constructor - * @param {bigInt/string} x The x coordinate. - * @param {bigInt/string} y The y coordinate. - * @param {bigInt/string} z The z coordinate. - * @param {sjcl.ecc.curve} curve The curve that this point lies on. - */ -sjcl.ecc.pointJac = function(curve, x, y, z) { - if (x === undefined) { - this.isIdentity = true; - } else { - this.x = x; - this.y = y; - this.z = z; - this.isIdentity = false; - } - this.curve = curve; -}; - -sjcl.ecc.pointJac.prototype = { - /** - * Adds S and T and returns the result in Jacobian coordinates. Note that S must be in Jacobian coordinates and T must be in affine coordinates. - * @param {sjcl.ecc.pointJac} S One of the points to add, in Jacobian coordinates. - * @param {sjcl.ecc.point} T The other point to add, in affine coordinates. - * @return {sjcl.ecc.pointJac} The sum of the two points, in Jacobian coordinates. - */ - add: function(T) { - var S = this, sz2, c, d, c2, x1, x2, x, y1, y2, y, z; - if (S.curve !== T.curve) { - throw("sjcl.ecc.add(): Points must be on the same curve to add them!"); - } - - if (S.isIdentity) { - return T.toJac(); - } else if (T.isIdentity) { - return S; - } - - sz2 = S.z.square(); - c = T.x.mul(sz2).subM(S.x); - - if (c.equals(0)) { - if (S.y.equals(T.y.mul(sz2.mul(S.z)))) { - // same point - return S.doubl(); - } else { - // inverses - return new sjcl.ecc.pointJac(S.curve); - } - } - - d = T.y.mul(sz2.mul(S.z)).subM(S.y); - c2 = c.square(); - - x1 = d.square(); - x2 = c.square().mul(c).addM( S.x.add(S.x).mul(c2) ); - x = x1.subM(x2); - - y1 = S.x.mul(c2).subM(x).mul(d); - y2 = S.y.mul(c.square().mul(c)); - y = y1.subM(y2); - - z = S.z.mul(c); - - return new sjcl.ecc.pointJac(this.curve,x,y,z); - }, - - /** - * doubles this point. - * @return {sjcl.ecc.pointJac} The doubled point. - */ - doubl: function() { - if (this.isIdentity) { return this; } - - var - y2 = this.y.square(), - a = y2.mul(this.x.mul(4)), - b = y2.square().mul(8), - z2 = this.z.square(), - c = this.x.sub(z2).mul(3).mul(this.x.add(z2)), - x = c.square().subM(a).subM(a), - y = a.sub(x).mul(c).subM(b), - z = this.y.add(this.y).mul(this.z); - return new sjcl.ecc.pointJac(this.curve, x, y, z); - }, - - /** - * Returns a copy of this point converted to affine coordinates. - * @return {sjcl.ecc.point} The converted point. - */ - toAffine: function() { - if (this.isIdentity || this.z.equals(0)) { - return new sjcl.ecc.point(this.curve); - } - var zi = this.z.inverse(), zi2 = zi.square(); - return new sjcl.ecc.point(this.curve, this.x.mul(zi2).fullReduce(), this.y.mul(zi2.mul(zi)).fullReduce()); - }, - - /** - * Multiply this point by k and return the answer in Jacobian coordinates. - * @param {bigInt} k The coefficient to multiply by. - * @param {sjcl.ecc.point} affine This point in affine coordinates. - * @return {sjcl.ecc.pointJac} The result of the multiplication, in Jacobian coordinates. - */ - mult: function(k, affine) { - if (typeof(k) === "number") { - k = [k]; - } else if (k.limbs !== undefined) { - k = k.normalize().limbs; - } - - var i, j, out = new sjcl.ecc.point(this.curve).toJac(), multiples = affine.multiples(); - - for (i=k.length-1; i>=0; i--) { - for (j=sjcl.bn.prototype.radix-4; j>=0; j-=4) { - out = out.doubl().doubl().doubl().doubl().add(multiples[k[i]>>j & 0xF]); - } - } - - return out; - }, - - /** - * Multiply this point by k, added to affine2*k2, and return the answer in Jacobian coordinates. - * @param {bigInt} k The coefficient to multiply this by. - * @param {sjcl.ecc.point} affine This point in affine coordinates. - * @param {bigInt} k2 The coefficient to multiply affine2 this by. - * @param {sjcl.ecc.point} affine The other point in affine coordinates. - * @return {sjcl.ecc.pointJac} The result of the multiplication and addition, in Jacobian coordinates. - */ - mult2: function(k1, affine, k2, affine2) { - if (typeof(k1) === "number") { - k1 = [k1]; - } else if (k1.limbs !== undefined) { - k1 = k1.normalize().limbs; - } - - if (typeof(k2) === "number") { - k2 = [k2]; - } else if (k2.limbs !== undefined) { - k2 = k2.normalize().limbs; - } - - var i, j, out = new sjcl.ecc.point(this.curve).toJac(), m1 = affine.multiples(), - m2 = affine2.multiples(), l1, l2; - - for (i=Math.max(k1.length,k2.length)-1; i>=0; i--) { - l1 = k1[i] | 0; - l2 = k2[i] | 0; - for (j=sjcl.bn.prototype.radix-4; j>=0; j-=4) { - out = out.doubl().doubl().doubl().doubl().add(m1[l1>>j & 0xF]).add(m2[l2>>j & 0xF]); - } - } - - return out; - }, - - isValid: function() { - var z2 = this.z.square(), z4 = z2.square(), z6 = z4.mul(z2); - return this.y.square().equals( - this.curve.b.mul(z6).add(this.x.mul( - this.curve.a.mul(z4).add(this.x.square())))); - } -}; - -/** - * Construct an elliptic curve. Most users will not use this and instead start with one of the NIST curves defined below. - * - * @constructor - * @param {bigInt} p The prime modulus. - * @param {bigInt} r The prime order of the curve. - * @param {bigInt} a The constant a in the equation of the curve y^2 = x^3 + ax + b (for NIST curves, a is always -3). - * @param {bigInt} x The x coordinate of a base point of the curve. - * @param {bigInt} y The y coordinate of a base point of the curve. - */ -sjcl.ecc.curve = function(Field, r, a, b, x, y) { - this.field = Field; - this.r = Field.prototype.modulus.sub(r); - this.a = new Field(a); - this.b = new Field(b); - this.G = new sjcl.ecc.point(this, new Field(x), new Field(y)); -}; - -sjcl.ecc.curve.prototype.fromBits = function (bits) { - var w = sjcl.bitArray, l = this.field.prototype.exponent + 7 & -8, - p = new sjcl.ecc.point(this, this.field.fromBits(w.bitSlice(bits, 0, l)), - this.field.fromBits(w.bitSlice(bits, l, 2*l))); - if (!p.isValid()) { - throw new sjcl.exception.corrupt("not on the curve!"); - } - return p; -}; - -sjcl.ecc.curves = { - c192: new sjcl.ecc.curve( - sjcl.bn.prime.p192, - "0x662107c8eb94364e4b2dd7ce", - -3, - "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", - "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"), - - c224: new sjcl.ecc.curve( - sjcl.bn.prime.p224, - "0xe95c1f470fc1ec22d6baa3a3d5c4", - -3, - "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4", - "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", - "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"), - - c256: new sjcl.ecc.curve( - sjcl.bn.prime.p256, - "0x4319055358e8617b0c46353d039cdaae", - -3, - "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", - "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", - "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"), - - c384: new sjcl.ecc.curve( - sjcl.bn.prime.p384, - "0x389cb27e0bc8d21fa7e5f24cb74f58851313e696333ad68c", - -3, - "0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef", - "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7", - "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f") -}; - - -/* Diffie-Hellman-like public-key system */ -sjcl.ecc._dh = function(cn) { - sjcl.ecc[cn] = { - publicKey: function(curve, point) { - this._curve = curve; - if (point instanceof Array) { - this._point = curve.fromBits(point); - } else { - this._point = point; - } - }, - - secretKey: function(curve, exponent) { - this._curve = curve; - this._exponent = exponent; - }, - - generateKeys: function(curve, paranoia) { - if (curve === undefined) { - curve = 256; - } - if (typeof curve === "number") { - curve = sjcl.ecc.curves['c'+curve]; - if (curve === undefined) { - throw new sjcl.exception.invalid("no such curve"); - } - } - var sec = sjcl.bn.random(curve.r, paranoia), pub = curve.G.mult(sec); - return { pub: new sjcl.ecc[cn].publicKey(curve, pub), - sec: new sjcl.ecc[cn].secretKey(curve, sec) }; - } - }; -}; - -sjcl.ecc._dh("elGamal"); - -sjcl.ecc.elGamal.publicKey.prototype = { - kem: function(paranoia) { - var sec = sjcl.bn.random(this._curve.r, paranoia), - tag = this._curve.G.mult(sec).toBits(), - key = sjcl.hash.sha256.hash(this._point.mult(sec).toBits()); - return { key: key, tag: tag }; - } -}; - -sjcl.ecc.elGamal.secretKey.prototype = { - unkem: function(tag) { - return sjcl.hash.sha256.hash(this._curve.fromBits(tag).mult(this._exponent).toBits()); - }, - - dh: function(pk) { - return sjcl.hash.sha256.hash(pk._point.mult(this._exponent).toBits()); - } -}; - -sjcl.ecc._dh("ecdsa"); - -sjcl.ecc.ecdsa.secretKey.prototype = { - sign: function(hash, paranoia) { - var R = this._curve.r, - l = R.bitLength(), - k = sjcl.bn.random(R.sub(1), paranoia).add(1), - r = this._curve.G.mult(k).x.mod(R), - s = sjcl.bn.fromBits(hash).add(r.mul(this._exponent)).inverseMod(R).mul(k).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)), - hG = sjcl.bn.fromBits(hash).mul(s).mod(R), - hA = r.mul(s).mod(R), - 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/test/run_tests_browser.js b/test/run_tests_browser.js index 617d751..007b66e 100644 --- a/test/run_tests_browser.js +++ b/test/run_tests_browser.js @@ -18,8 +18,6 @@ function testCore(coreName, cb) { "hmac_test.js", "hmac_vectors.js", "pbkdf2_test.js", - "ecdh_test.js", - "ecdsa_test.js", "bn_test.js", "bn_vectors.js", "srp_test.js",