diff --git a/core/bitArray.js b/core/bitArray.js index 40e4acd0..a6d06171 100644 --- a/core/bitArray.js +++ b/core/bitArray.js @@ -31,7 +31,7 @@ sjcl.bitArray = { /** * Array slices in units of bits. - * @param {bitArray a} The array to slice. + * @param {bitArray} a The array to slice. * @param {Number} bstart The offset to the start of the slice, in bits. * @param {Number} bend The offset to the end of the slice, in bits. If this is undefined, * slice until the end of the array. @@ -42,6 +42,27 @@ sjcl.bitArray = { return (bend === undefined) ? a : sjcl.bitArray.clamp(a, bend-bstart); }, + /** + * Extract a number packed into a bit array. + * @param {bitArray} a The array to slice. + * @param {Number} bstart The offset to the start of the slice, in bits. + * @param {Number} length The length of the number to extract. + * @return {Number} The requested slice. + */ + extract: function(a, bstart, blength) { + // FIXME: this Math.floor is not necessary at all, but for some reason + // seems to suppress a bug in the Chromium JIT. + var x, sh = Math.floor((-bstart-blength) & 31); + if ((bstart + blength - 1 ^ bstart) & -32) { + // it crosses a boundary + x = (a[bstart/32|0] << (32 - sh)) ^ (a[bstart/32+1|0] >>> sh); + } else { + // within a single word + x = a[bstart/32|0] >>> sh; + } + return x & ((1<= this.limbs.length) ? 0 : this.limbs[i]; + }, + + /** + * Constant time comparison function. + * Returns 1 if this >= that, or zero otherwise. + */ + greaterEquals: function(that) { + if (typeof that === "number") { that = new this._class(that); } + var less = 0, greater = 0, i, a, b; + i = Math.max(this.limbs.length, that.limbs.length) - 1; + for (; i>= 0; i--) { + a = this.getLimb(i); + b = that.getLimb(i); + greater |= (b - a) & ~less; + less |= (a - b) & ~greater; + } + return (greater | ~less) >>> 31; + }, + + /** + * Convert to a hex string. + */ + toString: function() { + this.fullReduce(); + var out="", i, s, l = this.limbs; + for (i=0; i < this.limbs.length; i++) { + s = l[i].toString(16); + while (i < this.limbs.length - 1 && s.length < 6) { + s = "0" + s; + } + out = s + out; + } + return "0x"+out; + }, + + /** this += that. Does not normalize. */ + addM: function(that) { + if (typeof(that) !== "object") { that = new this._class(that); } + var i, l=this.limbs, ll=that.limbs; + for (i=l.length; i> 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, l=this.limbs, ll=that.limbs; + for (i=l.length; i 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= 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), + b = this.limbs[this.limbs.length - 1]; + for (; b; b >>= 1) { + out ++; + } + return out+7 & -8; + } +}; + +sjcl.bn.fromBits = function(bits) { + var Class = this, out = new Class(), 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. + */ +sjcl.bn.pseudoMersennePrime = function(exponent, coeff) { + function p(it) { + this.initWith(it); + /*if (this.limbs[this.modOffset]) { + this.reduce(); + }*/ + } + + var ppr = p.prototype = new sjcl.bn(), i, tmp, mo; + mo = ppr.modOffset = Math.ceil(tmp = exponent / ppr.radix); + ppr.exponent = exponent; + ppr.offset = []; + ppr.factor = []; + ppr.minOffset = mo; + ppr.fullMask = 0; + ppr.fullOffset = []; + ppr.fullFactor = []; + ppr.modulus = p.modulus = new sjcl.bn(Math.pow(2,exponent)); + + ppr.fullMask = 0|-Math.pow(2, exponent % ppr.radix); + + for (i=0; i mo) { + l = limbs.pop(); + ll = limbs.length; + for (k=0; k> 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 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); + } + }; +}; diff --git a/core/convenience.js b/core/convenience.js index 2a7a3f25..d97f9dfb 100644 --- a/core/convenience.js +++ b/core/convenience.js @@ -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=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/core/ocb2.js b/core/ocb2.js index e4629ac5..388f4d1a 100644 --- a/core/ocb2.js +++ b/core/ocb2.js @@ -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); } diff --git a/core/random.js b/core/random.js index 2080cd32..a32eaa3a 100644 --- a/core/random.js +++ b/core/random.js @@ -47,7 +47,7 @@ sjcl.random = { var out = [], i, readiness = this.isReady(paranoia), g; if (readiness === this._NOT_READY) { - throw new sjcl.exception.notready("generator isn't seeded"); + throw new sjcl.exception.notReady("generator isn't seeded"); } else if (readiness & this._REQUIRES_RESEED) { this._reseedFromPools(!(readiness & this._READY)); } diff --git a/core/sjcl.js b/core/sjcl.js index 2cc50908..6f1337ee 100644 --- a/core/sjcl.js +++ b/core/sjcl.js @@ -58,6 +58,12 @@ var sjcl = { bug: function(message) { this.toString = function() { return "BUG: "+this.message; }; this.message = message; + }, + + /** @class Bug or missing feature in SJCL. */ + notReady: function(message) { + this.toString = function() { return "GENERATOR NOT READY: "+this.message; }; + this.message = message; } } }; diff --git a/sjcl.js b/sjcl.js index 57913d94..534cc0d6 100644 --- a/sjcl.js +++ b/sjcl.js @@ -1,43 +1,75 @@ -"use strict";var sjcl={cipher:{},hash:{},keyexchange:{},mode:{},misc:{},codec:{},exception:{corrupt:function(a){this.toString=function(){return"CORRUPT: "+this.message};this.message=a},invalid:function(a){this.toString=function(){return"INVALID: "+this.message};this.message=a},bug:function(a){this.toString=function(){return"BUG: "+this.message};this.message=a}}}; -sjcl.cipher.aes=function(a){this.j[0][0][0]||this.B();var b,c,d,e,f=this.j[0][4],g=this.j[1];b=a.length;var h=1;if(b!==4&&b!==6&&b!==8)throw new sjcl.exception.invalid("invalid aes key size");this.a=[d=a.slice(0),e=[]];for(a=b;a<4*b+28;a++){c=d[a-1];if(a%b===0||b===8&&a%b===4){c=f[c>>>24]<<24^f[c>>16&255]<<16^f[c>>8&255]<<8^f[c&255];if(a%b===0){c=c<<8^c>>>24^h<<24;h=h<<1^(h>>7)*283}}d[a]=d[a-b]^c}for(b=0;a;b++,a--){c=d[b&3?a:a-4];e[b]=a<=4||b<4?c:g[0][f[c>>>24]]^g[1][f[c>>16&255]]^g[2][f[c>>8&255]]^ +"use strict";var sjcl={cipher:{},hash:{},keyexchange:{},mode:{},misc:{},codec:{},exception:{corrupt:function(a){this.toString=function(){return"CORRUPT: "+this.message};this.message=a},invalid:function(a){this.toString=function(){return"INVALID: "+this.message};this.message=a},bug:function(a){this.toString=function(){return"BUG: "+this.message};this.message=a},notReady:function(a){this.toString=function(){return"GENERATOR NOT READY: "+this.message};this.message=a}}}; +sjcl.cipher.aes=function(a){this.o[0][0][0]||this.L();var b,c,d,e,f=this.o[0][4],g=this.o[1];b=a.length;var h=1;if(b!==4&&b!==6&&b!==8)throw new sjcl.exception.invalid("invalid aes key size");this.c=[d=a.slice(0),e=[]];for(a=b;a<4*b+28;a++){c=d[a-1];if(a%b===0||b===8&&a%b===4){c=f[c>>>24]<<24^f[c>>16&255]<<16^f[c>>8&255]<<8^f[c&255];if(a%b===0){c=c<<8^c>>>24^h<<24;h=h<<1^(h>>7)*283}}d[a]=d[a-b]^c}for(b=0;a;b++,a--){c=d[b&3?a:a-4];e[b]=a<=4||b<4?c:g[0][f[c>>>24]]^g[1][f[c>>16&255]]^g[2][f[c>>8&255]]^ g[3][f[c&255]]}}; -sjcl.cipher.aes.prototype={encrypt:function(a){return this.J(a,0)},decrypt:function(a){return this.J(a,1)},j:[[[],[],[],[],[]],[[],[],[],[],[]]],B:function(){var a=this.j[0],b=this.j[1],c=a[4],d=b[4],e,f,g,h=[],i=[],k,j,l,m;for(e=0;e<0x100;e++)i[(h[e]=e<<1^(e>>7)*283)^e]=e;for(f=g=0;!c[f];f^=k||1,g=i[g]||1){l=g^g<<1^g<<2^g<<3^g<<4;l=l>>8^l&255^99;c[f]=l;d[l]=f;j=h[e=h[k=h[f]]];m=j*0x1010101^e*0x10001^k*0x101^f*0x1010100;j=h[l]*0x101^l*0x1010100;for(e=0;e<4;e++){a[e][f]=j=j<<24^j>>>8;b[e][l]=m=m<<24^m>>>8}}for(e= -0;e<5;e++){a[e]=a[e].slice(0);b[e]=b[e].slice(0)}},J:function(a,b){if(a.length!==4)throw new sjcl.exception.invalid("invalid aes block size");var c=this.a[b],d=a[0]^c[0],e=a[b?3:1]^c[1],f=a[2]^c[2];a=a[b?1:3]^c[3];var g,h,i,k=c.length/4-2,j,l=4,m=[0,0,0,0];g=this.j[b];var n=g[0],o=g[1],p=g[2],q=g[3],r=g[4];for(j=0;j>>24]^o[e>>16&255]^p[f>>8&255]^q[a&255]^c[l];h=n[e>>>24]^o[f>>16&255]^p[a>>8&255]^q[d&255]^c[l+1];i=n[f>>>24]^o[a>>16&255]^p[d>>8&255]^q[e&255]^c[l+2];a=n[a>>>24]^o[d>>16& -255]^p[e>>8&255]^q[f&255]^c[l+3];l+=4;d=g;e=h;f=i}for(j=0;j<4;j++){m[b?3&-j:j]=r[d>>>24]<<24^r[e>>16&255]<<16^r[f>>8&255]<<8^r[a&255]^c[l++];g=d;d=e;e=f;f=a;a=g}return m}}; -sjcl.bitArray={bitSlice:function(a,b,c){a=sjcl.bitArray.Q(a.slice(b/32),32-(b&31)).slice(1);return c===undefined?a:sjcl.bitArray.clamp(a,c-b)},concat:function(a,b){if(a.length===0||b.length===0)return a.concat(b);var c=a[a.length-1],d=sjcl.bitArray.getPartial(c);return d===32?a.concat(b):sjcl.bitArray.Q(b,d,c|0,a.slice(0,a.length-1))},bitLength:function(a){var b=a.length;if(b===0)return 0;return(b-1)*32+sjcl.bitArray.getPartial(a[b-1])},clamp:function(a,b){if(a.length*320&&b)a[c-1]=sjcl.bitArray.partial(b,a[c-1]&2147483648>>b-1,1);return a},partial:function(a,b,c){if(a===32)return b;return(c?b|0:b<<32-a)+a*0x10000000000},getPartial:function(a){return Math.round(a/0x10000000000)||32},equal:function(a,b){if(sjcl.bitArray.bitLength(a)!==sjcl.bitArray.bitLength(b))return false;var c=0,d;for(d=0;d=32;b-=32){d.push(c);c=0}if(b===0)return d.concat(a); -for(e=0;e>>b);c=a[e]<<32-b}e=a.length?a[a.length-1]:0;a=sjcl.bitArray.getPartial(e);d.push(sjcl.bitArray.partial(b+a&31,b+a>32?c:d.pop(),1));return d},m:function(a,b){return[a[0]^b[0],a[1]^b[1],a[2]^b[2],a[3]^b[3]]}}; +sjcl.cipher.aes.prototype={encrypt:function(a){return this.S(a,0)},decrypt:function(a){return this.S(a,1)},o:[[[],[],[],[],[]],[[],[],[],[],[]]],L:function(){var a=this.o[0],b=this.o[1],c=a[4],d=b[4],e,f,g,h=[],i=[],j,k,l,m;for(e=0;e<0x100;e++)i[(h[e]=e<<1^(e>>7)*283)^e]=e;for(f=g=0;!c[f];f^=j||1,g=i[g]||1){l=g^g<<1^g<<2^g<<3^g<<4;l=l>>8^l&255^99;c[f]=l;d[l]=f;k=h[e=h[j=h[f]]];m=k*0x1010101^e*0x10001^j*0x101^f*0x1010100;k=h[l]*0x101^l*0x1010100;for(e=0;e<4;e++){a[e][f]=k=k<<24^k>>>8;b[e][l]=m=m<<24^m>>>8}}for(e= +0;e<5;e++){a[e]=a[e].slice(0);b[e]=b[e].slice(0)}},S:function(a,b){if(a.length!==4)throw new sjcl.exception.invalid("invalid aes block size");var c=this.c[b],d=a[0]^c[0],e=a[b?3:1]^c[1],f=a[2]^c[2];a=a[b?1:3]^c[3];var g,h,i,j=c.length/4-2,k,l=4,m=[0,0,0,0];g=this.o[b];var n=g[0],o=g[1],p=g[2],q=g[3],r=g[4];for(k=0;k>>24]^o[e>>16&255]^p[f>>8&255]^q[a&255]^c[l];h=n[e>>>24]^o[f>>16&255]^p[a>>8&255]^q[d&255]^c[l+1];i=n[f>>>24]^o[a>>16&255]^p[d>>8&255]^q[e&255]^c[l+2];a=n[a>>>24]^o[d>>16& +255]^p[e>>8&255]^q[f&255]^c[l+3];l+=4;d=g;e=h;f=i}for(k=0;k<4;k++){m[b?3&-k:k]=r[d>>>24]<<24^r[e>>16&255]<<16^r[f>>8&255]<<8^r[a&255]^c[l++];g=d;d=e;e=f;f=a;a=g}return m}}; +sjcl.bitArray={bitSlice:function(a,b,c){a=sjcl.bitArray.aa(a.slice(b/32),32-(b&31)).slice(1);return c===undefined?a:sjcl.bitArray.clamp(a,c-b)},extract:function(a,b,c){var d=Math.floor(-b-c&31);return((b+c-1^b)&-32?a[b/32|0]<<32-d^a[b/32+1|0]>>>d:a[b/32|0]>>>d)&(1<0&&b)a[c-1]=sjcl.bitArray.partial(b,a[c-1]&2147483648>>b-1,1);return a},partial:function(a,b,c){if(a===32)return b;return(c?b|0:b<<32-a)+a*0x10000000000},getPartial:function(a){return Math.round(a/0x10000000000)||32},equal:function(a,b){if(sjcl.bitArray.bitLength(a)!==sjcl.bitArray.bitLength(b))return false;var c=0,d;for(d=0;d=32;b-=32){d.push(c);c=0}if(b===0)return d.concat(a);for(e=0;e>>b);c=a[e]<<32-b}e=a.length?a[a.length-1]:0;a=sjcl.bitArray.getPartial(e);d.push(sjcl.bitArray.partial(b+a&31,b+a>32?c:d.pop(),1));return d},l:function(a,b){return[a[0]^b[0],a[1]^b[1],a[2]^b[2],a[3]^b[3]]}}; sjcl.codec.utf8String={fromBits:function(a){var b="",c=sjcl.bitArray.bitLength(a),d,e;for(d=0;d>>24);e<<=8}return decodeURIComponent(escape(b))},toBits:function(a){a=unescape(encodeURIComponent(a));var b=[],c,d=0;for(c=0;c>>e)>>>26);if(e<6){g=a[d]<<6-e;e+=26;d++}else{g<<=6;e-=6}}for(;c.length&3&&!b;)c+="=";return c},toBits:function(a){a=a.replace(/\s|=/g,"");var b=[],c,d=0,e=sjcl.codec.base64.G,f=0,g;for(c=0;c26){d-=26;b.push(f^g>>>d);f=g<<32-d}else{d+=6;f^=g<<32-d}}d&56&&b.push(sjcl.bitArray.partial(d&56,f,1));return b}};sjcl.hash.sha1=function(a){if(a){this.d=a.d.slice(0);this.c=a.c.slice(0);this.b=a.b}else this.reset()};sjcl.hash.sha1.hash=function(a){return(new sjcl.hash.sha1).update(a).finalize()}; -sjcl.hash.sha1.prototype={blockSize:512,reset:function(){this.d=this.p.slice(0);this.c=[];this.b=0;return this},update:function(a){if(typeof a==="string")a=sjcl.codec.utf8String.toBits(a);var b,c=this.c=sjcl.bitArray.concat(this.c,a);b=this.b;a=this.b=b+sjcl.bitArray.bitLength(a);for(b=this.blockSize+b&-this.blockSize;b<=a;b+=this.blockSize)this.k(c.splice(0,16));return this},finalize:function(){var a,b=this.c,c=this.d;b=sjcl.bitArray.concat(b,[sjcl.bitArray.partial(1,1)]);for(a=b.length+2;a&15;a++)b.push(0); -b.push(Math.floor(this.b/0x100000000));for(b.push(this.b|0);b.length;)this.k(b.splice(0,16));this.reset();return c},p:[1732584193,4023233417,2562383102,271733878,3285377520],a:[1518500249,1859775393,2400959708,3395469782],T:function(a,b,c,d){if(a<=19)return b&c|~b&d;else if(a<=39)return b^c^d;else if(a<=59)return b&c|b&d|c&d;else if(a<=79)return b^c^d},t:function(a,b){return b<>>32-a},k:function(a){var b,c,d,e,f,g,h=a.slice(0),i=this.d;c=i[0];d=i[1];e=i[2];f=i[3];g=i[4];for(a=0;a<=79;a++){if(a>= -16)h[a]=this.t(1,h[a-3]^h[a-8]^h[a-14]^h[a-16]);b=this.t(5,c)+this.T(a,d,e,f)+g+h[a]+this.a[Math.floor(a/20)]|0;g=f;f=e;e=this.t(30,d);d=c;c=b}i[0]=i[0]+c|0;i[1]=i[1]+d|0;i[2]=i[2]+e|0;i[3]=i[3]+f|0;i[4]=i[4]+g|0}};sjcl.hash.sha256=function(a){this.a[0]||this.B();if(a){this.d=a.d.slice(0);this.c=a.c.slice(0);this.b=a.b}else this.reset()};sjcl.hash.sha256.hash=function(a){return(new sjcl.hash.sha256).update(a).finalize()}; -sjcl.hash.sha256.prototype={blockSize:512,reset:function(){this.d=this.p.slice(0);this.c=[];this.b=0;return this},update:function(a){if(typeof a==="string")a=sjcl.codec.utf8String.toBits(a);var b,c=this.c=sjcl.bitArray.concat(this.c,a);b=this.b;a=this.b=b+sjcl.bitArray.bitLength(a);for(b=512+b&-512;b<=a;b+=512)this.k(c.splice(0,16));return this},finalize:function(){var a,b=this.c,c=this.d;b=sjcl.bitArray.concat(b,[sjcl.bitArray.partial(1,1)]);for(a=b.length+2;a&15;a++)b.push(0);b.push(Math.floor(this.b/ -4294967296));for(b.push(this.b|0);b.length;)this.k(b.splice(0,16));this.reset();return c},p:[],a:[],B:function(){function a(e){return(e-Math.floor(e))*0x100000000|0}var b=0,c=2,d;a:for(;b<64;c++){for(d=2;d*d<=c;d++)if(c%d===0)continue a;if(b<8)this.p[b]=a(Math.pow(c,0.5));this.a[b]=a(Math.pow(c,1/3));b++}},k:function(a){var b,c,d=a.slice(0),e=this.d,f=this.a,g=e[0],h=e[1],i=e[2],k=e[3],j=e[4],l=e[5],m=e[6],n=e[7];for(a=0;a<64;a++){if(a<16)b=d[a];else{b=d[a+1&15];c=d[a+14&15];b=d[a&15]=(b>>>7^b>>>18^ -b>>>3^b<<25^b<<14)+(c>>>17^c>>>19^c>>>10^c<<15^c<<13)+d[a&15]+d[a+9&15]|0}b=b+n+(j>>>6^j>>>11^j>>>25^j<<26^j<<21^j<<7)+(m^j&(l^m))+f[a];n=m;m=l;l=j;j=k+b|0;k=i;i=h;h=g;g=b+(h&i^k&(h^i))+(h>>>2^h>>>13^h>>>22^h<<30^h<<19^h<<10)|0}e[0]=e[0]+g|0;e[1]=e[1]+h|0;e[2]=e[2]+i|0;e[3]=e[3]+k|0;e[4]=e[4]+j|0;e[5]=e[5]+l|0;e[6]=e[6]+m|0;e[7]=e[7]+n|0}}; -sjcl.mode.ccm={name:"ccm",encrypt:function(a,b,c,d,e){var f,g=b.slice(0),h=sjcl.bitArray,i=h.bitLength(c)/8,k=h.bitLength(g)/8;e=e||64;d=d||[];if(i<7)throw new sjcl.exception.invalid("ccm: iv must be at least 7 bytes");for(f=2;f<4&&k>>>8*f;f++);if(f<15-i)f=15-i;c=h.clamp(c,8*(15-f));b=sjcl.mode.ccm.I(a,b,c,d,e,f);g=sjcl.mode.ccm.K(a,g,c,b,e,f);return h.concat(g.data,g.tag)},decrypt:function(a,b,c,d,e){e=e||64;d=d||[];var f=sjcl.bitArray,g=f.bitLength(c)/8,h=f.bitLength(b),i=f.clamp(b,h-e),k=f.bitSlice(b, -h-e);h=(h-e)/8;if(g<7)throw new sjcl.exception.invalid("ccm: iv must be at least 7 bytes");for(b=2;b<4&&h>>>8*b;b++);if(b<15-g)b=15-g;c=f.clamp(c,8*(15-b));i=sjcl.mode.ccm.K(a,i,c,k,e,b);a=sjcl.mode.ccm.I(a,i.data,c,d,e,b);if(!f.equal(i.tag,a))throw new sjcl.exception.corrupt("ccm: tag doesn't match");return i.data},I:function(a,b,c,d,e,f){var g=[],h=sjcl.bitArray,i=h.m;e/=8;if(e%2||e<4||e>16)throw new sjcl.exception.invalid("ccm: invalid tag length");if(d.length>0xffffffff||b.length>0xffffffff)throw new sjcl.exception.bug("ccm: can't deal with 4GiB or more data"); -f=[h.partial(8,(d.length?64:0)|e-2<<2|f-1)];f=h.concat(f,c);f[3]|=h.bitLength(b)/8;f=a.encrypt(f);if(d.length){c=h.bitLength(d)/8;if(c<=65279)g=[h.partial(16,c)];else if(c<=0xffffffff)g=h.concat([h.partial(16,65534)],[c]);g=h.concat(g,d);for(d=0;d>>31,a[1]<<1^a[2]>>>31,a[2]<<1^a[3]>>>31,a[3]<<1^(a[0]>>>31)*135]}};sjcl.misc.hmac=function(a,b){this.O=b=b||sjcl.hash.sha256;var c=[[],[]],d=b.prototype.blockSize/32;this.n=[new b,new b];if(a.length>d)a=b.hash(a);for(b=0;b0;){b++;e>>>=1}this.e[g].update([d,this.L++,2,b,f,a.length].concat(a));break;case "string":if(b===undefined)b=a.length;this.e[g].update([d,this.L++,3,b,f,a.length]);this.e[g].update(a);break;default:throw new sjcl.exception.bug("random: addEntropy only supports number, array or string");}this.l[g]+=b;this.h+=b;if(h===0){this.isReady()!==0&&this.M("seeded",Math.max(this.i, -this.h));this.M("progress",this.getProgress())}},isReady:function(a){a=this.F[a!==undefined?a:this.z];return this.i&&this.i>=a?this.l[0]>80&&(new Date).valueOf()>this.P?3:1:this.h>=a?2:0},getProgress:function(a){a=this.F[a?a:this.z];return this.i>=a?1["0"]:this.h>a?1["0"]:this.h/a},startCollectors:function(){if(!this.o){if(window.addEventListener){window.addEventListener("load",this.q,false);window.addEventListener("mousemove",this.r,false)}else if(document.attachEvent){document.attachEvent("onload", -this.q);document.attachEvent("onmousemove",this.r)}else throw new sjcl.exception.bug("can't attach event");this.o=true}},stopCollectors:function(){if(this.o){if(window.removeEventListener){window.removeEventListener("load",this.q);window.removeEventListener("mousemove",this.r)}else if(window.detachEvent){window.detachEvent("onload",this.q);window.detachEvent("onmousemove",this.r)}this.o=false}},addEventListener:function(a,b){this.u[a][this.R++]=b},removeEventListener:function(a,b){var c;a=this.u[a]; -var d=[];for(c in a)a.hasOwnProperty(c)&&a[c]===b&&d.push(c);for(b=0;b=1<this.i)this.i=c;this.C++;this.V(b)},r:function(a){sjcl.random.addEntropy([a.x|| -a.clientX||a.offsetX,a.y||a.clientY||a.offsetY],2,"mouse")},q:function(){sjcl.random.addEntropy(new Date,2,"loadtime")},M:function(a,b){var c;a=sjcl.random.u[a];var d=[];for(c in a)a.hasOwnProperty(c)&&d.push(a[c]);for(c=0;c -4)throw new sjcl.exception.invalid("json encrypt: invalid parameters");if(typeof a==="string"){c=sjcl.misc.cachedPbkdf2(a,f);a=c.key.slice(0,f.ks/32);f.salt=c.salt}if(typeof b==="string")b=sjcl.codec.utf8String.toBits(b);c=new sjcl.cipher[f.cipher](a);e.f(d,f);d.key=a;f.ct=sjcl.mode[f.mode].encrypt(c,b,f.iv,f.adata,f.tag);return e.encode(e.X(f,e.defaults))},decrypt:function(a,b,c,d){c=c||{};d=d||{};var e=sjcl.json;b=e.f(e.f(e.f({},e.defaults),e.decode(b)),c,true);if(typeof b.salt==="string")b.salt= -sjcl.codec.base64.toBits(b.salt);if(typeof b.iv==="string")b.iv=sjcl.codec.base64.toBits(b.iv);if(!sjcl.mode[b.mode]||!sjcl.cipher[b.cipher]||typeof a==="string"&&b.iter<=100||b.ts!==64&&b.ts!==96&&b.ts!==128||b.ks!==128&&b.ks!==192&&b.ks!==0x100||!b.iv||b.iv.length<2||b.iv.length>4)throw new sjcl.exception.invalid("json decrypt: invalid parameters");if(typeof a==="string"){c=sjcl.misc.cachedPbkdf2(a,b);a=c.key.slice(0,b.ks/32);b.salt=c.salt}c=new sjcl.cipher[b.cipher](a);c=sjcl.mode[b.mode].decrypt(c, -b.ct,b.iv,b.adata,b.tag);e.f(d,b);d.key=a;return sjcl.codec.utf8String.fromBits(c)},encode:function(a){var b,c="{",d="";for(b in a)if(a.hasOwnProperty(b)){if(!b.match(/^[a-z0-9]+$/i))throw new sjcl.exception.invalid("json encode: invalid property name");c+=d+b+":";d=",";switch(typeof a[b]){case "number":case "boolean":c+=a[b];break;case "string":c+='"'+escape(a[b])+'"';break;case "object":c+='"'+sjcl.codec.base64.fromBits(a[b],1)+'"';break;default:throw new sjcl.exception.bug("json encode: unsupported type"); -}}return c+"}"},decode:function(a){a=a.replace(/\s/g,"");if(!a.match(/^\{.*\}$/))throw new sjcl.exception.invalid("json decode: this isn't json!");a=a.replace(/^\{|\}$/g,"").split(/,/);var b={},c,d;for(c=0;c>>e)>>>26);if(e<6){g=a[d]<<6-e;e+=26;d++}else{g<<=6;e-=6}}for(;c.length&3&&!b;)c+="=";return c},toBits:function(a){a=a.replace(/\s|=/g,"");var b=[],c,d=0,e=sjcl.codec.base64.P,f=0,g;for(c=0;c26){d-=26;b.push(f^g>>>d);f=g<<32-d}else{d+=6;f^=g<<32-d}}d&56&&b.push(sjcl.bitArray.partial(d&56,f,1));return b}};sjcl.hash.sha1=function(a){if(a){this.g=a.g.slice(0);this.e=a.e.slice(0);this.d=a.d}else this.reset()};sjcl.hash.sha1.hash=function(a){return(new sjcl.hash.sha1).update(a).finalize()}; +sjcl.hash.sha1.prototype={blockSize:512,reset:function(){this.g=this.u.slice(0);this.e=[];this.d=0;return this},update:function(a){if(typeof a==="string")a=sjcl.codec.utf8String.toBits(a);var b,c=this.e=sjcl.bitArray.concat(this.e,a);b=this.d;a=this.d=b+sjcl.bitArray.bitLength(a);for(b=this.blockSize+b&-this.blockSize;b<=a;b+=this.blockSize)this.p(c.splice(0,16));return this},finalize:function(){var a,b=this.e,c=this.g;b=sjcl.bitArray.concat(b,[sjcl.bitArray.partial(1,1)]);for(a=b.length+2;a&15;a++)b.push(0); +b.push(Math.floor(this.d/0x100000000));for(b.push(this.d|0);b.length;)this.p(b.splice(0,16));this.reset();return c},u:[1732584193,4023233417,2562383102,271733878,3285377520],c:[1518500249,1859775393,2400959708,3395469782],ea:function(a,b,c,d){if(a<=19)return b&c|~b&d;else if(a<=39)return b^c^d;else if(a<=59)return b&c|b&d|c&d;else if(a<=79)return b^c^d},C:function(a,b){return b<>>32-a},p:function(a){var b,c,d,e,f,g,h=a.slice(0),i=this.g;c=i[0];d=i[1];e=i[2];f=i[3];g=i[4];for(a=0;a<=79;a++){if(a>= +16)h[a]=this.C(1,h[a-3]^h[a-8]^h[a-14]^h[a-16]);b=this.C(5,c)+this.ea(a,d,e,f)+g+h[a]+this.c[Math.floor(a/20)]|0;g=f;f=e;e=this.C(30,d);d=c;c=b}i[0]=i[0]+c|0;i[1]=i[1]+d|0;i[2]=i[2]+e|0;i[3]=i[3]+f|0;i[4]=i[4]+g|0}};sjcl.hash.sha256=function(a){this.c[0]||this.L();if(a){this.g=a.g.slice(0);this.e=a.e.slice(0);this.d=a.d}else this.reset()};sjcl.hash.sha256.hash=function(a){return(new sjcl.hash.sha256).update(a).finalize()}; +sjcl.hash.sha256.prototype={blockSize:512,reset:function(){this.g=this.u.slice(0);this.e=[];this.d=0;return this},update:function(a){if(typeof a==="string")a=sjcl.codec.utf8String.toBits(a);var b,c=this.e=sjcl.bitArray.concat(this.e,a);b=this.d;a=this.d=b+sjcl.bitArray.bitLength(a);for(b=512+b&-512;b<=a;b+=512)this.p(c.splice(0,16));return this},finalize:function(){var a,b=this.e,c=this.g;b=sjcl.bitArray.concat(b,[sjcl.bitArray.partial(1,1)]);for(a=b.length+2;a&15;a++)b.push(0);b.push(Math.floor(this.d/ +4294967296));for(b.push(this.d|0);b.length;)this.p(b.splice(0,16));this.reset();return c},u:[],c:[],L:function(){function a(e){return(e-Math.floor(e))*0x100000000|0}var b=0,c=2,d;a:for(;b<64;c++){for(d=2;d*d<=c;d++)if(c%d===0)continue a;if(b<8)this.u[b]=a(Math.pow(c,0.5));this.c[b]=a(Math.pow(c,1/3));b++}},p:function(a){var b,c,d=a.slice(0),e=this.g,f=this.c,g=e[0],h=e[1],i=e[2],j=e[3],k=e[4],l=e[5],m=e[6],n=e[7];for(a=0;a<64;a++){if(a<16)b=d[a];else{b=d[a+1&15];c=d[a+14&15];b=d[a&15]=(b>>>7^b>>>18^ +b>>>3^b<<25^b<<14)+(c>>>17^c>>>19^c>>>10^c<<15^c<<13)+d[a&15]+d[a+9&15]|0}b=b+n+(k>>>6^k>>>11^k>>>25^k<<26^k<<21^k<<7)+(m^k&(l^m))+f[a];n=m;m=l;l=k;k=j+b|0;j=i;i=h;h=g;g=b+(h&i^j&(h^i))+(h>>>2^h>>>13^h>>>22^h<<30^h<<19^h<<10)|0}e[0]=e[0]+g|0;e[1]=e[1]+h|0;e[2]=e[2]+i|0;e[3]=e[3]+j|0;e[4]=e[4]+k|0;e[5]=e[5]+l|0;e[6]=e[6]+m|0;e[7]=e[7]+n|0}}; +sjcl.mode.ccm={name:"ccm",encrypt:function(a,b,c,d,e){var f,g=b.slice(0),h=sjcl.bitArray,i=h.bitLength(c)/8,j=h.bitLength(g)/8;e=e||64;d=d||[];if(i<7)throw new sjcl.exception.invalid("ccm: iv must be at least 7 bytes");for(f=2;f<4&&j>>>8*f;f++);if(f<15-i)f=15-i;c=h.clamp(c,8*(15-f));b=sjcl.mode.ccm.R(a,b,c,d,e,f);g=sjcl.mode.ccm.T(a,g,c,b,e,f);return h.concat(g.data,g.tag)},decrypt:function(a,b,c,d,e){e=e||64;d=d||[];var f=sjcl.bitArray,g=f.bitLength(c)/8,h=f.bitLength(b),i=f.clamp(b,h-e),j=f.bitSlice(b, +h-e);h=(h-e)/8;if(g<7)throw new sjcl.exception.invalid("ccm: iv must be at least 7 bytes");for(b=2;b<4&&h>>>8*b;b++);if(b<15-g)b=15-g;c=f.clamp(c,8*(15-b));i=sjcl.mode.ccm.T(a,i,c,j,e,b);a=sjcl.mode.ccm.R(a,i.data,c,d,e,b);if(!f.equal(i.tag,a))throw new sjcl.exception.corrupt("ccm: tag doesn't match");return i.data},R:function(a,b,c,d,e,f){var g=[],h=sjcl.bitArray,i=h.l;e/=8;if(e%2||e<4||e>16)throw new sjcl.exception.invalid("ccm: invalid tag length");if(d.length>0xffffffff||b.length>0xffffffff)throw new sjcl.exception.bug("ccm: can't deal with 4GiB or more data"); +f=[h.partial(8,(d.length?64:0)|e-2<<2|f-1)];f=h.concat(f,c);f[3]|=h.bitLength(b)/8;f=a.encrypt(f);if(d.length){c=h.bitLength(d)/8;if(c<=65279)g=[h.partial(16,c)];else if(c<=0xffffffff)g=h.concat([h.partial(16,65534)],[c]);g=h.concat(g,d);for(d=0;d>3&15))*0x1010101;c=a.encrypt(f(c,e.concat(b,[g,g,g,g]).slice(d,d+4)));i.splice(d,0,c[0],c[1],c[2],c[3]);return i},decrypt:function(a,b,c,d){if(d&&d.length)throw new sjcl.exception.invalid("cbc can't authenticate data");if(sjcl.bitArray.bitLength(c)!==128)throw new sjcl.exception.invalid("cbc iv must be 128 bits");if(sjcl.bitArray.bitLength(b)&127||!b.length)throw new sjcl.exception.corrupt("cbc ciphertext must be a positive multiple of the block size"); +var e=sjcl.bitArray,f=e.l,g,h=[];for(d=0;d16)throw new sjcl.exception.corrupt("pkcs#5 padding corrupt");c=g*0x1010101;if(!e.equal(e.bitSlice([c,c,c,c],0,g*8),e.bitSlice(h,h.length*32-g*8,h.length*32)))throw new sjcl.exception.corrupt("pkcs#5 padding corrupt");return e.bitSlice(h,0,h.length*32-g*8)}}}; +sjcl.mode.ocb2={name:"ocb2",encrypt:function(a,b,c,d,e,f){if(sjcl.bitArray.bitLength(c)!==128)throw new sjcl.exception.invalid("ocb iv must be 128 bits");var g,h=sjcl.mode.ocb2.N,i=sjcl.bitArray,j=i.l,k=[0,0,0,0];c=h(a.encrypt(c));var l,m=[];d=d||[];e=e||64;for(g=0;g+4>>31,a[1]<<1^a[2]>>>31,a[2]<<1^a[3]>>>31,a[3]<<1^(a[0]>>>31)*135]}};sjcl.misc.hmac=function(a,b){this.Y=b=b||sjcl.hash.sha256;var c=[[],[]],d=b.prototype.blockSize/32;this.s=[new b,new b];if(a.length>d)a=b.hash(a);for(b=0;b0;){b++;e>>>=1}this.i[g].update([d,this.V++,2,b,f,a.length].concat(a));break;case "string":if(b===undefined)b=a.length;this.i[g].update([d,this.V++,3,b,f,a.length]);this.i[g].update(a);break;default:throw new sjcl.exception.bug("random: addEntropy only supports number, array or string");}this.q[g]+=b;this.m+=b;if(h===0){this.isReady()!==0&&this.W("seeded", +Math.max(this.n,this.m));this.W("progress",this.getProgress())}},isReady:function(a){a=this.O[a!==undefined?a:this.H];return this.n&&this.n>=a?this.q[0]>80&&(new Date).valueOf()>this.$?3:1:this.m>=a?2:0},getProgress:function(a){a=this.O[a?a:this.H];return this.n>=a?1["0"]:this.m>a?1["0"]:this.m/a},startCollectors:function(){if(!this.t){if(window.addEventListener){window.addEventListener("load",this.w,false);window.addEventListener("mousemove",this.A,false)}else if(document.attachEvent){document.attachEvent("onload", +this.w);document.attachEvent("onmousemove",this.A)}else throw new sjcl.exception.bug("can't attach event");this.t=true}},stopCollectors:function(){if(this.t){if(window.removeEventListener){window.removeEventListener("load",this.w);window.removeEventListener("mousemove",this.A)}else if(window.detachEvent){window.detachEvent("onload",this.w);window.detachEvent("onmousemove",this.A)}this.t=false}},addEventListener:function(a,b){this.D[a][this.ca++]=b},removeEventListener:function(a,b){var c;a=this.D[a]; +var d=[];for(c in a)a.hasOwnProperty(c)&&a[c]===b&&d.push(c);for(b=0;b=1<this.n)this.n=c;this.M++;this.ga(b)},A:function(a){sjcl.random.addEntropy([a.x|| +a.clientX||a.offsetX,a.y||a.clientY||a.offsetY],2,"mouse")},w:function(){sjcl.random.addEntropy(new Date,2,"loadtime")},W:function(a,b){var c;a=sjcl.random.D[a];var d=[];for(c in a)a.hasOwnProperty(c)&&d.push(a[c]);for(c=0;c +4)throw new sjcl.exception.invalid("json encrypt: invalid parameters");if(typeof a==="string"){c=sjcl.misc.cachedPbkdf2(a,f);a=c.key.slice(0,f.ks/32);f.salt=c.salt}if(typeof b==="string")b=sjcl.codec.utf8String.toBits(b);c=new sjcl.cipher[f.cipher](a);e.j(d,f);d.key=a;f.ct=sjcl.mode[f.mode].encrypt(c,b,f.iv,f.adata,f.tag);return e.encode(f)},decrypt:function(a,b,c,d){c=c||{};d=d||{};var e=sjcl.json;b=e.j(e.j(e.j({},e.defaults),e.decode(b)),c,true);if(typeof b.salt==="string")b.salt=sjcl.codec.base64.toBits(b.salt); +if(typeof b.iv==="string")b.iv=sjcl.codec.base64.toBits(b.iv);if(!sjcl.mode[b.mode]||!sjcl.cipher[b.cipher]||typeof a==="string"&&b.iter<=100||b.ts!==64&&b.ts!==96&&b.ts!==128||b.ks!==128&&b.ks!==192&&b.ks!==0x100||!b.iv||b.iv.length<2||b.iv.length>4)throw new sjcl.exception.invalid("json decrypt: invalid parameters");if(typeof a==="string"){c=sjcl.misc.cachedPbkdf2(a,b);a=c.key.slice(0,b.ks/32);b.salt=c.salt}c=new sjcl.cipher[b.cipher](a);c=sjcl.mode[b.mode].decrypt(c,b.ct,b.iv,b.adata,b.tag);e.j(d, +b);d.key=a;return sjcl.codec.utf8String.fromBits(c)},encode:function(a){var b,c="{",d="";for(b in a)if(a.hasOwnProperty(b)){if(!b.match(/^[a-z0-9]+$/i))throw new sjcl.exception.invalid("json encode: invalid property name");c+=d+'"'+b+'":';d=",";switch(typeof a[b]){case "number":case "boolean":c+=a[b];break;case "string":c+='"'+escape(a[b])+'"';break;case "object":c+='"'+sjcl.codec.base64.fromBits(a[b],1)+'"';break;default:throw new sjcl.exception.bug("json encode: unsupported type");}}return c+"}"}, +decode:function(a){a=a.replace(/\s/g,"");if(!a.match(/^\{.*\}$/))throw new sjcl.exception.invalid("json decode: this isn't json!");a=a.replace(/^\{|\}$/g,"").split(/,/);var b={},c,d;for(c=0;c=this.limbs.length?0:this.limbs[a]},greaterEquals:function(a){if(typeof a==="number")a=new this.f(a);var b=0,c=0,d,e,f;for(d=Math.max(this.limbs.length,a.limbs.length)-1;d>=0;d--){e=this.getLimb(d);f=a.getLimb(d);c|=f-e&~b;b|=e-f&~c}return(c|~b)>>>31},toString:function(){this.fullReduce();var a="",b,c,d=this.limbs;for(b=0;b>d}b&&f.push(b);return this},halveM:function(){var a,b=0,c,d=this.radix,e=this.limbs;for(a=e.length-1;a>=0;a--){c=e[a];e[a]=c+b>> +1;b=(c&1)<0;c--){a.halveM();b.greaterEquals(a)&&b.subM(a).normalize()}return b.trim()},inverseMod:function(a){var b=new sjcl.bn(1),c=new sjcl.bn(0),d=new sjcl.bn(this), +e=new sjcl.bn(a),f,g=1;if(!(a.limbs[0]&1))throw new sjcl.exception.invalid("inverseMod: p must be odd");do{if(d.limbs[0]&1){if(!d.greaterEquals(e)){f=d;d=e;e=f;f=b;b=c;c=f}d.subM(e);d.normalize();b.greaterEquals(c)||b.addM(a);b.subM(c)}d.halveM();b.limbs[0]&1&&b.addM(a);b.normalize();b.halveM();for(f=g=0;f=0;b--)a=c.concat(a,[c.partial(this.radix,this.getLimb(b))]);return a},bitLength:function(){this.fullReduce();for(var a=this.radix*(this.limbs.length-1),b=this.limbs[this.limbs.length- +1];b;b>>=1)a++;return a+7&-8}};sjcl.bn.fromBits=function(a){var b=new this,c=[],d=sjcl.bitArray,e=this.prototype,f=Math.min(this.bitLength||0x100000000,d.bitLength(a)),g=f%e.radix||e.radix;for(c[0]=d.extract(a,0,g);gj;){i=k.pop();o=k.length;for(h=0;h=0;b--)for(c=sjcl.bn.prototype.radix-4;c>=0;c-=4)d=d.doubl().doubl().doubl().doubl().add(e[a[b]>>c&15]);return d},mult2:function(a,b,c,d){if(typeof a==="number")a=[a];else if(a.limbs!== +undefined)a=a.normalize().limbs;if(typeof c==="number")c=[c];else if(c.limbs!==undefined)c=c.normalize().limbs;var e,f=(new sjcl.ecc.point(this.curve)).toJac();b=b.multiples();var g=d.multiples(),h,i;for(d=Math.max(a.length,c.length)-1;d>=0;d--){h=a[d]|0;i=c[d]|0;for(e=sjcl.bn.prototype.radix-4;e>=0;e-=4)f=f.doubl().doubl().doubl().doubl().add(b[h>>e&15]).add(g[i>>e&15])}return f},isValid:function(){var a=this.z.square(),b=a.square();a=b.mul(a);return this.y.square().equals(this.curve.b.mul(a).add(this.x.mul(this.curve.a.mul(b).add(this.x.square()))))}}; +sjcl.ecc.curve=function(a,b,c,d,e,f){this.field=a;this.r=a.prototype.modulus.sub(b);this.a=new a(c);this.b=new a(d);this.G=new sjcl.ecc.point(this,new a(e),new a(f))};sjcl.ecc.curve.prototype.fromBits=function(a){var b=sjcl.bitArray,c=this.field.prototype.exponent+7&-8;a=new sjcl.ecc.point(this,this.field.fromBits(b.bitSlice(a,0,c)),this.field.fromBits(b.bitSlice(a,c,2*c)));if(!a.isValid())throw new sjcl.exception.corrupt("not on the curve!");return a}; +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")}; +sjcl.ecc.U=function(a){sjcl.ecc[a]={publicKey:function(b,c){this.h=b;this.K=c instanceof Array?b.fromBits(c):c},secretKey:function(b,c){this.h=b;this.I=c},generateKeys:function(b,c){if(b===undefined)b=0x100;if(typeof b==="number"){b=sjcl.ecc.curves["c"+b];if(b===undefined)throw new sjcl.exception.invalid("no such curve");}c=sjcl.bn.random(b.r,c);var d=b.G.mult(c);return{pub:new sjcl.ecc[a].publicKey(b,d),sec:new sjcl.ecc[a].secretKey(b,c)}}}};sjcl.ecc.U("elGamal"); +sjcl.ecc.elGamal.publicKey.prototype={kem:function(a){a=sjcl.bn.random(this.h.r,a);var b=this.h.G.mult(a).toBits();return{key:sjcl.hash.sha256.hash(this.K.mult(a).toBits()),tag:b}}};sjcl.ecc.elGamal.secretKey.prototype={unkem:function(a){return sjcl.hash.sha256.hash(this.h.fromBits(a).mult(this.I).toBits())},dh:function(a){return sjcl.hash.sha256.hash(a.K.mult(this.I).toBits())}};sjcl.ecc.U("ecdsa"); +sjcl.ecc.ecdsa.secretKey.prototype={sign:function(a,b){var c=this.h.r,d=c.bitLength(),e=sjcl.bn.random(c.sub(1),b).add(1);b=this.h.G.mult(e).x.mod(c);a=sjcl.bn.fromBits(a).add(b.mul(this.I)).inverseMod(c).mul(e).mod(c);return sjcl.bitArray.concat(b.toBits(d),a.toBits(d))}}; +sjcl.ecc.ecdsa.publicKey.prototype={verify:function(a,b){var c=sjcl.bitArray,d=this.h.r,e=d.bitLength(),f=sjcl.bn.fromBits(c.bitSlice(b,0,e));b=sjcl.bn.fromBits(c.bitSlice(b,e,2*e));a=sjcl.bn.fromBits(a).mul(b).mod(d);c=f.mul(b).mod(d);a=this.h.G.mult2(a,c,this.K).x;if(f.equals(0)||b.equals(0)||f.greaterEquals(d)||b.greaterEquals(d)||!a.equals(f))throw new sjcl.exception.corrupt("signature didn't check out");return true}}; diff --git a/test/cbc_test.js b/test/cbc_test.js new file mode 100644 index 00000000..b57bb8cc --- /dev/null +++ b/test/cbc_test.js @@ -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