mirror of
https://github.com/PrivateBin/PrivateBin.git
synced 2025-10-11 04:48:39 -04:00
ecdsa works! now time for some tests...
This commit is contained in:
parent
017ff8c82b
commit
624b61197e
5 changed files with 336 additions and 168 deletions
223
core/bn.js
223
core/bn.js
|
@ -1,14 +1,14 @@
|
|||
/**
|
||||
* Constructs a new bignum from another bignum, a number or a hex string.
|
||||
*/
|
||||
function bn(it) {
|
||||
sjcl.bn = function(it) {
|
||||
this.initWith(it);
|
||||
}
|
||||
|
||||
bn.prototype = {
|
||||
sjcl.bn.prototype = {
|
||||
radix: 24,
|
||||
maxMul: 8,
|
||||
_class: bn,
|
||||
_class: sjcl.bn,
|
||||
|
||||
copy: function() {
|
||||
return new this._class(this);
|
||||
|
@ -103,29 +103,116 @@ bn.prototype = {
|
|||
/** this += that. Does not normalize. */
|
||||
addM: function(that) {
|
||||
if (typeof(that) !== "object") { that = new this._class(that); }
|
||||
var i;
|
||||
for (i=this.limbs.length; i<that.limbs.length; i++) {
|
||||
this.limbs[i] = 0;
|
||||
var i, l=this.limbs, ll=that.limbs;
|
||||
for (i=l.length; i<ll.length; i++) {
|
||||
l[i] = 0;
|
||||
}
|
||||
for (i=0; i<that.limbs.length; i++) {
|
||||
this.limbs[i] += that.limbs[i];
|
||||
for (i=0; i<ll.length; i++) {
|
||||
l[i] += ll[i];
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
/** this *= 2. Requires normalized; ends up normalized. */
|
||||
doubleM: function() {
|
||||
var i, carry=0, tmp, r=this.radix, m=this.radixMask, l=this.limbs;
|
||||
for (i=0; i<l.length; i++) {
|
||||
tmp = l[i];
|
||||
tmp = tmp+tmp+carry;
|
||||
l[i] = tmp & m;
|
||||
carry = tmp >> r;
|
||||
}
|
||||
if (carry) l.push(carry);
|
||||
return this;
|
||||
},
|
||||
|
||||
/** this /= 2, rounded down. Requires normalized; ends up normalized. */
|
||||
halveM: function() {
|
||||
var i, carry=0, tmp, r=this.radix, l=this.limbs;
|
||||
for (i=l.length-1; i>=0; i--) {
|
||||
tmp = l[i];
|
||||
l[i] = (tmp+carry)>>1;
|
||||
carry = (tmp&1) << r;
|
||||
}
|
||||
if (!l[l.length-1]) l.pop();
|
||||
return this;
|
||||
},
|
||||
|
||||
/** this -= that. Does not normalize. */
|
||||
subM: function(that) {
|
||||
if (typeof(that) !== "object") { that = new this._class(that); }
|
||||
var i;
|
||||
for (i=this.limbs.length; i<that.limbs.length; i++) {
|
||||
this.limbs[i] = 0;
|
||||
var i, l=this.limbs, ll=that.limbs;
|
||||
for (i=l.length; i<ll.length; i++) {
|
||||
l[i] = 0;
|
||||
}
|
||||
for (i=0; i<that.limbs.length; i++) {
|
||||
this.limbs[i] -= that.limbs[i];
|
||||
for (i=0; i<ll.length; i++) {
|
||||
l[i] -= ll[i];
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
mod: function(that) {
|
||||
that = new sjcl.bn(that).normalize(); // copy before we begin
|
||||
var out = new sjcl.bn(this).normalize(), ci=0;
|
||||
|
||||
for (; out.greaterEquals(that); ci++) {
|
||||
that.doubleM();
|
||||
}
|
||||
for (; ci > 0; ci--) {
|
||||
that.halveM();
|
||||
if (out.greaterEquals(that)) {
|
||||
out.subM(that).normalize();
|
||||
}
|
||||
}
|
||||
return out.trim();
|
||||
},
|
||||
|
||||
/** return inverse mod prime p. p must be odd. Binary extended Euclidean algorithm mod p. */
|
||||
inverseMod: function(p) {
|
||||
var a = new sjcl.bn(1), b = new sjcl.bn(0), x = new sjcl.bn(this), y = new sjcl.bn(p), tmp, i, nz=1;
|
||||
|
||||
if (!(p.limbs[0] & 1)) {
|
||||
throw (new sjcl.exception.invalid("inverseMod: p must be odd"));
|
||||
}
|
||||
|
||||
// invariant: y is odd
|
||||
do {
|
||||
if (x.limbs[0] & 1) {
|
||||
if (!x.greaterEquals(y)) {
|
||||
// x < y; swap everything
|
||||
tmp = x; x = y; y = tmp;
|
||||
tmp = a; a = b; b = tmp;
|
||||
}
|
||||
x.subM(y);
|
||||
x.normalize();
|
||||
|
||||
if (!a.greaterEquals(b)) {
|
||||
a.addM(p);
|
||||
}
|
||||
a.subM(b);
|
||||
}
|
||||
|
||||
// cut everything in half
|
||||
x.halveM();
|
||||
if (a.limbs[0] & 1) {
|
||||
a.addM(p);
|
||||
}
|
||||
a.normalize();
|
||||
a.halveM();
|
||||
|
||||
// check for termination: x ?= 0
|
||||
for (i=nz=0; i<x.limbs.length; i++) {
|
||||
nz |= x.limbs[i];
|
||||
}
|
||||
} while(nz);
|
||||
|
||||
if (!y.equals(1)) {
|
||||
throw (new sjcl.exception.invalid("inverseMod: p and x must be relatively prime"));
|
||||
}
|
||||
|
||||
return b;
|
||||
},
|
||||
|
||||
/** this + that. Does not normalize. */
|
||||
add: function(that) {
|
||||
return this.copy().addM(that);
|
||||
|
@ -184,6 +271,13 @@ bn.prototype = {
|
|||
return out;
|
||||
},
|
||||
|
||||
trim: function() {
|
||||
var l = this.limbs, p;
|
||||
do { p = l.pop() } while (l.length && p == 0);
|
||||
l.push(p);
|
||||
return this;
|
||||
},
|
||||
|
||||
/** Reduce mod a modulus. Stubbed for subclassing. */
|
||||
reduce: function() {
|
||||
return this;
|
||||
|
@ -218,20 +312,55 @@ bn.prototype = {
|
|||
}
|
||||
limbs[i] += carry;
|
||||
return this;
|
||||
},
|
||||
|
||||
/** Serialize to a bit array */
|
||||
toBits: function(len) {
|
||||
this.fullReduce();
|
||||
len = len || this.exponent || this.limbs.length * this.radix;
|
||||
var i = Math.floor((len-1)/24), w=sjcl.bitArray, e = (len + 7 & -8) % this.radix || this.radix;
|
||||
out = [w.partial(e, this.getLimb(i))];
|
||||
for (i--; i >= 0; i--) {
|
||||
out = w.concat(out, [w.partial(this.radix, this.getLimb(i))]);
|
||||
}
|
||||
return out;
|
||||
},
|
||||
|
||||
/** Return the length in bits, rounded up to the nearest byte. */
|
||||
bitLength: function() {
|
||||
this.fullReduce();
|
||||
var out = this.radix * (this.limbs.length - 1);
|
||||
var b = this.limbs[this.limbs.length - 1];
|
||||
for (; b; b >>= 1) {
|
||||
out ++;
|
||||
}
|
||||
return out+7 & -8;
|
||||
}
|
||||
};
|
||||
|
||||
/* Initialization routines for bignum library. */
|
||||
(function init(){
|
||||
bn.prototype.ipv = 1 / (bn.prototype.placeVal = Math.pow(2,bn.prototype.radix));
|
||||
bn.prototype.radixMask = (1 << bn.prototype.radix) - 1;
|
||||
})();
|
||||
sjcl.bn.fromBits = function(bits) {
|
||||
var out = new this(), words=[], w=sjcl.bitArray, t = this.prototype,
|
||||
l = Math.min(this.bitLength || 0x100000000, w.bitLength(bits)), e = l % t.radix || t.radix;
|
||||
|
||||
words[0] = w.extract(bits, 0, e);
|
||||
for (; e < l; e += t.radix) {
|
||||
words.unshift(w.extract(bits, e, t.radix));
|
||||
}
|
||||
|
||||
out.limbs = words;
|
||||
return out;
|
||||
};
|
||||
|
||||
|
||||
|
||||
sjcl.bn.prototype.ipv = 1 / (sjcl.bn.prototype.placeVal = Math.pow(2,sjcl.bn.prototype.radix))
|
||||
sjcl.bn.prototype.radixMask = (1 << sjcl.bn.prototype.radix) - 1;
|
||||
|
||||
/**
|
||||
* Creates a new subclass of bn, based on reduction modulo a pseudo-Mersenne prime,
|
||||
* i.e. a prime of the form 2^e + sum(a * 2^b),where the sum is negative and sparse.
|
||||
*/
|
||||
function pseudoMersennePrime(exponent, coeff) {
|
||||
sjcl.bn.pseudoMersennePrime = function(exponent, coeff) {
|
||||
function p(it) {
|
||||
this.initWith(it);
|
||||
/*if (this.limbs[this.modOffset]) {
|
||||
|
@ -239,7 +368,7 @@ function pseudoMersennePrime(exponent, coeff) {
|
|||
}*/
|
||||
}
|
||||
|
||||
var ppr = p.prototype = new bn(), i, tmp, mo;
|
||||
var ppr = p.prototype = new sjcl.bn(), i, tmp, mo;
|
||||
mo = ppr.modOffset = Math.ceil(tmp = exponent / ppr.radix);
|
||||
ppr.exponent = exponent;
|
||||
ppr.offset = [];
|
||||
|
@ -248,7 +377,7 @@ function pseudoMersennePrime(exponent, coeff) {
|
|||
ppr.fullMask = 0;
|
||||
ppr.fullOffset = [];
|
||||
ppr.fullFactor = [];
|
||||
ppr.modulus = p.modulus = new bn(Math.pow(2,exponent));
|
||||
ppr.modulus = p.modulus = new sjcl.bn(Math.pow(2,exponent));
|
||||
|
||||
ppr.fullMask = 0|-Math.pow(2, exponent % ppr.radix);
|
||||
|
||||
|
@ -257,7 +386,7 @@ function pseudoMersennePrime(exponent, coeff) {
|
|||
ppr.fullOffset[i] = Math.ceil(coeff[i][0] / ppr.radix - tmp);
|
||||
ppr.factor[i] = coeff[i][1] * Math.pow(1/2, exponent - coeff[i][0] + ppr.offset[i] * ppr.radix);
|
||||
ppr.fullFactor[i] = coeff[i][1] * Math.pow(1/2, exponent - coeff[i][0] + ppr.fullOffset[i] * ppr.radix);
|
||||
ppr.modulus.addM(new bn(Math.pow(2,coeff[i][0])*coeff[i][1]));
|
||||
ppr.modulus.addM(new sjcl.bn(Math.pow(2,coeff[i][0])*coeff[i][1]));
|
||||
ppr.minOffset = Math.min(ppr.minOffset, -ppr.offset[i]); // conservative
|
||||
}
|
||||
ppr._class = p;
|
||||
|
@ -336,49 +465,29 @@ function pseudoMersennePrime(exponent, coeff) {
|
|||
return (this.power(this.modulus.sub(2)));
|
||||
};
|
||||
|
||||
ppr.toBits = function() {
|
||||
this.fullReduce();
|
||||
var i=this.modOffset - 1, w=sjcl.bitArray, e = (this.exponent + 7 & -8) % this.radix || this.radix;
|
||||
out = [w.partial(e, this.getLimb(i))];
|
||||
for (i--; i >= 0; i--) {
|
||||
out = w.concat(out, [w.partial(this.radix, this.getLimb(i))]);
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
||||
p.fromBits = function(bits) {
|
||||
|
||||
var out = new this(), words=[], w=sjcl.bitArray, t = this.prototype,
|
||||
l = Math.min(w.bitLength(bits), t.exponent + 7 & -8), e = l % t.radix || t.radix;
|
||||
|
||||
words[0] = w.extract(bits, 0, e);
|
||||
for (; e < l; e += t.radix) {
|
||||
words.unshift(w.extract(bits, e, t.radix));
|
||||
}
|
||||
|
||||
out.limbs = words;
|
||||
return out;
|
||||
};
|
||||
p.fromBits = sjcl.bn.fromBits;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
// a small Mersenne prime
|
||||
p127 = pseudoMersennePrime(127, [[0,-1]]);
|
||||
sjcl.bn.prime = {
|
||||
p127: sjcl.bn.pseudoMersennePrime(127, [[0,-1]]),
|
||||
|
||||
// Bernstein's prime for Curve25519
|
||||
p25519 = pseudoMersennePrime(255, [[0,-19]]);
|
||||
// Bernstein's prime for Curve25519
|
||||
p25519: sjcl.bn.pseudoMersennePrime(255, [[0,-19]]),
|
||||
|
||||
// NIST primes
|
||||
p192 = pseudoMersennePrime(192, [[0,-1],[64,-1]]);
|
||||
p224 = pseudoMersennePrime(224, [[0,1],[96,-1]]);
|
||||
p256 = pseudoMersennePrime(256, [[0,-1],[96,1],[192,1],[224,-1]]);
|
||||
p384 = pseudoMersennePrime(384, [[0,-1],[32,1],[96,-1],[128,-1]]);
|
||||
p521 = pseudoMersennePrime(521, [[0,-1]]);
|
||||
// NIST primes
|
||||
p192: sjcl.bn.pseudoMersennePrime(192, [[0,-1],[64,-1]]),
|
||||
p224: sjcl.bn.pseudoMersennePrime(224, [[0,1],[96,-1]]),
|
||||
p256: sjcl.bn.pseudoMersennePrime(256, [[0,-1],[96,1],[192,1],[224,-1]]),
|
||||
p384: sjcl.bn.pseudoMersennePrime(384, [[0,-1],[32,1],[96,-1],[128,-1]]),
|
||||
p521: sjcl.bn.pseudoMersennePrime(521, [[0,-1]])
|
||||
};
|
||||
|
||||
bn.random = function(modulus, paranoia) {
|
||||
if (typeof modulus != "object") { modulus = new bn(modulus); }
|
||||
var words, i, l = modulus.limbs.length, m = modulus.limbs[l-1]+1, out = new bn();
|
||||
sjcl.bn.random = function(modulus, paranoia) {
|
||||
if (typeof modulus != "object") { modulus = new sjcl.bn(modulus); }
|
||||
var words, i, l = modulus.limbs.length, m = modulus.limbs[l-1]+1, out = new sjcl.bn();
|
||||
while (true) {
|
||||
// get a sequence whose first digits make sense
|
||||
do {
|
||||
|
|
|
@ -58,7 +58,8 @@
|
|||
/* do the encryption */
|
||||
p.ct = sjcl.mode[p.mode].encrypt(prp, plaintext, p.iv, p.adata, p.tag);
|
||||
|
||||
return j.encode(j._subtract(p, j.defaults));
|
||||
//return j.encode(j._subtract(p, j.defaults));
|
||||
return j.encode(p);
|
||||
},
|
||||
|
||||
/** Simple decryption function.
|
||||
|
@ -122,7 +123,7 @@
|
|||
if (!i.match(/^[a-z0-9]+$/i)) {
|
||||
throw new sjcl.exception.invalid("json encode: invalid property name");
|
||||
}
|
||||
out += comma + i + ':';
|
||||
out += comma + "'" + i + "':";
|
||||
comma = ',';
|
||||
|
||||
switch (typeof obj[i]) {
|
||||
|
@ -160,13 +161,13 @@
|
|||
}
|
||||
var a = str.replace(/^\{|\}$/g, '').split(/,/), out={}, i, m;
|
||||
for (i=0; i<a.length; i++) {
|
||||
if (!(m=a[i].match(/^([a-z][a-z0-9]*):(?:(\d+)|"([a-z0-9+\/%*_.@=\-]*)")$/i))) {
|
||||
if (!(m=a[i].match(/^(?:(["']?)([a-z][a-z0-9]*)\1):(?:(\d+)|"([a-z0-9+\/%*_.@=\-]*)")$/i))) {
|
||||
throw new sjcl.exception.invalid("json decode: this isn't json!");
|
||||
}
|
||||
if (m[2]) {
|
||||
out[m[1]] = parseInt(m[2],10);
|
||||
if (m[3]) {
|
||||
out[m[2]] = parseInt(m[3],10);
|
||||
} else {
|
||||
out[m[1]] = m[1].match(/^(ct|salt|iv)$/) ? sjcl.codec.base64.toBits(m[3]) : unescape(m[3]);
|
||||
out[m[2]] = m[2].match(/^(ct|salt|iv)$/) ? sjcl.codec.base64.toBits(m[4]) : unescape(m[4]);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
|
@ -196,7 +197,6 @@
|
|||
|
||||
/** Remove all elements of minus from plus. Does not modify plus.
|
||||
* @private
|
||||
*/
|
||||
_subtract: function (plus, minus) {
|
||||
var out = {}, i;
|
||||
|
||||
|
@ -208,6 +208,7 @@
|
|||
|
||||
return out;
|
||||
},
|
||||
*/
|
||||
|
||||
/** Return only the specified elements of src.
|
||||
* @private
|
||||
|
|
160
core/ecc.js
160
core/ecc.js
|
@ -1,7 +1,3 @@
|
|||
if (window.sjcl == undefined) {
|
||||
window.sjcl = {};
|
||||
}
|
||||
|
||||
sjcl.ecc = {};
|
||||
|
||||
/**
|
||||
|
@ -145,7 +141,7 @@ sjcl.ecc.pointJac.prototype = {
|
|||
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), this.y.mul(zi2.mul(zi)));
|
||||
return new sjcl.ecc.point(this.curve, this.x.mul(zi2).fullReduce(), this.y.mul(zi2.mul(zi)).fullReduce());
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -160,7 +156,7 @@ sjcl.ecc.pointJac.prototype = {
|
|||
} else if (k.limbs !== undefined) {
|
||||
k = k.normalize().limbs;
|
||||
}
|
||||
var i, j, out = this, multiples, aff2;
|
||||
var i, j, out = new sjcl.ecc.point(this.curve).toJac(), multiples, aff2;
|
||||
|
||||
if (affine === undefined) {
|
||||
affine = this.toAffine();
|
||||
|
@ -177,7 +173,7 @@ sjcl.ecc.pointJac.prototype = {
|
|||
multiples = affine.multiples;
|
||||
|
||||
for (i=k.length-1; i>=0; i--) {
|
||||
for (j=bn.prototype.radix-4; j>=0; j-=4) {
|
||||
for (j=sjcl.bn.prototype.radix-4; j>=0; j-=4) {
|
||||
out = out.doubl().doubl().doubl().doubl().add(multiples[k[i]>>j & 0xF]);
|
||||
}
|
||||
}
|
||||
|
@ -221,75 +217,77 @@ sjcl.ecc.curve.prototype.fromBits = function (bits) {
|
|||
return p;
|
||||
};
|
||||
|
||||
sjcl.ecc.p192curve = new sjcl.ecc.curve(
|
||||
p192,
|
||||
"0x662107c8eb94364e4b2dd7ce",
|
||||
-3,
|
||||
"0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
|
||||
"0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
|
||||
"0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811");
|
||||
|
||||
sjcl.ecc.p224curve = new sjcl.ecc.curve(
|
||||
p224,
|
||||
"0xe95c1f470fc1ec22d6baa3a3d5c4",
|
||||
-3,
|
||||
"0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4",
|
||||
"0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
|
||||
"0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34");
|
||||
|
||||
sjcl.ecc.p256curve = new sjcl.ecc.curve(
|
||||
p256,
|
||||
"0x4319055358e8617b0c46353d039cdaae",
|
||||
-3,
|
||||
"0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
|
||||
"0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
|
||||
"0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5");
|
||||
|
||||
sjcl.ecc.p384curve = new sjcl.ecc.curve(
|
||||
p384,
|
||||
"0x389cb27e0bc8d21fa7e5f24cb74f58851313e696333ad68c",
|
||||
-3,
|
||||
"0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef",
|
||||
"0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7",
|
||||
"0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f");
|
||||
|
||||
sjcl.ecc.curves = {
|
||||
192: sjcl.ecc.p192curve,
|
||||
224: sjcl.ecc.p224curve,
|
||||
256: sjcl.ecc.p256curve,
|
||||
384: sjcl.ecc.p384curve
|
||||
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")
|
||||
};
|
||||
|
||||
sjcl.ecc.elGamal = {
|
||||
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 (typeof curve == "number") {
|
||||
curve = sjcl.ecc.curves[curve];
|
||||
if (curve === undefined) {
|
||||
throw new sjcl.exception.invalid("no such curve");
|
||||
/* 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 (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) };
|
||||
}
|
||||
var sec = bn.random(curve.r, paranoia), pub = curve.G.mult(sec);
|
||||
return { pub: new sjcl.ecc.elGamal.publicKey(curve, pub),
|
||||
sec: new sjcl.ecc.elGamal.secretKey(curve, sec) };
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
sjcl.ecc._dh("elGamal");
|
||||
|
||||
sjcl.ecc.elGamal.publicKey.prototype = {
|
||||
kem: function(paranoia) {
|
||||
var sec = bn.random(this._curve.r, 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 };
|
||||
|
@ -302,5 +300,35 @@ sjcl.ecc.elGamal.secretKey.prototype = {
|
|||
}
|
||||
};
|
||||
|
||||
sjcl.ecc._dh("dsa");
|
||||
|
||||
sjcl.ecc.dsa.secretKey.prototype = {
|
||||
sign: function(hash, paranoia) {
|
||||
var R = this._curve.r,
|
||||
l = R.bitLength(),
|
||||
k = kkkk = 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(kkkk).mod(R);
|
||||
return sjcl.bitArray.concat(r.toBits(l), s.toBits(l));
|
||||
}
|
||||
};
|
||||
|
||||
sjcl.ecc.dsa.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),
|
||||
jG = this._curve.G.toJac(),
|
||||
r2 = jG.mult(hG, this._curve.G).add(this._point.mult(hA)).toAffine().x,
|
||||
corrupt = sjcl.exception.corrupt;
|
||||
|
||||
if (r.equals(0) || s.equals(0) || r.greaterEquals(R) || s.greaterEquals(R) || !r2.equals(r)) {
|
||||
throw (new corrupt("signature didn't check out"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,8 @@ sjcl.mode.ocb2 = {
|
|||
/* Encrypt a non-final block */
|
||||
bi = plaintext.slice(i,i+4);
|
||||
checksum = xor(checksum, bi);
|
||||
output = output.concat(xor(delta,prp.encrypt(xor(delta, bi))));
|
||||
bi = xor(delta,prp.encrypt(xor(delta, bi)));
|
||||
output.splice(i,0,bi[0],bi[1],bi[2],bi[3]);
|
||||
delta = times2(delta);
|
||||
}
|
||||
|
||||
|
@ -105,7 +106,7 @@ sjcl.mode.ocb2 = {
|
|||
/* Decrypt a non-final block */
|
||||
bi = xor(delta, prp.decrypt(xor(delta, ciphertext.slice(i,i+4))));
|
||||
checksum = xor(checksum, bi);
|
||||
output = output.concat(bi);
|
||||
output.splice(i,0,bi[0],bi[1],bi[2],bi[3]);
|
||||
delta = times2(delta);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue