restore ecc, cbc
This commit is contained in:
parent
28b0b389ac
commit
117fce4fa2
115
core/cbc.js
Normal file
115
core/cbc.js
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/** @fileOverview CBC mode implementation
|
||||||
|
*
|
||||||
|
* @author Emily Stark
|
||||||
|
* @author Mike Hamburg
|
||||||
|
* @author Dan Boneh
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @namespace
|
||||||
|
* Dangerous: CBC mode with PKCS#5 padding.
|
||||||
|
*
|
||||||
|
* @author Emily Stark
|
||||||
|
* @author Mike Hamburg
|
||||||
|
* @author Dan Boneh
|
||||||
|
*/
|
||||||
|
if (sjcl.beware === undefined) {
|
||||||
|
sjcl.beware = {};
|
||||||
|
}
|
||||||
|
sjcl.beware["CBC mode is dangerous because it doesn't protect message integrity."
|
||||||
|
] = function() {
|
||||||
|
sjcl.mode.cbc = {
|
||||||
|
/** The name of the mode.
|
||||||
|
* @constant
|
||||||
|
*/
|
||||||
|
name: "cbc",
|
||||||
|
|
||||||
|
/** Encrypt in CBC mode with PKCS#5 padding.
|
||||||
|
* @param {Object} prp The block cipher. It must have a block size of 16 bytes.
|
||||||
|
* @param {bitArray} plaintext The plaintext data.
|
||||||
|
* @param {bitArray} iv The initialization value.
|
||||||
|
* @param {bitArray} [adata=[]] The authenticated data. Must be empty.
|
||||||
|
* @return The encrypted data, an array of bytes.
|
||||||
|
* @throws {sjcl.exception.invalid} if the IV isn't exactly 128 bits, or if any adata is specified.
|
||||||
|
*/
|
||||||
|
encrypt: function(prp, plaintext, iv, adata) {
|
||||||
|
if (adata && adata.length) {
|
||||||
|
throw new sjcl.exception.invalid("cbc can't authenticate data");
|
||||||
|
}
|
||||||
|
if (sjcl.bitArray.bitLength(iv) !== 128) {
|
||||||
|
throw new sjcl.exception.invalid("cbc iv must be 128 bits");
|
||||||
|
}
|
||||||
|
var i,
|
||||||
|
w = sjcl.bitArray,
|
||||||
|
xor = w._xor4,
|
||||||
|
bl = w.bitLength(plaintext),
|
||||||
|
bp = 0,
|
||||||
|
output = [];
|
||||||
|
|
||||||
|
if (bl&7) {
|
||||||
|
throw new sjcl.exception.invalid("pkcs#5 padding only works for multiples of a byte");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; bp+128 <= bl; i+=4, bp+=128) {
|
||||||
|
/* Encrypt a non-final block */
|
||||||
|
iv = prp.encrypt(xor(iv, plaintext.slice(i,i+4)));
|
||||||
|
output.splice(i,0,iv[0],iv[1],iv[2],iv[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Construct the pad. */
|
||||||
|
bl = (16 - ((bl >> 3) & 15)) * 0x1010101;
|
||||||
|
|
||||||
|
/* Pad and encrypt. */
|
||||||
|
iv = prp.encrypt(xor(iv,w.concat(plaintext,[bl,bl,bl,bl]).slice(i,i+4)));
|
||||||
|
output.splice(i,0,iv[0],iv[1],iv[2],iv[3]);
|
||||||
|
return output;
|
||||||
|
},
|
||||||
|
|
||||||
|
/** Decrypt in CBC mode.
|
||||||
|
* @param {Object} prp The block cipher. It must have a block size of 16 bytes.
|
||||||
|
* @param {bitArray} ciphertext The ciphertext data.
|
||||||
|
* @param {bitArray} iv The initialization value.
|
||||||
|
* @param {bitArray} [adata=[]] The authenticated data. It must be empty.
|
||||||
|
* @return The decrypted data, an array of bytes.
|
||||||
|
* @throws {sjcl.exception.invalid} if the IV isn't exactly 128 bits, or if any adata is specified.
|
||||||
|
* @throws {sjcl.exception.corrupt} if if the message is corrupt.
|
||||||
|
*/
|
||||||
|
decrypt: function(prp, ciphertext, iv, adata) {
|
||||||
|
if (adata && adata.length) {
|
||||||
|
throw new sjcl.exception.invalid("cbc can't authenticate data");
|
||||||
|
}
|
||||||
|
if (sjcl.bitArray.bitLength(iv) !== 128) {
|
||||||
|
throw new sjcl.exception.invalid("cbc iv must be 128 bits");
|
||||||
|
}
|
||||||
|
if ((sjcl.bitArray.bitLength(ciphertext) & 127) || !ciphertext.length) {
|
||||||
|
throw new sjcl.exception.corrupt("cbc ciphertext must be a positive multiple of the block size");
|
||||||
|
}
|
||||||
|
var i,
|
||||||
|
w = sjcl.bitArray,
|
||||||
|
xor = w._xor4,
|
||||||
|
bi, bo,
|
||||||
|
output = [];
|
||||||
|
|
||||||
|
adata = adata || [];
|
||||||
|
|
||||||
|
for (i=0; i<ciphertext.length; i+=4) {
|
||||||
|
bi = ciphertext.slice(i,i+4);
|
||||||
|
bo = xor(iv,prp.decrypt(bi));
|
||||||
|
output.splice(i,0,bo[0],bo[1],bo[2],bo[3]);
|
||||||
|
iv = bi;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check and remove the pad */
|
||||||
|
bi = output[i-1] & 255;
|
||||||
|
if (bi == 0 || bi > 16) {
|
||||||
|
throw new sjcl.exception.corrupt("pkcs#5 padding corrupt");
|
||||||
|
}
|
||||||
|
bo = bi * 0x1010101;
|
||||||
|
if (!w.equal(w.bitSlice([bo,bo,bo,bo], 0, bi*8),
|
||||||
|
w.bitSlice(output, output.length*32 - bi*8, output.length*32))) {
|
||||||
|
throw new sjcl.exception.corrupt("pkcs#5 padding corrupt");
|
||||||
|
}
|
||||||
|
|
||||||
|
return w.bitSlice(output, 0, output.length*32 - bi*8);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
380
core/ecc.js
Normal file
380
core/ecc.js
Normal file
@ -0,0 +1,380 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
};
|
33
test/cbc_test.js
Normal file
33
test/cbc_test.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
new sjcl.test.TestCase("CBC mode tests", function (cb) {
|
||||||
|
((sjcl.beware &&
|
||||||
|
sjcl.beware["CBC mode is dangerous because it doesn't protect message integrity."]) ||
|
||||||
|
function(){})();
|
||||||
|
|
||||||
|
if (!sjcl.cipher.aes || !sjcl.mode.cbc) {
|
||||||
|
this.unimplemented();
|
||||||
|
cb && cb();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var i, kat = sjcl.test.vector.cbc, tv, iv, ct, aes, len, thiz=this, w=sjcl.bitArray, pt, h=sjcl.codec.hex;
|
||||||
|
browserUtil.cpsIterate(function (j, cbb) {
|
||||||
|
for (i=100*j; i<kat.length && i<100*(j+1); i++) {
|
||||||
|
tv = kat[i];
|
||||||
|
len = 32 * tv.key.length;
|
||||||
|
aes = new sjcl.cipher.aes(h.toBits(tv.key));
|
||||||
|
|
||||||
|
// Convert from strings
|
||||||
|
iv = h.toBits(tv.iv);
|
||||||
|
pt = h.toBits(tv.pt);
|
||||||
|
ct = h.toBits(tv.ct);
|
||||||
|
|
||||||
|
thiz.require(w.equal(sjcl.mode.cbc.encrypt(aes, pt, iv), ct), "aes-"+len+"-cbc-encrypt #"+i);
|
||||||
|
try {
|
||||||
|
thiz.require(w.equal(sjcl.mode.cbc.decrypt(aes, ct, iv), pt), "aes-"+len+"-cbc-decrypt #"+i);
|
||||||
|
} catch (e) {
|
||||||
|
thiz.fail("aes-cbc-decrypt #"+i+" (exn "+e+")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cbb();
|
||||||
|
}, 0, kat.length / 100, true, cb);
|
||||||
|
});
|
413
test/cbc_vectors.js
Normal file
413
test/cbc_vectors.js
Normal file
@ -0,0 +1,413 @@
|
|||||||
|
/* Test vector for CBC mode with PKCS#5 padding.
|
||||||
|
* Generated by vpaes. Not kosher, I know...
|
||||||
|
*/
|
||||||
|
sjcl.test.vector.cbc = [
|
||||||
|
{ key: '654a1661a99a6b3abf52e52a4e951491',
|
||||||
|
iv: 'bfd3814678afe0036efa67ca8da44e2e',
|
||||||
|
pt: '',
|
||||||
|
ct: 'ac5517ed8b3118ae7bd90a81891cbeb5' },
|
||||||
|
{ key: 'edd235a58a408e0fc2334cac942c21af',
|
||||||
|
iv: 'd2e730833f975086589ff5ba1c956984',
|
||||||
|
pt: '00',
|
||||||
|
ct: '49803e9755775f5bbb51d5c1ecf418a4'},
|
||||||
|
{ key: '6b5564e1ded7a1d357672e3b19d1dfa2',
|
||||||
|
iv: '797c32df1e21f3b5f47d05d20b18a33f',
|
||||||
|
pt: '89b7',
|
||||||
|
ct: '4b44164950e8de0b2a38099d9354a7e5'},
|
||||||
|
{ key: 'd4f174c0e72a1466c951329509aec5e7',
|
||||||
|
iv: 'a719cb40f3b7125ee7f2306434852cfc',
|
||||||
|
pt: '1d2100',
|
||||||
|
ct: '92f59cc6543fd2da488fdc04d2b4982f'},
|
||||||
|
{ key: '54ddee3a2694df6f7612aa065b14cf31',
|
||||||
|
iv: '2d572df96cf4e224ccf61ace7376e731',
|
||||||
|
pt: 'b7fc937d',
|
||||||
|
ct: '32b46b99d90213ab16caaa184ae63946'},
|
||||||
|
{ key: 'c22244ec29cc5c037ba8b3118a3d283a',
|
||||||
|
iv: '6ce97a977464ddf05155b1c492c8ab02',
|
||||||
|
pt: 'e8928b2000',
|
||||||
|
ct: 'ebe257542d9712d11dd11701ed758379'},
|
||||||
|
{ key: '4db2aa81834fb2f06c3ea1c5df24073a',
|
||||||
|
iv: 'dc096803b232b0290cab20fe6146d1b1',
|
||||||
|
pt: 'e64fa3b00013',
|
||||||
|
ct: '8841ae4645b1691a5ccbf29f3ae5ac3f'},
|
||||||
|
{ key: '351c879ead5537158f956131d760bbd9',
|
||||||
|
iv: 'ae275ac6dc726be6de5699f7d47965e3',
|
||||||
|
pt: '75029324bb7e00',
|
||||||
|
ct: 'a92de8911739838c5b4a54eb72bb784e'},
|
||||||
|
{ key: '3140906ebd809aa944a2ab4130fd0e30',
|
||||||
|
iv: '6533608e75ff1f4808a83fed0defcf15',
|
||||||
|
pt: '40dc5b866923cd98',
|
||||||
|
ct: '959d6071b0250e598f2a05d9462a9039'},
|
||||||
|
{ key: 'bee40d04ca74ce33256b36b4ec9e8f10',
|
||||||
|
iv: 'e5b5e8679ddf8498cd6a4a91f21f8429',
|
||||||
|
pt: '20966e1b5a32485900',
|
||||||
|
ct: 'd4f95975d6fec328f23097b614da9a02'},
|
||||||
|
{ key: 'b5a9e4a040be44f8c7bee70915f4f9f2',
|
||||||
|
iv: '6fd21ae15b6cd50ce4d8c742756f3166',
|
||||||
|
pt: 'a0852c8b5ebf10573d87',
|
||||||
|
ct: '068bc0b4e78db558b4139b98345390e7'},
|
||||||
|
{ key: '2f7b0b456d4b0f1c56a76acd8ad62175',
|
||||||
|
iv: 'd410d9f5dd5a7b7ba6c1e8892d52abe5',
|
||||||
|
pt: '8ec711ec4542912c60de00',
|
||||||
|
ct: 'd9e7216d902302126def45f364b77a6e'},
|
||||||
|
{ key: '2e5d947a11568b91b4002dc534f75980',
|
||||||
|
iv: 'ed7a554fa987ea62f3a9493e1834f13b',
|
||||||
|
pt: 'e64812413d4d62ca2105594d',
|
||||||
|
ct: 'd50f74e4cc6ede7fa5543fb8914b68a2'},
|
||||||
|
{ key: 'a70d82626dfe6a78febc7e409e02a8d2',
|
||||||
|
iv: '4afa79a4fa7214ae3206edbcaa583ca6',
|
||||||
|
pt: '9fd2db77f76f35b07632a8a200',
|
||||||
|
ct: '374d0cca0caed7903503ddd578c50dcb'},
|
||||||
|
{ key: '4cce464be97d22dbfeea0e1927e354fa',
|
||||||
|
iv: '14ab2f0a265950d42965d5e10db21cce',
|
||||||
|
pt: 'e36418499ad8fd6bb23857630f8b',
|
||||||
|
ct: '58f42409d9c43764a1bc01b67f8372e4'},
|
||||||
|
{ key: '61b3ea7bdae146e8b4423d8235bdb177',
|
||||||
|
iv: '2ee9315405791f97cfb407183b376d73',
|
||||||
|
pt: 'dc684e62d2b860a6ed9767c252fb00',
|
||||||
|
ct: 'f68c632e85c4c54e9d306e0b18c6f3a8'},
|
||||||
|
{ key: '9630d3c4aff96dbbe38cd66c75392262',
|
||||||
|
iv: '570269363841d528397e938360cb2fbd',
|
||||||
|
pt: 'e5b641941eeb811335bbc80f3b507899',
|
||||||
|
ct: '79196dcdc74747eb60f387378b558243436f2b9e08f9589004a7b084f1b76fc5'},
|
||||||
|
{ key: 'd89d15abad3f967821d5c5c85ac55b9d',
|
||||||
|
iv: 'ee742d60dd3caf5ff2bc89fb128909b9',
|
||||||
|
pt: '03ef2d7fec1d4692e2c67cc19c5a9f8b00',
|
||||||
|
ct: '72365e907006bf2d77d610758327f34dffc860e1f962f45fff6a4b5e5e9cc1d9'},
|
||||||
|
{ key: 'bde6416bddddb2eb75409dde200f5f48',
|
||||||
|
iv: 'a061380881269ce94777d5ddb6b9dab8',
|
||||||
|
pt: '30d95187f9e967a1a32fff6438c582b0922b',
|
||||||
|
ct: '51750ae35f819e27f6bd8b3ac3b0cec092634c3699b47c9e323b32c932f93b2c'},
|
||||||
|
{ key: 'cf4234be6284f19236fa193fc319999c',
|
||||||
|
iv: 'baa9dda1ace10acc87e7b15cf2747105',
|
||||||
|
pt: 'd8ba43941ad60cf173236d5da3f90d5f9be300',
|
||||||
|
ct: '0c982ea7e130212d40d2f0d50badcfb8ba86c167ff1c87fa2e5563b6c5b9bcea'},
|
||||||
|
{ key: 'fd91a35802f1297d528c0c174a5bbefd',
|
||||||
|
iv: '9c4f8a944e85728aaa66f0ca2e5731e1',
|
||||||
|
pt: 'a015232023d931bdbf07a21368cb2ad2b2f41a79',
|
||||||
|
ct: '77cf9d88969310224c453213a0a43bfc46adef36ed0ad3433717c844850c18ee'},
|
||||||
|
{ key: '59c9e20047a695931ed0331586f9f3c3',
|
||||||
|
iv: '3db8fe673a529369b967653bc87a71b5',
|
||||||
|
pt: '0310dcc07920997995a028c6b2e9291bbeaba6dc00',
|
||||||
|
ct: '333657878de1d3c64afeef50894c3266266b5fd5ec875e5196f8aa2b171e6cb0'},
|
||||||
|
{ key: 'ea408bd9d05f3fbc403b3573e2d25efd',
|
||||||
|
iv: '720647d5cb3f263cfafd3860554b2754',
|
||||||
|
pt: '5224dc0e4646d613e238d90cd4f6d6fdd1094727fa0c',
|
||||||
|
ct: '9e3e53ae69076c2b41cdb710803ce4fdecfc429e3858862864edc0750d370705'},
|
||||||
|
{ key: 'b9682daefe6183e15577cd2cf930d14d',
|
||||||
|
iv: 'cd8c596053366912c0e617777908a9f7',
|
||||||
|
pt: '1889ea8e0807fd7a53adf9d3be4354addd2a1f191aee00',
|
||||||
|
ct: 'c008155179beb8dab6912bbc65b364acdb4d26faf9200b66c9e215ff7427fe2f'},
|
||||||
|
{ key: '87ff9cb14ab295d3d75133947c1cf313',
|
||||||
|
iv: 'ffb8c07bc0a69eee21d756b41913b6d3',
|
||||||
|
pt: '26ca689b9d33314a7edeb87e16854e7455919ebb4aea0e5f',
|
||||||
|
ct: 'bb43876e5136d739174403696fff0864e54a972696c824e85d34b7c4919e9ea4'},
|
||||||
|
{ key: '535a90505b7883db23b81b3a0c06cfb6',
|
||||||
|
iv: '987654b0884810c6766b5d379eb23757',
|
||||||
|
pt: 'df0b45b8a687eab7a55e60e7d9ff67d6a89220f9d021cb4100',
|
||||||
|
ct: '538517df958d671bb24e906536a184422bca5e21b8a676831d67a29294773ebb'},
|
||||||
|
{ key: 'e3c5d819fad40a0e1d0b286629470ca7',
|
||||||
|
iv: '09be9361930af491075a69ccd83ed7a0',
|
||||||
|
pt: '33d5bb83984e4df8c78315714122bc5b9ee572aaaa2d3616597b',
|
||||||
|
ct: 'b32e4f20f6ca08efbbfd5dec794c29ff61e7e49c9a420c5a3cf629941cf22ab0'},
|
||||||
|
{ key: 'ddd178208107f37b89a7ecc1f7256e54',
|
||||||
|
iv: 'd0bd6cd9a20ff82ac63ef5b0dc8e5bf6',
|
||||||
|
pt: '329e22215546c3c005304bcba101ce22f450de32e3c03553d75000',
|
||||||
|
ct: '8917031f9ca41eeffd4f8a0eeb05cda09d2c098b0be7327dd97379890eb7a100'},
|
||||||
|
{ key: 'e55870370045008ecfb37342fe0665bc',
|
||||||
|
iv: 'c28e966a6069cbc2ff49ab91ae9d5163',
|
||||||
|
pt: '9b00bf0e202852180b24080c7707ce7bb4bce84c19772a9d1571ab73',
|
||||||
|
ct: '83f477f200ae3bfe2e4337d53b0b59124410e0e6d3b5c0bfe9d0fd6c62d755be'},
|
||||||
|
{ key: '790442c04d0ee830152887307346b5cb',
|
||||||
|
iv: '2e59e9ddb6d7a7bd685c37f7616d10c1',
|
||||||
|
pt: 'a5eeaa6d82180f1d885b1c3debae35afb5a464b803b96d9b07b2464500',
|
||||||
|
ct: 'b60ac84a073869f4e7c5bd36ec383fc8645cedca44a78252892aab9102b07500'},
|
||||||
|
{ key: '6dc960c89141928e581b0b0250e80f71',
|
||||||
|
iv: '1222e688ee4c1d73f3b1a52fb5256f28',
|
||||||
|
pt: '2f6c15acc481c06eb57b444824c00148636c09a4dce7d12e2ef2915394d7',
|
||||||
|
ct: '0646894ed9bddbd373de7d64e4994fd38b7d4502e8ed38a6384a20f5ee729de6'},
|
||||||
|
{ key: 'cab5adfeb428f91872e03b04faf771a8',
|
||||||
|
iv: '68606a14a86cece478b337b0d72b6018',
|
||||||
|
pt: '738c3c06aacd07fdb49a15879565c5db0d43c91f5ab3ecf4ef4b432afa7100',
|
||||||
|
ct: 'aec39dceeac1497d383c42a1d88d31a04a5830b8f302ce8dc4ea5a93c269c09c'},
|
||||||
|
{ key: 'eb870b0cefeb90d8baf11be40c97246f',
|
||||||
|
iv: '042258eeddfeac2d56f5305be14d7cf7',
|
||||||
|
pt: '3f8cea6d9ebd3039dddb96b0a50dc5056b84794a81cd9b455c68f2d5bd7dc9d1',
|
||||||
|
ct: '2544ca1e2f3f1625c8ea2526423de65f819e6f33e835be48a9912e4bc168d4bb5186c6839ab2a30ab95e3a0009205b1d'},
|
||||||
|
{ key: '0e617fe76bdadc619f090c64871a4f40',
|
||||||
|
iv: '5dc4edc2cf625324e5f4d86e6ea06bee',
|
||||||
|
pt: '44a0492be0dfb9c7f2849146deaf35dd3b52c381ff5d120e0ba77693aeb117b200',
|
||||||
|
ct: '5a32033dce1b8827b0d8dc5afbf73f7da4cc59e33219eda4ab6f56527331782cafcbfe68d6abc91db4ea48218aaec1ca'},
|
||||||
|
{ key: '50c7af12e391b76d5285b05677f733aee66602dd8510fd8b',
|
||||||
|
iv: 'e45e1f84b016f44e5bb6c4e51a9aa712',
|
||||||
|
pt: '',
|
||||||
|
ct: '73bf44d50eb98876cd0731925c111317' },
|
||||||
|
{ key: 'a48beaa956ed4a76522e622bce69555b0defc0ad2867dd6a',
|
||||||
|
iv: '4ab495fe424477345f0eb55818566ec1',
|
||||||
|
pt: '00',
|
||||||
|
ct: '300d78eb45bafc15eb58f67d3b62386f'},
|
||||||
|
{ key: 'e0d18e04cedfe3a261da48431c0027944164bf9c641c873b',
|
||||||
|
iv: '0cb4054c985215afb7da003011a1fc34',
|
||||||
|
pt: '1b35',
|
||||||
|
ct: 'f5e3f5fac1c4ae994cbe2b7bf7b88d80'},
|
||||||
|
{ key: 'f6a13d3a87d9f2620be349fd30d1eeba22d0a25e37ffba9d',
|
||||||
|
iv: '9a94d5cc2bab6b9a07d828657f64e8b5',
|
||||||
|
pt: '7bf100',
|
||||||
|
ct: '9562603ce54a8f7168f67ab6f0ea03b4'},
|
||||||
|
{ key: '8b68ea634ec49a93509ba6894d882548d9dfb6c51645a589',
|
||||||
|
iv: 'ca195407ed8391ff818ee98eed36d875',
|
||||||
|
pt: '3f7c67f5',
|
||||||
|
ct: '5ed17eca0fdbb809d49db866cc4e1c34'},
|
||||||
|
{ key: '6c1ea81194f81fe46485cd46e8b652cb68717e29f1874a32',
|
||||||
|
iv: '5e1b7bc261b4d23ff241ba9196c44741',
|
||||||
|
pt: '785c4f3900',
|
||||||
|
ct: 'e11bbbaf7f41cdcde84d7b15100c4892'},
|
||||||
|
{ key: 'f8bb94da21490c3c3fe9c98bc42984bc7ed803bdaa93e504',
|
||||||
|
iv: 'bd532eab4ccbc985774481f78790ee32',
|
||||||
|
pt: '17fd0f15d01f',
|
||||||
|
ct: '1a9c9d266483805b27826c3de6c2d2d8'},
|
||||||
|
{ key: '129fd4064bdaf0998174a772ec62e5475e07df2c760fa38b',
|
||||||
|
iv: 'a3862ad96d3f3abfe41576c82b180de7',
|
||||||
|
pt: '53b10a93df9100',
|
||||||
|
ct: '5eb656dbbfc4645648f9c3441fbfe91b'},
|
||||||
|
{ key: 'd5acf63c908e61ddd8bc372648c38e099f49410e7a857492',
|
||||||
|
iv: 'e8a5c8459fba4d628edde2b6c6dba6c5',
|
||||||
|
pt: '6d4b04f72c780d0a',
|
||||||
|
ct: 'c7d3840e66b034780c94ab5f266ae2e4'},
|
||||||
|
{ key: 'd32d90130666a43edf3b66eb2737d0c0cec80ebec006ba1b',
|
||||||
|
iv: '70c5af55793796091dd8429e2d91ef50',
|
||||||
|
pt: 'da1ebb164a2d4ec100',
|
||||||
|
ct: '6155514d17b4403583a1ab7867246a68'},
|
||||||
|
{ key: '66f79944768cf85532c3cabf47b7f36372f5ec1fa690cdbe',
|
||||||
|
iv: '448e8e99506c9e5123e97a7bf10e62d6',
|
||||||
|
pt: 'b6f2987003f5a5c1dc61',
|
||||||
|
ct: '8d5dd0400c8c8e1e8f95340393e17424'},
|
||||||
|
{ key: '8e204f1b66199c730c2a9a84652de895cd53160f0e87d978',
|
||||||
|
iv: '46d36b43b401d389162e91e5de6c8ed9',
|
||||||
|
pt: 'f40da33a6d06ec4fc6a000',
|
||||||
|
ct: '9579daaae370add6ee62f276f3037b73'},
|
||||||
|
{ key: 'f678e7b672fe8d5b9801e43dd2269f7449e12f6cf1428ce4',
|
||||||
|
iv: 'd88f8091018b3c76656796aa0fa0a34f',
|
||||||
|
pt: '07cc0d9010df0d4fe707d348',
|
||||||
|
ct: 'ab72afc254895680acc0e0761fe6bda3'},
|
||||||
|
{ key: 'eec2452f01772a1c7df6d5123aac113b0db9c2c47cd7a691',
|
||||||
|
iv: 'd5d978588a7e4164898a629b2672de8f',
|
||||||
|
pt: 'ce9dcec460ea2750aa70beaf00',
|
||||||
|
ct: 'eb41241048e48185e82c8f92a0504a69'},
|
||||||
|
{ key: 'f8017da8d19bc42b286b7e789bd414088839642755c6b702',
|
||||||
|
iv: 'a064e7b3afd4cb802d0b4fc90a324682',
|
||||||
|
pt: 'e9edb0f9205896aec914b78708ad',
|
||||||
|
ct: 'd05eadfb7ae6538201b15946b25e9609'},
|
||||||
|
{ key: 'acd7d8b829da722568f4087191c08e58927d5ce529846336',
|
||||||
|
iv: '3d81241852001aac5cd590c39b262d04',
|
||||||
|
pt: '8ed43dae2376c703767bf102b00f00',
|
||||||
|
ct: '53f28dd117cc0c94b70ceeb2f2587ce2'},
|
||||||
|
{ key: 'f5b191b1661306525522c6730723b68b8c0112140915c448',
|
||||||
|
iv: '74d36354e6522e00f389c79180f4640d',
|
||||||
|
pt: '07857574e029d46eb93f0759a378a9af',
|
||||||
|
ct: '002c55318fdef1edde038c6568b61ab9ede588ad33ebb3a99aa94637d35f401a'},
|
||||||
|
{ key: '0d4b54fb98309a501fa7b308dd1fa62aff45b95edebdaad7',
|
||||||
|
iv: 'b54954cd7f7724135fa8c64cf9f82ba1',
|
||||||
|
pt: '085c6900854de678747027d2b9f3c32700',
|
||||||
|
ct: 'a2199b6d0dbbab4b0d7374bb4555adf05d3eb81bbf409850ea3cbf383c6349f5'},
|
||||||
|
{ key: '8e115f1a9b1b49651e8f5ac930caa789f8e4570252522b5f',
|
||||||
|
iv: '46262446985936cdeb4026b9e0d1e67e',
|
||||||
|
pt: '294ed502f560ef1d0fda793bd0867eee25f4',
|
||||||
|
ct: '87448b44e4202a31fb352c602c69101014374413e3680605872005bd1165dd22'},
|
||||||
|
{ key: '730133c2bd3e434bc809f967844ef4e866155012ad932781',
|
||||||
|
iv: '7e6d0d7526c386b7a49c7718c8159854',
|
||||||
|
pt: 'f58709f86d0b9a86dd9785aa0ebdf39d1c7900',
|
||||||
|
ct: '6ba1b71d05d75e636194c9e0d5ddf19161f887cb1880abe1c0502b08f3010317'},
|
||||||
|
{ key: '859e5acfcb8967c05469a0399f152413813d49f065010402',
|
||||||
|
iv: 'ff9b037bd6aceaf9410a404814ccc62a',
|
||||||
|
pt: '6a0ccd32f03e3582ac8c1159abcaa32f34a21e68',
|
||||||
|
ct: 'e38b2a9a8f9b55ea27d3c801709b80727058d1f348c4a60456d95b6e95d1f0b3'},
|
||||||
|
{ key: '80615fd06086b35d2f08b6d960a7408dc2c0aa1346cd4c7e',
|
||||||
|
iv: 'a45f31093f6437584b50f0e486fbc538',
|
||||||
|
pt: 'cb0abed2fca17517cad750186a86c4b6bc5ee01a00',
|
||||||
|
ct: '0d47057c9d143c763049362dead1ac4f78700207a9d9b4b3c42104407418983c'},
|
||||||
|
{ key: '57290fe1321b21737709db8a45a27ebd6e8bb0516e6d484a',
|
||||||
|
iv: '3959637361c755de29eeac9a27026cf5',
|
||||||
|
pt: '01d2099d8fb744aa3c98104e891e6d7988e50c55af98',
|
||||||
|
ct: 'd2134c493353959fce3038edc680e2772f6741625f4194ce269ff8d4e41e0631'},
|
||||||
|
{ key: '3aca898b3131ad101ad8baa309de222d6d3516759bdc3b47',
|
||||||
|
iv: '5ce544757e77b156defd6e9d4fcc071e',
|
||||||
|
pt: 'f9d48cc42d5b8fc9e27b3a2b88fe7ebecafa47adda8600',
|
||||||
|
ct: '1a2c0cc15746cdbd87efa34f3dedae4bab98dfc75ef2bdd8ae40404d94058199'},
|
||||||
|
{ key: '3dec2d715140c4c0cda2ba07b1a0c30fa99b94b77531cf1a',
|
||||||
|
iv: 'aa721ba32e7f638a5254d139ff8b8403',
|
||||||
|
pt: '2adcd886c9628385a90af487d9c79a459004efdcd1f98525',
|
||||||
|
ct: '83da49e56631c3f75bfe75a074b4d7c0e06d15c80b706aa3c41b3852449e368a'},
|
||||||
|
{ key: 'f340374a5d5b09b46f71f7ca015426c4413d4774cfe923be',
|
||||||
|
iv: '02dc026b751f02ce289a1f39c4d8bd07',
|
||||||
|
pt: '6e4b922d5874971948268516468474439ed605d2a4204abc00',
|
||||||
|
ct: 'c804a0b6203339d4ef2101309ac53d2635a15bb28ee3f01617e3afd607190806'},
|
||||||
|
{ key: '3d6b00bd836a4c902c634a93a0d88982d7cdeca4c289e190',
|
||||||
|
iv: 'fcfe8bfe9ce3da49d49fcb539c209c42',
|
||||||
|
pt: 'b4fea16b13cff9f0d8f6ed34e3b83fb6a2fc4d12a6f6ca5f585a',
|
||||||
|
ct: '9478992d05617f0d80580942f05042f8f97d45093b4b2bdefad69a5bd375ac20'},
|
||||||
|
{ key: '633c436c8e0bbfbafe19743630086411518882f0f3ee773c',
|
||||||
|
iv: '3d659bd81c6ad290987d3e8c3af4366b',
|
||||||
|
pt: '643cf0b0274ef953bc7b8c493addc2408e3864b5e26185f9ca9800',
|
||||||
|
ct: '98911164893aa7cde799212cde322b228f3982a601030738ed7be46e8861e041'},
|
||||||
|
{ key: '6ec4dada6fc9cbdd5e9257113c3fdf5d889396df6d59f42f',
|
||||||
|
iv: '4915dd59766933d8fa836486cf203e86',
|
||||||
|
pt: '9dc6fe36d1c9770e4d83101e88ddf383546dbf0ca6eee2e60984886c',
|
||||||
|
ct: 'fa3798196a9520dbf5375f2800663b96f848d5fc9de31eb91f30204d4278604b'},
|
||||||
|
{ key: 'ae8fbb9fcbc656f862664541a8ea39555086164edbc71ecf',
|
||||||
|
iv: '2bafcf66f154c9202fa84b1aa26d85e4',
|
||||||
|
pt: '0b0f0187ad816e62b0d5516d75edce884c3dd96a7b99dea33220793e00',
|
||||||
|
ct: 'c48eed40fbf45a2303abf5f345dfe5c6b2054b2a9e0086cd13981cc4e29e87e5'},
|
||||||
|
{ key: '50ffe49b53f7d8f7c7bc2c7cbb20b3a0a62887f2f1c401d7',
|
||||||
|
iv: '074b5d68e3c10f06c681c3b62b3f4f4e',
|
||||||
|
pt: '11a68218945f7fb8c0be0a39e66d19ec96fff29b5e346a1c63287382978f',
|
||||||
|
ct: 'ed2f175848a2fb82977f844ddc2fc84f2ab17b66a183fd4404e4456348d83d9b'},
|
||||||
|
{ key: '030df814a29fa9f08e31c5bd83938235eb4f5a0b6ea9de8e',
|
||||||
|
iv: '0ee1a6fc92cd0df4e1febc429aaae981',
|
||||||
|
pt: '98dc43687a9b9cda4ff44c6187d42b9d34cd9bdacd499a25df8353258a4200',
|
||||||
|
ct: '5a644a17025d45fa227dd1a009af52545d471e6f8b4dbaeac195e806ce887c5d'},
|
||||||
|
{ key: 'ccbddfc6ecfc44befa8c98d36afe98d94ae17e40c0f66136',
|
||||||
|
iv: '0a5ad4c27cee489754d7370758c14eab',
|
||||||
|
pt: '2fb8d075ac4c663b8b62436cfad3d0bef8c59aea55d1fb031f0b66e35580c570',
|
||||||
|
ct: 'fd23f01f87661418bfcb80100ac30b0c67fdf0069ca78be7632d64e86114bdbafcfb5126ae2646398bbf7e2d1693d602'},
|
||||||
|
{ key: '8473dc849d97b203b6ae97ace84d14760efc214d00f7245d',
|
||||||
|
iv: 'ae3cadd77f45b927bcf6e91cc4ad1d0b',
|
||||||
|
pt: '562448becd74320bfbd19455270db6a1e864f3473b2b32d728672d2bde54a67900',
|
||||||
|
ct: '04949c4d7c22af8126d0ba47e0dddc6f6dcbf1d24f3ec250ad19c19e733a26d852a18dda1e42ce7c7002b6d4cff0f083'},
|
||||||
|
{ key: 'e42f351d7ba0b0d5e7179206f9d4cd7317102f6159823b65bce123f82fa738a8',
|
||||||
|
iv: '5d7fa5578780f234a52bb2848e7a94d9',
|
||||||
|
pt: '',
|
||||||
|
ct: '7b8b4685a4943225e50025ef2a617b39'},
|
||||||
|
{ key: '3d25c893d44c4a831b5df70dd4796e31da1511fbcc01050ed3136a3546587448',
|
||||||
|
iv: '6d794b58f8f72cc5176fea41d7b8103e',
|
||||||
|
pt: '00',
|
||||||
|
ct: 'a8f470e9302cea96e58d09987329b40d'},
|
||||||
|
{ key: '7d85cd994cff3194f0e02816eb0b7e78d564135c19dadf419d40fd3bc6d26f82',
|
||||||
|
iv: '207a8f2cf340b2951098d6dd28b5a664',
|
||||||
|
pt: 'f619',
|
||||||
|
ct: 'eba7bc0584cce840224eac2c6e7321b3'},
|
||||||
|
{ key: 'e8022cb73009b51e675445d913926d88d8e8512146dd1bada2747953178a6370',
|
||||||
|
iv: 'd7c8a742aa0b10d82e6e2ced39ae192a',
|
||||||
|
pt: '222c00',
|
||||||
|
ct: '417b29e8a97f2e603137aead26b2da78'},
|
||||||
|
{ key: '0c5308090f8e8716978a6313687bc6b09e1ac61555cf6402268ae8eebad68b88',
|
||||||
|
iv: 'a08cd0b57d560419c5972bf84c5d19fe',
|
||||||
|
pt: '1612e835',
|
||||||
|
ct: '9690c1b51388d69b821164234bddb2eb'},
|
||||||
|
{ key: '992de58faee1a7082bf84f0bffbe9c6cf465cf4238b54481a9051d0df1a7c150',
|
||||||
|
iv: 'e0f4e6f2781b86b9d13a410b50dfd364',
|
||||||
|
pt: '1a66a62700',
|
||||||
|
ct: '4cb1335dd563d5a81c9736b1ac06a82e'},
|
||||||
|
{ key: '8a4ec0ca2aef8544b6602ae70d8682b87543865990fe2b86ae7ee24b5c6a3089',
|
||||||
|
iv: '30d322e9f6e8846edf4214fefda3f890',
|
||||||
|
pt: 'aacb743e4a9a',
|
||||||
|
ct: 'd8c6324bd196f5c36a852e1df72dcb5b'},
|
||||||
|
{ key: '23a3e7cf5ed77731db0208bdbdb54ed45361c5b33dc4b8c171492d689991f47f',
|
||||||
|
iv: '8672d7eb0dd94a26931772099c648186',
|
||||||
|
pt: 'fc2c294896a800',
|
||||||
|
ct: '294f60476255a83f760892fae7367724'},
|
||||||
|
{ key: 'da9f1cd9d0b0b0ca3dd6913fae90f40ec455a29a6bc7cab186c4a736290b21b7',
|
||||||
|
iv: 'bb35cb6b12d21fb8f8a8ce260ef498a5',
|
||||||
|
pt: '1f45ee1012d3d3dc',
|
||||||
|
ct: '2ce43566dad01626bb19fd16b45bcd48'},
|
||||||
|
{ key: '27f0a99b7d78bf2a9bdf991f18002cfc2987c91a418a3da84c685d8779858fb8',
|
||||||
|
iv: '0a060f98940d7c254122273c20057dcb',
|
||||||
|
pt: '778272f3c39c776000',
|
||||||
|
ct: '0fb9a117463517c4c49c34cd162e1651'},
|
||||||
|
{ key: '318c48bbc94f05ed741557feeff2eb686cabe0795b42c7284d8f80f087a9b68c',
|
||||||
|
iv: '5980865193dde231cc1b4359010d6a84',
|
||||||
|
pt: 'edfe5f69aa55a95fef1e',
|
||||||
|
ct: '649f883586ba0de28a9a185435a554ed'},
|
||||||
|
{ key: '5b8d1dabc9f061be17454dd5f7962d1a5c771c17931c63a4f3b2eba485a08c8e',
|
||||||
|
iv: 'a65b2decc5c1d756a9429d3cd1ef6a84',
|
||||||
|
pt: '705fbe4cb096cf7120d700',
|
||||||
|
ct: '84a5a325fa8432d786f56d71fcb91a3c'},
|
||||||
|
{ key: '00f3b406136d9b532e03209cd92afac62cf4fda70b24e6a950dcedffac93ba78',
|
||||||
|
iv: '97c2d64f66da929faac6e8eded626b6a',
|
||||||
|
pt: 'b168557e2ddb25157dc5fb28',
|
||||||
|
ct: 'bcbe4093a2b26fdddc751d9c904a55ca'},
|
||||||
|
{ key: '94eaa150bab6967835bb5b9b7b13deb2b67719c1f45658e3a5e937f5279387ca',
|
||||||
|
iv: '5ae415aaed85b3dbba720ba124571a5d',
|
||||||
|
pt: 'a2a2a3403195ac28054a92e800',
|
||||||
|
ct: '4a0600326d2b83d0b7aa495e7c4cb295'},
|
||||||
|
{ key: 'c93e88093db3da5d132972d626c9e642626698b138e4b6ebca598c5d2f67fb84',
|
||||||
|
iv: '4bf19d191ad4a007b60487b716b0541e',
|
||||||
|
pt: 'e05f9e4193974f6de481c399ce1d',
|
||||||
|
ct: 'f4aeb017addaac5445e43ce8598b7cb7'},
|
||||||
|
{ key: 'b83958925488ac2a40ea7d2ef50daf8cd43e83c0a95597d5b26588f8baef3bdf',
|
||||||
|
iv: 'dc0471d37e3c18249ee09e9cafe18cb7',
|
||||||
|
pt: '0c2f78fd281f9afadd49965f318500',
|
||||||
|
ct: 'b50f9001fad8bb39790bad3cb015af66'},
|
||||||
|
{ key: '07b43d7de698307daee4b214556fc6fd869e042bb3b955bd5b799d9ec80f1f55',
|
||||||
|
iv: '5bfadcb756f387854583818a705dced9',
|
||||||
|
pt: '1629613b412b367b9cf8080bb6c594b0',
|
||||||
|
ct: '44ff68d98123de4e33c3527394d20ead6abf19c5d848ca97b258659e2faa2194'},
|
||||||
|
{ key: '288ceb14f13940f8d0b416132e64194df0529070bac94a05cda1be6e2c644066',
|
||||||
|
iv: 'c93174e1d2112e42ba1941a1b9d3bfe9',
|
||||||
|
pt: '379ee7e5d08d834343175d3cdab361c900',
|
||||||
|
ct: '8ba1793815e70b85ec36e6c6515344cb5a5524677d8b2635ae352b54b222c9f5'},
|
||||||
|
{ key: '429076f04edc81c21a3788dc02b0e85b6a63f64f7c6a97614152d3cdd9ce0a87',
|
||||||
|
iv: 'fdafd103abf2d65ee1e24a8f926d435f',
|
||||||
|
pt: '23f85a48808db6b6d87ab9dbffaac55c7790',
|
||||||
|
ct: '24c35bfb5a7221e698c09193a1fecb3a16ecc6d66f9ed8bf828013376c0fefd1'},
|
||||||
|
{ key: '0098016faa7c5a4a42d3c944de9db27cce8df467be0923dab466f48662302f44',
|
||||||
|
iv: '0a58058a38cfc3dcbe41afd18d796185',
|
||||||
|
pt: 'cb5956d8812e4dc08db4bfc91d3721f9a75300',
|
||||||
|
ct: 'd4d993d92b11d853b8b9e4d14656291dca499816cc7a104b245898e3c5cb0402'},
|
||||||
|
{ key: '974335cd8f5202814130bfc3e718bcdc3e611657f89ac06b90bbe70e67ef3829',
|
||||||
|
iv: 'f6cfe8993f36cb99c38adfb94acaea2e',
|
||||||
|
pt: '826533e3cb26ee4918da7dedaa3d8a6f3d1c9e2c',
|
||||||
|
ct: '2ef88001acda2734b7cf6ed86eb8549cdf9f96ff2f4c2fe01138f42d6ad45c80'},
|
||||||
|
{ key: '32ec8f73cca288f2743cb899e8b8268df5657e5c2a2638f1678768427c677477',
|
||||||
|
iv: '5fc5f1e47181e654f4a8325b4befcbd2',
|
||||||
|
pt: '833f4b472037e10e99b29083e8a882988a756bd600',
|
||||||
|
ct: '8f90e66599dd5f17202652e66ccaf75f85b979ead96766977f8f2e3357b3518d'},
|
||||||
|
{ key: '588e8db3532ee70577f63103eefefd0b78785406b5b62ba1d989249e9af76fb4',
|
||||||
|
iv: '75fee3f23b437225677136b11dd3b6c3',
|
||||||
|
pt: '715f6bd71e83debb4fe5c6bce459f7635d4b50589e89',
|
||||||
|
ct: 'e774bbf7db4e7e9156616a4f12215e7b3256b14e74235272921e474f622f0930'},
|
||||||
|
{ key: '91f48a3a74a950f5ca5eacfad8504db442664340f6f8a5e4e6d50a62bb66b2c6',
|
||||||
|
iv: '265b12af694298822222d74ebd1f09be',
|
||||||
|
pt: '89c95a06b68fc9d808d225bf4174ebaa2b070542acfb00',
|
||||||
|
ct: '01b62d1bc7cdab722876ee97f6b9cab8ea6aab64a00de08ec5555b89fa1d8c78'},
|
||||||
|
{ key: 'fc234f3ebbe1efde731029148d53c5c6ded807d98d2a3ce100a3aed0cb27c87e',
|
||||||
|
iv: 'f662ab34223328600c0e92ae72a1175d',
|
||||||
|
pt: '3244ca65d198fb136dd0cbdcfd0f4ba0eafc10a4bb91e079',
|
||||||
|
ct: 'ef5de516dac92afa2773a8c66fb6706a78e928188433257e150fdefe4aace484'},
|
||||||
|
{ key: '3f1f33f564b8e09e6d00056f9fe13c86bf91d823414e52753bd3731e6acd3373',
|
||||||
|
iv: '31a9f9dcfb218dea159138a56ee6081d',
|
||||||
|
pt: '636e9ae2ceb0dc6096eb26bd50d2c922dafb9c50595a261500',
|
||||||
|
ct: 'f4499d125192391180aa92667f68dcff31686c2967ce17879eb5d6aaf927a7e2'},
|
||||||
|
{ key: 'b7e39f0a7ba6bd86df12e9c98191919beb25e49b84aaa575f53c56936a74f034',
|
||||||
|
iv: 'aefd601491a2d43c1199686b83030927',
|
||||||
|
pt: 'a232d965f20ccd91e7f6cbda9bc5d675a4c84e987839b0eb179f',
|
||||||
|
ct: 'e10ae47ff24b1da0bc3bbd84b6ffc1609adf2c60862c7a81daee0302212b4e12'},
|
||||||
|
{ key: 'e00dc9e9d9a0dc526e06892c49a95e86ceebb2a59aba297317ee697479fec6a0',
|
||||||
|
iv: '25e188b2d43c210ced6f57fd174722ba',
|
||||||
|
pt: 'ec7a1b2879e3cade7552f80200d9a0ff1c7f3c33a6fbf301c3dc00',
|
||||||
|
ct: '9bd45b1fe46eee94b0e1d65ea1dc0a7b8d0c9f805e4446c2b299d64a86d840b8'},
|
||||||
|
{ key: 'a0d02e6ef3ca54dbe99df9dc37255ca77ab6abc8385d6c4bbb3f78952e8d563d',
|
||||||
|
iv: '38975ccd24a41caddfbbc2de9113b3ba',
|
||||||
|
pt: '233dc9c2ede16aee5d51bc92f31fa390ee8e3637deb95d6252037668',
|
||||||
|
ct: '676d876f672424cf0c764e36fd59abdd6c28d1e6d048572ad6abcea5d1a5b759'},
|
||||||
|
{ key: '067ac605f536ca420fc3866825e166c20b27c6713654a179fb100c93da184667',
|
||||||
|
iv: '1e743169d0ca71c0fb2786b784a3446e',
|
||||||
|
pt: '36f50fcf087bf9ce1fec841d22b408c914288b718326f023881b9afb00',
|
||||||
|
ct: '86dd788ab8013fe47b086f0aa0d15b7a6a66fae319f6534c843111916e97e541'},
|
||||||
|
{ key: 'd42109990019a30d39f28057188bbd6bd703574b130d714c4040d55a3cce39a0',
|
||||||
|
iv: 'c713d8e6e118e5f69ef775b4c13e0e35',
|
||||||
|
pt: '4e6c7c462ef25d769e32715abc505c979d3a1bbac0ea5acbffa0246a44a1',
|
||||||
|
ct: 'b787a84d26cda07ae99cb7318ba56fe9b294af1a48d0c462a81d05c6b23fd3c1'},
|
||||||
|
{ key: '5f1ac8a96c117e6249345aff36251a186ef4e45e81029746d9454618236106b7',
|
||||||
|
iv: '0e0334deda83ec916bd98a1b8af6212b',
|
||||||
|
pt: '824db874404e9f2ce0683863953665db945fc55f5de3c6a2dff508f0442400',
|
||||||
|
ct: 'ea5ccbae05c37b0185c67d4a5539360ca5ed843dc6484ddba5ccca43eb82f9e5'},
|
||||||
|
{ key: 'ee3c82743640ed6a61d24619ed4b2e9a6e225f8269ec27e1d905e541d76f8749',
|
||||||
|
iv: '6613b555aef40f989c208a7da25ae056',
|
||||||
|
pt: '77f1a3c4e2abe13f46e978d37eef76eca76561cbb8b5ad55a07300b32e6df3fe',
|
||||||
|
ct: '67d4321ecff812dfc8d3b63722f3624894aa533b9101b915900bd2048ed3878067b875e714c55e543664e1fad2b9b8de'},
|
||||||
|
{ key: 'b3e0b79d742b0e8c7f608be8c6f60cee066323ddec13e7e374e2854a2d6e789c',
|
||||||
|
iv: '63af28e5f5a4529c6f79489f90ae1843',
|
||||||
|
pt: '4b759f9f9d496044423151e10250680614977544a7c87299af426cc6f9ed538100',
|
||||||
|
ct: 'd985b810fb206dd341ae3dcbd97c0706456f63eff8be703ba1e30731c7141c081e11d14129d16363bb9de1a200d12ffa'},
|
||||||
|
];
|
18
test/ecdh_test.js
Normal file
18
test/ecdh_test.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
new sjcl.test.TestCase("ECDH test", function (cb) {
|
||||||
|
if (!sjcl.ecc) {
|
||||||
|
this.unimplemented();
|
||||||
|
cb && cb();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
var keys = sjcl.ecc.elGamal.generateKeys(192,0),
|
||||||
|
keyTag = keys.pub.kem(0),
|
||||||
|
key2 = keys.sec.unkem(keyTag.tag);
|
||||||
|
|
||||||
|
this.require(sjcl.bitArray.equal(keyTag.key, key2));
|
||||||
|
} catch(e) {
|
||||||
|
this.fail(e);
|
||||||
|
}
|
||||||
|
cb && cb();
|
||||||
|
});
|
29
test/ecdsa_test.js
Normal file
29
test/ecdsa_test.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
new sjcl.test.TestCase("ECSA test", function (cb) {
|
||||||
|
if (!sjcl.ecc) {
|
||||||
|
this.unimplemented();
|
||||||
|
cb && cb();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var keys = sjcl.ecc.ecdsa.generateKeys(192,0),
|
||||||
|
hash = sjcl.hash.sha256.hash("The quick brown fox jumps over the lazy dog."),
|
||||||
|
signature = keys.sec.sign(hash,0);
|
||||||
|
|
||||||
|
try {
|
||||||
|
keys.pub.verify(hash, signature);
|
||||||
|
this.pass();
|
||||||
|
} catch (e) {
|
||||||
|
this.fail("good message rejected");
|
||||||
|
}
|
||||||
|
|
||||||
|
hash[1] ^= 8; // minor change to hash
|
||||||
|
|
||||||
|
try {
|
||||||
|
keys.pub.verify(hash, signature);
|
||||||
|
this.fail();
|
||||||
|
} catch (e) {
|
||||||
|
this.pass("bad message accepted");
|
||||||
|
}
|
||||||
|
|
||||||
|
cb && cb();
|
||||||
|
});
|
@ -6,6 +6,8 @@ function testCore(coreName, cb) {
|
|||||||
"aes_vectors.js",
|
"aes_vectors.js",
|
||||||
"ccm_test.js",
|
"ccm_test.js",
|
||||||
"ccm_vectors.js",
|
"ccm_vectors.js",
|
||||||
|
"cbc_test.js",
|
||||||
|
"cbc_vectors.js",
|
||||||
"ocb2_test.js",
|
"ocb2_test.js",
|
||||||
"ocb2_vectors.js",
|
"ocb2_vectors.js",
|
||||||
"sha256_test.js",
|
"sha256_test.js",
|
||||||
@ -18,6 +20,8 @@ function testCore(coreName, cb) {
|
|||||||
"pbkdf2_test.js",
|
"pbkdf2_test.js",
|
||||||
"bn_test.js",
|
"bn_test.js",
|
||||||
"bn_vectors.js",
|
"bn_vectors.js",
|
||||||
|
"ecdsa_test.js",
|
||||||
|
"ecdh_test.js",
|
||||||
"srp_test.js",
|
"srp_test.js",
|
||||||
"srp_vectors.js"
|
"srp_vectors.js"
|
||||||
], i;
|
], i;
|
||||||
|
Loading…
Reference in New Issue
Block a user