diff options
author | Quinn Slack <sqs@cs.stanford.edu> | 2011-04-19 02:42:39 -0700 |
---|---|---|
committer | Quinn Slack <sqs@cs.stanford.edu> | 2011-04-19 02:42:39 -0700 |
commit | 87098ccfe5ceb10b8b9bbe3ede114c2034102ff9 (patch) | |
tree | ccd63460413b859180df49069285617523ffd722 | |
parent | ccf4595f1b2003722593cb2b30230c020b6930f2 (diff) | |
parent | 096b3848a15064d82e9b0b4b0d746501d585df23 (diff) | |
download | sjcl-87098ccfe5ceb10b8b9bbe3ede114c2034102ff9.zip sjcl-87098ccfe5ceb10b8b9bbe3ede114c2034102ff9.tar.gz sjcl-87098ccfe5ceb10b8b9bbe3ede114c2034102ff9.tar.bz2 |
Merge branch 'ecc' of github.com:sqs/sjcl into srp
Conflicts:
config.mk
sjcl.js
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | config.mk | 2 | ||||
-rwxr-xr-x | configure | 6 | ||||
-rw-r--r-- | core/bitArray.js | 23 | ||||
-rw-r--r-- | core/bn.js | 517 | ||||
-rw-r--r-- | core/cbc.js | 115 | ||||
-rw-r--r-- | core/convenience.js | 15 | ||||
-rw-r--r-- | core/ecc.js | 380 | ||||
-rw-r--r-- | core/ocb2.js | 5 | ||||
-rw-r--r-- | core/random.js | 2 | ||||
-rw-r--r-- | core/sjcl.js | 6 | ||||
-rw-r--r-- | sjcl.js | 112 | ||||
-rw-r--r-- | test/cbc_test.js | 33 | ||||
-rw-r--r-- | test/cbc_vectors.js | 413 | ||||
-rw-r--r-- | test/ecdh_test.js | 18 | ||||
-rw-r--r-- | test/ecdsa_test.js | 29 | ||||
-rw-r--r-- | test/run_tests_browser.js | 6 |
17 files changed, 1629 insertions, 57 deletions
@@ -49,9 +49,9 @@ doc_private: $(SOURCES) rm -fr $@ JSDOCDIR=$(JSDOCDIR) $(JSDOC) -t=$(JSTEMPLATEDIR) $(SOURCES) --private -d=$@ -lint: core.js core/*.js test/*.js browser/*.js lint/coding_guidelines.pl +lint: core.js core/*.js test/*.js browserTest/*.js lint/coding_guidelines.pl rhino lint/jslint_rhino.js core.js - lint/coding_guidelines.pl core/*.js test/*.js browser/*.js + lint/coding_guidelines.pl core/*.js test/*.js browserTest/*.js TEST_SCRIPTS= browserTest/rhinoUtil.js \ @@ -1,2 +1,2 @@ -SOURCES= core/sjcl.js core/aes.js core/bitArray.js core/codecString.js core/codecHex.js core/codecBase64.js core/sha1.js core/sha256.js core/ccm.js core/ocb2.js core/hmac.js core/pbkdf2.js core/random.js core/convenience.js +SOURCES= core/sjcl.js core/aes.js core/bitArray.js core/codecString.js core/codecHex.js core/codecBase64.js core/sha1.js core/sha256.js core/ccm.js core/cbc.js core/ocb2.js core/hmac.js core/pbkdf2.js core/random.js core/convenience.js core/bn.js core/ecc.js COMPRESS= core_closure.js @@ -4,7 +4,7 @@ use strict; my ($arg, $i, $j, $targ); -my @targets = qw/sjcl aes bitArray codecString codecHex codecBase64 codecBytes sha256 ccm ocb2 hmac pbkdf2 random convenience/; +my @targets = qw/sjcl aes bitArray codecString codecHex codecBase64 codecBytes sha256 ccm cbc ocb2 hmac pbkdf2 random convenience bn ecc/; my %deps = ('aes'=>'sjcl', 'bitArray'=>'sjcl', 'codecString'=>'bitArray', @@ -12,10 +12,12 @@ my %deps = ('aes'=>'sjcl', 'codecBase64'=>'bitArray', 'codecBytes'=>'bitArray', 'sha256'=>'codecString', + 'cbc'=>'bitArray,aes', 'ccm'=>'bitArray,aes', 'ocb2'=>'bitArray,aes', 'hmac'=>'sha256', 'pbkdf2'=>'hmac', + 'ecc'=>'bn', 'random'=>'sha256,aes', 'convenience'=>'ccm,pbkdf2,random'); @@ -24,7 +26,7 @@ my $compress = "closure"; my %enabled = (); $enabled{$_} = 0 foreach (@targets); -# by default, all but codecBytes +# by default, all but codecBytes, ecc, bn, cbc $enabled{$_} = 1 foreach (qw/aes bitArray codecString codecHex codecBase64 sha256 ccm ocb2 hmac pbkdf2 random convenience/); # argument parsing diff --git a/core/bitArray.js b/core/bitArray.js index 40e4acd..a6d0617 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. @@ -43,6 +43,27 @@ sjcl.bitArray = { }, /** + * 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<<blength) - 1); + }, + + /** * Concatenate two bit arrays. * @param {bitArray} a1 The first array. * @param {bitArray} a2 The second array. diff --git a/core/bn.js b/core/bn.js new file mode 100644 index 0000000..16978e7 --- /dev/null +++ b/core/bn.js @@ -0,0 +1,517 @@ +/** + * Constructs a new bignum from another bignum, a number or a hex string. + */ +sjcl.bn = function(it) { + this.initWith(it); +}; + +sjcl.bn.prototype = { + radix: 24, + maxMul: 8, + _class: sjcl.bn, + + copy: function() { + return new this._class(this); + }, + + /** + * Initializes this with it, either as a bn, a number, or a hex string. + */ + initWith: function(it) { + var i=0, k, n, l; + switch(typeof it) { + case "object": + this.limbs = it.limbs.slice(0); + break; + + case "number": + this.limbs = [it]; + this.normalize(); + break; + + case "string": + it = it.replace(/^0x/, ''); + this.limbs = []; + // hack + k = this.radix / 4; + for (i=0; i < it.length; i+=k) { + this.limbs.push(parseInt(it.substring(Math.max(it.length - i - k, 0), it.length - i),16)); + } + break; + + default: + this.limbs = [0]; + } + return this; + }, + + /** + * Returns true if "this" and "that" are equal. Calls fullReduce(). + * Equality test is in constant time. + */ + equals: function(that) { + if (typeof that === "number") { that = new this._class(that); } + var difference = 0, i; + this.fullReduce(); + that.fullReduce(); + for (i = 0; i < this.limbs.length || i < that.limbs.length; i++) { + difference |= this.getLimb(i) ^ that.getLimb(i); + } + return (difference === 0); + }, + + /** + * Get the i'th limb of this, zero if i is too large. + */ + getLimb: function(i) { + return (i >= 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<ll.length; i++) { + l[i] = 0; + } + 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, l=this.limbs, ll=that.limbs; + for (i=l.length; i<ll.length; i++) { + l[i] = 0; + } + 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); + }, + + /** this - that. Does not normalize. */ + sub: function(that) { + return this.copy().subM(that); + }, + + /** this * that. Normalizes and reduces. */ + mul: function(that) { + if (typeof(that) === "number") { that = new this._class(that); } + var i, j, a = this.limbs, b = that.limbs, al = a.length, bl = b.length, out = new this._class(), c = out.limbs, ai, ii=this.maxMul; + + for (i=0; i < this.limbs.length + that.limbs.length + 1; i++) { + c[i] = 0; + } + for (i=0; i<al; i++) { + ai = a[i]; + for (j=0; j<bl; j++) { + c[i+j] += ai * b[j]; + } + + if (!--ii) { + ii = this.maxMul; + out.cnormalize(); + } + } + return out.cnormalize().reduce(); + }, + + /** this ^ 2. Normalizes and reduces. */ + square: function() { + return this.mul(this); + }, + + /** this ^ n. Uses square-and-multiply. Normalizes and reduces. */ + power: function(l) { + if (typeof(l) === "number") { + l = [l]; + } else if (l.limbs !== undefined) { + l = l.normalize().limbs; + } + var i, j, out = new this._class(1), pow = this; + + for (i=0; i<l.length; i++) { + for (j=0; j<this.radix; j++) { + if (l[i] & (1<<j)) { + out = out.mul(pow); + } + pow = pow.square(); + } + } + + 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; + }, + + /** Reduce and normalize. */ + fullReduce: function() { + return this.normalize(); + }, + + /** Propagate carries. */ + normalize: function() { + var carry=0, i, pv = this.placeVal, ipv = this.ipv, l, m, limbs = this.limbs, ll = limbs.length, mask = this.radixMask; + for (i=0; i < ll || (carry !== 0 && carry !== -1); i++) { + l = (limbs[i]||0) + carry; + m = limbs[i] = l & mask; + carry = (l-m)*ipv; + } + if (carry === -1) { + limbs[i-1] -= this.placeVal; + } + return this; + }, + + /** Constant-time normalize. Does not allocate additional space. */ + cnormalize: function() { + var carry=0, i, ipv = this.ipv, l, m, limbs = this.limbs, ll = limbs.length, mask = this.radixMask; + for (i=0; i < ll-1; i++) { + l = limbs[i] + carry; + m = limbs[i] = l & mask; + carry = (l-m)*ipv; + } + 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), + 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<coeff.length; i++) { + ppr.offset[i] = Math.floor(coeff[i][0] / ppr.radix - tmp); + 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 sjcl.bn(Math.pow(2,coeff[i][0])*coeff[i][1])); + ppr.minOffset = Math.min(ppr.minOffset, -ppr.offset[i]); // conservative + } + ppr._class = p; + ppr.modulus.cnormalize(); + + /** Approximate reduction mod p. May leave a number which is negative or slightly larger than p. */ + ppr.reduce = function() { + var i, k, l, mo = this.modOffset, limbs = this.limbs, aff, off = this.offset, ol = this.offset.length, fac = this.factor, ll; + + i = this.minOffset; + while (limbs.length > mo) { + l = limbs.pop(); + ll = limbs.length; + for (k=0; k<ol; k++) { + limbs[ll+off[k]] -= fac[k] * l; + } + + i--; + if (!i) { + limbs.push(0); + this.cnormalize(); + i = this.minOffset; + } + } + this.cnormalize(); + + return this; + }; + + ppr._strongReduce = (ppr.fullMask === -1) ? ppr.reduce : function() { + var limbs = this.limbs, i = limbs.length - 1, k, l; + this.reduce(); + if (i === this.modOffset - 1) { + l = limbs[i] & this.fullMask; + limbs[i] -= l; + for (k=0; k<this.fullOffset.length; k++) { + limbs[i+this.fullOffset[k]] -= this.fullFactor[k] * l; + } + this.normalize(); + } + }; + + /** mostly constant-time, very expensive full reduction. */ + ppr.fullReduce = function() { + var greater, i; + // massively above the modulus, may be negative + + this._strongReduce(); + // less than twice the modulus, may be negative + + this.addM(this.modulus); + this.addM(this.modulus); + this.normalize(); + // probably 2-3x the modulus + + this._strongReduce(); + // less than the power of 2. still may be more than + // the modulus + + // HACK: pad out to this length + for (i=this.limbs.length; i<this.modOffset; i++) { + this.limbs[i] = 0; + } + + // constant-time subtract modulus + greater = this.greaterEquals(this.modulus); + for (i=0; i<this.limbs.length; i++) { + this.limbs[i] -= this.modulus.limbs[i] * greater; + } + this.cnormalize(); + + return this; + }; + + ppr.inverse = function() { + return (this.power(this.modulus.sub(2))); + }; + + p.fromBits = sjcl.bn.fromBits; + + return p; +}; + +// a small Mersenne prime +sjcl.bn.prime = { + p127: sjcl.bn.pseudoMersennePrime(127, [[0,-1]]), + + // Bernstein's prime for Curve25519 + p25519: sjcl.bn.pseudoMersennePrime(255, [[0,-19]]), + + // 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]]) +}; + +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 { + words = sjcl.random.randomWords(l, paranoia); + if (words[l-1] < 0) { words[l-1] += 0x100000000; } + } while (Math.floor(words[l-1] / m) === Math.floor(0x100000000 / m)); + words[l-1] %= m; + + // mask off all the limbs + for (i=0; i<l-1; i++) { + words[i] &= modulus.radixMask; + } + + // check the rest of the digitssj + out.limbs = words; + if (!out.greaterEquals(modulus)) { + return out; + } + } +}; + diff --git a/core/cbc.js b/core/cbc.js new file mode 100644 index 0000000..9a98ed8 --- /dev/null +++ b/core/cbc.js @@ -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); + } + }; +}; diff --git a/core/convenience.js b/core/convenience.js index 2a7a3f2..d97f9df 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<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 diff --git a/core/ecc.js b/core/ecc.js new file mode 100644 index 0000000..504288f --- /dev/null +++ b/core/ecc.js @@ -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; + } +}; diff --git a/core/ocb2.js b/core/ocb2.js index e4629ac..388f4d1 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 2080cd3..a32eaa3 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 2cc5090..6f1337e 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; } } }; @@ -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<k;j++){g=n[d>>>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*32<b)return a;a=a.slice(0,Math.ceil(b/ -32));var c=a.length;b&=31;if(c>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<a.length;d++)c|=a[d]^b[d];return c===0},Q:function(a,b,c,d){var e;e=0;if(d===undefined)d=[];for(;b>=32;b-=32){d.push(c);c=0}if(b===0)return d.concat(a); -for(e=0;e<a.length;e++){d.push(c|a[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<j;k++){g=n[d>>>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<<c)-1},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.aa(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*32<b)return a;a=a.slice(0,Math.ceil(b/32));var c=a.length;b&=31;if(c>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<a.length;d++)c|= +a[d]^b[d];return c===0},aa:function(a,b,c,d){var e;e=0;if(d===undefined)d=[];for(;b>=32;b-=32){d.push(c);c=0}if(b===0)return d.concat(a);for(e=0;e<a.length;e++){d.push(c|a[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<c/8;d++){if((d&3)===0)e=a[d/4];b+=String.fromCharCode(e>>>24);e<<=8}return decodeURIComponent(escape(b))},toBits:function(a){a=unescape(encodeURIComponent(a));var b=[],c,d=0;for(c=0;c<a.length;c++){d=d<<8|a.charCodeAt(c);if((c&3)===3){b.push(d);d=0}}c&3&&b.push(sjcl.bitArray.partial(8*(c&3),d));return b}}; sjcl.codec.hex={fromBits:function(a){var b="",c;for(c=0;c<a.length;c++)b+=((a[c]|0)+0xf00000000000).toString(16).substr(4);return b.substr(0,sjcl.bitArray.bitLength(a)/4)},toBits:function(a){var b,c=[],d;a=a.replace(/\s|0x/g,"");d=a.length;a+="00000000";for(b=0;b<a.length;b+=8)c.push(parseInt(a.substr(b,8),16)^0);return sjcl.bitArray.clamp(c,d*4)}}; -sjcl.codec.base64={G:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",fromBits:function(a,b){var c="",d,e=0,f=sjcl.codec.base64.G,g=0,h=sjcl.bitArray.bitLength(a);for(d=0;c.length*6<h;){c+=f.charAt((g^a[d]>>>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;c<a.length;c++){g=e.indexOf(a.charAt(c));if(g<0)throw new sjcl.exception.invalid("this isn't base64!"); -if(d>26){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<<a|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<g.length;d+=4)f=a.encrypt(i(f,g.slice(d,d+4).concat([0,0,0])))}for(d=0;d<b.length;d+=4)f=a.encrypt(i(f,b.slice(d,d+4).concat([0,0,0])));return h.clamp(f,e*8)},K:function(a,b,c,d,e,f){var g,h=sjcl.bitArray;g=h.m;var i=b.length,k=h.bitLength(b);c=h.concat([h.partial(8, -f-1)],c).concat([0,0,0]).slice(0,4);d=h.bitSlice(g(d,a.encrypt(c)),0,e);if(!i)return{tag:d,data:[]};for(g=0;g<i;g+=4){c[3]++;e=a.encrypt(c);b[g]^=e[0];b[g+1]^=e[1];b[g+2]^=e[2];b[g+3]^=e[3]}return{tag:d,data:h.clamp(b,k)}}}; -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.D,i=sjcl.bitArray,k=i.m,j=[0,0,0,0];c=h(a.encrypt(c));var l,m=[];d=d||[];e=e||64;for(g=0;g+4<b.length;g+=4){l=b.slice(g,g+4);j=k(j,l);m=m.concat(k(c,a.encrypt(k(c,l))));c=h(c)}l=b.slice(g);b=i.bitLength(l);g=a.encrypt(k(c,[0,0,0,b]));l=i.clamp(k(l.concat([0,0,0]),g),b);j=k(j,k(l.concat([0,0,0]),g));j=a.encrypt(k(j,k(c,h(c)))); -if(d.length)j=k(j,f?d:sjcl.mode.ocb2.pmac(a,d));return m.concat(i.concat(l,i.clamp(j,e)))},decrypt:function(a,b,c,d,e,f){if(sjcl.bitArray.bitLength(c)!==128)throw new sjcl.exception.invalid("ocb iv must be 128 bits");e=e||64;var g=sjcl.mode.ocb2.D,h=sjcl.bitArray,i=h.m,k=[0,0,0,0],j=g(a.encrypt(c)),l,m,n=sjcl.bitArray.bitLength(b)-e,o=[];d=d||[];for(c=0;c+4<n/32;c+=4){l=i(j,a.decrypt(i(j,b.slice(c,c+4))));k=i(k,l);o=o.concat(l);j=g(j)}m=n-c*32;l=a.encrypt(i(j,[0,0,0,m]));l=i(l,h.clamp(b.slice(c), -m).concat([0,0,0]));k=i(k,l);k=a.encrypt(i(k,i(j,g(j))));if(d.length)k=i(k,f?d:sjcl.mode.ocb2.pmac(a,d));if(!h.equal(h.clamp(k,e),h.bitSlice(b,n)))throw new sjcl.exception.corrupt("ocb: tag doesn't match");return o.concat(h.clamp(l,m))},pmac:function(a,b){var c,d=sjcl.mode.ocb2.D,e=sjcl.bitArray,f=e.m,g=[0,0,0,0],h=a.encrypt([0,0,0,0]);h=f(h,d(d(h)));for(c=0;c+4<b.length;c+=4){h=d(h);g=f(g,a.encrypt(f(h,b.slice(c,c+4))))}b=b.slice(c);if(e.bitLength(b)<128){h=f(h,d(h));b=e.concat(b,[2147483648|0,0, -0,0])}g=f(g,b);return a.encrypt(f(d(f(h,d(h))),g))},D:function(a){return[a[0]<<1^a[1]>>>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;b<d;b++){c[0][b]=a[b]^909522486;c[1][b]=a[b]^1549556828}this.n[0].update(c[0]);this.n[1].update(c[1])}; -sjcl.misc.hmac.prototype.encrypt=sjcl.misc.hmac.prototype.mac=function(a,b){a=(new this.O(this.n[0])).update(a,b).finalize();return(new this.O(this.n[1])).update(a).finalize()}; -sjcl.misc.pbkdf2=function(a,b,c,d,e){c=c||1E3;if(d<0||c<0)throw sjcl.exception.invalid("invalid params to pbkdf2");if(typeof a==="string")a=sjcl.codec.utf8String.toBits(a);e=e||sjcl.misc.hmac;a=new e(a);var f,g,h,i,k=[],j=sjcl.bitArray;for(i=1;32*k.length<(d||1);i++){e=f=a.encrypt(j.concat(b,[i]));for(g=1;g<c;g++){f=a.encrypt(f);for(h=0;h<f.length;h++)e[h]^=f[h]}k=k.concat(e)}if(d)k=j.clamp(k,d);return k}; -sjcl.random={randomWords:function(a,b){var c=[];b=this.isReady(b);var d;if(b===0)throw new sjcl.exception.notready("generator isn't seeded");else b&2&&this.W(!(b&1));for(b=0;b<a;b+=4){(b+1)%0x10000===0&&this.N();d=this.A();c.push(d[0],d[1],d[2],d[3])}this.N();return c.slice(0,a)},setDefaultParanoia:function(a){this.z=a},addEntropy:function(a,b,c){c=c||"user";var d,e,f=(new Date).valueOf(),g=this.s[c],h=this.isReady();d=this.H[c];if(d===undefined)d=this.H[c]=this.S++;if(g===undefined)g=this.s[c]=0;this.s[c]= -(this.s[c]+1)%this.e.length;switch(typeof a){case "number":break;case "object":if(b===undefined)for(c=b=0;c<a.length;c++)for(e=a[c];e>0;){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<d.length;b++){c=d[b];delete a[c]}},e:[new sjcl.hash.sha256],l:[0],C:0,s:{},L:0,H:{},S:0,i:0,h:0,P:0,a:[0,0,0,0,0,0,0,0],g:[0,0,0,0],w:undefined,z:6,o:false,u:{progress:{},seeded:{}},R:0,F:[0,48,64,96,128,192,0x100,384,512,768,1024],A:function(){for(var a=0;a<4;a++){this.g[a]=this.g[a]+1|0;if(this.g[a])break}return this.w.encrypt(this.g)},N:function(){this.a=this.A().concat(this.A());this.w=new sjcl.cipher.aes(this.a)},V:function(a){this.a= -sjcl.hash.sha256.hash(this.a.concat(a));this.w=new sjcl.cipher.aes(this.a);for(a=0;a<4;a++){this.g[a]=this.g[a]+1|0;if(this.g[a])break}},W:function(a){var b=[],c=0,d;this.P=b[0]=(new Date).valueOf()+3E4;for(d=0;d<16;d++)b.push(Math.random()*0x100000000|0);for(d=0;d<this.e.length;d++){b=b.concat(this.e[d].finalize());c+=this.l[d];this.l[d]=0;if(!a&&this.C&1<<d)break}if(this.C>=1<<this.e.length){this.e.push(new sjcl.hash.sha256);this.l.push(0)}this.h-=c;if(c>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<d.length;c++)d[c](b)}}; -sjcl.json={defaults:{v:1,iter:1E3,ks:128,ts:64,mode:"ccm",adata:"",cipher:"aes"},encrypt:function(a,b,c,d){c=c||{};d=d||{};var e=sjcl.json,f=e.f({iv:sjcl.random.randomWords(4,0)},e.defaults);e.f(f,c);if(typeof f.salt==="string")f.salt=sjcl.codec.base64.toBits(f.salt);if(typeof f.iv==="string")f.iv=sjcl.codec.base64.toBits(f.iv);if(!sjcl.mode[f.mode]||!sjcl.cipher[f.cipher]||typeof a==="string"&&f.iter<=100||f.ts!==64&&f.ts!==96&&f.ts!==128||f.ks!==128&&f.ks!==192&&f.ks!==0x100||f.iv.length<2||f.iv.length> -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<a.length;c++){if(!(d=a[c].match(/^([a-z][a-z0-9]*):(?:(\d+)|"([a-z0-9+\/%*_.@=\-]*)")$/i)))throw new sjcl.exception.invalid("json decode: this isn't json!");b[d[1]]=d[2]?parseInt(d[2],10):d[1].match(/^(ct|salt|iv)$/)?sjcl.codec.base64.toBits(d[3]):unescape(d[3])}return b},f:function(a,b,c){if(a=== -undefined)a={};if(b===undefined)return a;var d;for(d in b)if(b.hasOwnProperty(d)){if(c&&a[d]!==undefined&&a[d]!==b[d])throw new sjcl.exception.invalid("required parameter overridden");a[d]=b[d]}return a},X:function(a,b){var c={},d;for(d in a)if(a.hasOwnProperty(d)&&a[d]!==b[d])c[d]=a[d];return c},Y:function(a,b){var c={},d;for(d=0;d<b.length;d++)if(a[b[d]]!==undefined)c[b[d]]=a[b[d]];return c}};sjcl.encrypt=sjcl.json.encrypt;sjcl.decrypt=sjcl.json.decrypt;sjcl.misc.U={}; -sjcl.misc.cachedPbkdf2=function(a,b){var c=sjcl.misc.U,d;b=b||{};d=b.iter||1E3;c=c[a]=c[a]||{};d=c[d]=c[d]||{firstSalt:b.salt&&b.salt.length?b.salt.slice(0):sjcl.random.randomWords(2,0)};c=b.salt===undefined?d.firstSalt:b.salt;d[c]=d[c]||sjcl.misc.pbkdf2(a,c,b.iter);return{key:d[c].slice(0),salt:c.slice(0)}}; +sjcl.codec.base64={P:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",fromBits:function(a,b){var c="",d,e=0,f=sjcl.codec.base64.P,g=0,h=sjcl.bitArray.bitLength(a);for(d=0;c.length*6<h;){c+=f.charAt((g^a[d]>>>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;c<a.length;c++){g=e.indexOf(a.charAt(c));if(g<0)throw new sjcl.exception.invalid("this isn't base64!"); +if(d>26){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<<a|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<g.length;d+=4)f=a.encrypt(i(f,g.slice(d,d+4).concat([0,0,0])))}for(d=0;d<b.length;d+=4)f=a.encrypt(i(f,b.slice(d,d+4).concat([0,0,0])));return h.clamp(f,e*8)},T:function(a,b,c,d,e,f){var g,h=sjcl.bitArray;g=h.l;var i=b.length,j=h.bitLength(b);c=h.concat([h.partial(8, +f-1)],c).concat([0,0,0]).slice(0,4);d=h.bitSlice(g(d,a.encrypt(c)),0,e);if(!i)return{tag:d,data:[]};for(g=0;g<i;g+=4){c[3]++;e=a.encrypt(c);b[g]^=e[0];b[g+1]^=e[1];b[g+2]^=e[2];b[g+3]^=e[3]}return{tag:d,data:h.clamp(b,j)}}};if(sjcl.beware===undefined)sjcl.beware={}; +sjcl.beware["CBC mode is dangerous because it doesn't protect message integrity."]=function(){sjcl.mode.cbc={name:"cbc",encrypt: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");var e=sjcl.bitArray,f=e.l,g=e.bitLength(b),h=0,i=[];if(g&7)throw new sjcl.exception.invalid("pkcs#5 padding only works for multiples of a byte");for(d=0;h+128<=g;d+=4,h+=128){c=a.encrypt(f(c, +b.slice(d,d+4)));i.splice(d,0,c[0],c[1],c[2],c[3])}g=(16-(g>>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;d<b.length;d+=4){g=b.slice(d,d+4);c=f(c,a.decrypt(g));h.splice(d,0,c[0],c[1],c[2],c[3]);c=g}g=h[d-1]&255;if(g==0||g>16)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<b.length;g+=4){l=b.slice(g,g+4);k=j(k,l);l=j(c,a.encrypt(j(c,l)));m.splice(g,0,l[0],l[1],l[2],l[3]);c=h(c)}l=b.slice(g);b=i.bitLength(l);g=a.encrypt(j(c,[0,0,0,b]));l=i.clamp(j(l.concat([0,0,0]),g),b);k=j(k,j(l.concat([0,0,0]),g)); +k=a.encrypt(j(k,j(c,h(c))));if(d.length)k=j(k,f?d:sjcl.mode.ocb2.pmac(a,d));return m.concat(i.concat(l,i.clamp(k,e)))},decrypt:function(a,b,c,d,e,f){if(sjcl.bitArray.bitLength(c)!==128)throw new sjcl.exception.invalid("ocb iv must be 128 bits");e=e||64;var g=sjcl.mode.ocb2.N,h=sjcl.bitArray,i=h.l,j=[0,0,0,0],k=g(a.encrypt(c)),l,m,n=sjcl.bitArray.bitLength(b)-e,o=[];d=d||[];for(c=0;c+4<n/32;c+=4){l=i(k,a.decrypt(i(k,b.slice(c,c+4))));j=i(j,l);o.splice(c,0,l[0],l[1],l[2],l[3]);k=g(k)}m=n-c*32;l=a.encrypt(i(k, +[0,0,0,m]));l=i(l,h.clamp(b.slice(c),m).concat([0,0,0]));j=i(j,l);j=a.encrypt(i(j,i(k,g(k))));if(d.length)j=i(j,f?d:sjcl.mode.ocb2.pmac(a,d));if(!h.equal(h.clamp(j,e),h.bitSlice(b,n)))throw new sjcl.exception.corrupt("ocb: tag doesn't match");return o.concat(h.clamp(l,m))},pmac:function(a,b){var c,d=sjcl.mode.ocb2.N,e=sjcl.bitArray,f=e.l,g=[0,0,0,0],h=a.encrypt([0,0,0,0]);h=f(h,d(d(h)));for(c=0;c+4<b.length;c+=4){h=d(h);g=f(g,a.encrypt(f(h,b.slice(c,c+4))))}b=b.slice(c);if(e.bitLength(b)<128){h=f(h, +d(h));b=e.concat(b,[2147483648|0,0,0,0])}g=f(g,b);return a.encrypt(f(d(f(h,d(h))),g))},N:function(a){return[a[0]<<1^a[1]>>>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;b<d;b++){c[0][b]=a[b]^909522486;c[1][b]=a[b]^1549556828}this.s[0].update(c[0]);this.s[1].update(c[1])}; +sjcl.misc.hmac.prototype.encrypt=sjcl.misc.hmac.prototype.mac=function(a,b){a=(new this.Y(this.s[0])).update(a,b).finalize();return(new this.Y(this.s[1])).update(a).finalize()}; +sjcl.misc.pbkdf2=function(a,b,c,d,e){c=c||1E3;if(d<0||c<0)throw sjcl.exception.invalid("invalid params to pbkdf2");if(typeof a==="string")a=sjcl.codec.utf8String.toBits(a);e=e||sjcl.misc.hmac;a=new e(a);var f,g,h,i,j=[],k=sjcl.bitArray;for(i=1;32*j.length<(d||1);i++){e=f=a.encrypt(k.concat(b,[i]));for(g=1;g<c;g++){f=a.encrypt(f);for(h=0;h<f.length;h++)e[h]^=f[h]}j=j.concat(e)}if(d)j=k.clamp(j,d);return j}; +sjcl.random={randomWords:function(a,b){var c=[];b=this.isReady(b);var d;if(b===0)throw new sjcl.exception.notReady("generator isn't seeded");else b&2&&this.ha(!(b&1));for(b=0;b<a;b+=4){(b+1)%0x10000===0&&this.X();d=this.J();c.push(d[0],d[1],d[2],d[3])}this.X();return c.slice(0,a)},setDefaultParanoia:function(a){this.H=a},addEntropy:function(a,b,c){c=c||"user";var d,e,f=(new Date).valueOf(),g=this.B[c],h=this.isReady();d=this.Q[c];if(d===undefined)d=this.Q[c]=this.da++;if(g===undefined)g=this.B[c]=0; +this.B[c]=(this.B[c]+1)%this.i.length;switch(typeof a){case "number":break;case "object":if(b===undefined)for(c=b=0;c<a.length;c++)for(e=a[c];e>0;){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<d.length;b++){c=d[b];delete a[c]}},i:[new sjcl.hash.sha256],q:[0],M:0,B:{},V:0,Q:{},da:0,n:0,m:0,$:0,c:[0,0,0,0,0,0,0,0],k:[0,0,0,0],F:undefined,H:6,t:false,D:{progress:{},seeded:{}},ca:0,O:[0,48,64,96,128,192,0x100,384,512,768,1024],J:function(){for(var a=0;a<4;a++){this.k[a]=this.k[a]+1|0;if(this.k[a])break}return this.F.encrypt(this.k)},X:function(){this.c=this.J().concat(this.J());this.F=new sjcl.cipher.aes(this.c)},ga:function(a){this.c= +sjcl.hash.sha256.hash(this.c.concat(a));this.F=new sjcl.cipher.aes(this.c);for(a=0;a<4;a++){this.k[a]=this.k[a]+1|0;if(this.k[a])break}},ha:function(a){var b=[],c=0,d;this.$=b[0]=(new Date).valueOf()+3E4;for(d=0;d<16;d++)b.push(Math.random()*0x100000000|0);for(d=0;d<this.i.length;d++){b=b.concat(this.i[d].finalize());c+=this.q[d];this.q[d]=0;if(!a&&this.M&1<<d)break}if(this.M>=1<<this.i.length){this.i.push(new sjcl.hash.sha256);this.q.push(0)}this.m-=c;if(c>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<d.length;c++)d[c](b)}}; +sjcl.json={defaults:{v:1,iter:1E3,ks:128,ts:64,mode:"ccm",adata:"",cipher:"aes"},encrypt:function(a,b,c,d){c=c||{};d=d||{};var e=sjcl.json,f=e.j({iv:sjcl.random.randomWords(4,0)},e.defaults);e.j(f,c);if(typeof f.salt==="string")f.salt=sjcl.codec.base64.toBits(f.salt);if(typeof f.iv==="string")f.iv=sjcl.codec.base64.toBits(f.iv);if(!sjcl.mode[f.mode]||!sjcl.cipher[f.cipher]||typeof a==="string"&&f.iter<=100||f.ts!==64&&f.ts!==96&&f.ts!==128||f.ks!==128&&f.ks!==192&&f.ks!==0x100||f.iv.length<2||f.iv.length> +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<a.length;c++){if(!(d=a[c].match(/^(?:(["']?)([a-z][a-z0-9]*)\1):(?:(\d+)|"([a-z0-9+\/%*_.@=\-]*)")$/i)))throw new sjcl.exception.invalid("json decode: this isn't json!");b[d[2]]=d[3]?parseInt(d[3],10):d[2].match(/^(ct|salt|iv)$/)?sjcl.codec.base64.toBits(d[4]):unescape(d[4])}return b},j:function(a,b,c){if(a=== +undefined)a={};if(b===undefined)return a;var d;for(d in b)if(b.hasOwnProperty(d)){if(c&&a[d]!==undefined&&a[d]!==b[d])throw new sjcl.exception.invalid("required parameter overridden");a[d]=b[d]}return a},ia:function(a,b){var c={},d;for(d=0;d<b.length;d++)if(a[b[d]]!==undefined)c[b[d]]=a[b[d]];return c}};sjcl.encrypt=sjcl.json.encrypt;sjcl.decrypt=sjcl.json.decrypt;sjcl.misc.fa={}; +sjcl.misc.cachedPbkdf2=function(a,b){var c=sjcl.misc.fa,d;b=b||{};d=b.iter||1E3;c=c[a]=c[a]||{};d=c[d]=c[d]||{firstSalt:b.salt&&b.salt.length?b.salt.slice(0):sjcl.random.randomWords(2,0)};c=b.salt===undefined?d.firstSalt:b.salt;d[c]=d[c]||sjcl.misc.pbkdf2(a,c,b.iter);return{key:d[c].slice(0),salt:c.slice(0)}};sjcl.bn=function(a){this.initWith(a)}; +sjcl.bn.prototype={radix:24,maxMul:8,f:sjcl.bn,copy:function(){return new this.f(this)},initWith:function(a){var b=0,c;switch(typeof a){case "object":this.limbs=a.limbs.slice(0);break;case "number":this.limbs=[a];this.normalize();break;case "string":a=a.replace(/^0x/,"");this.limbs=[];c=this.radix/4;for(b=0;b<a.length;b+=c)this.limbs.push(parseInt(a.substring(Math.max(a.length-b-c,0),a.length-b),16));break;default:this.limbs=[0]}return this},equals:function(a){if(typeof a==="number")a=new this.f(a); +var b=0,c;this.fullReduce();a.fullReduce();for(c=0;c<this.limbs.length||c<a.limbs.length;c++)b|=this.getLimb(c)^a.getLimb(c);return b===0},getLimb:function(a){return a>=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<this.limbs.length;b++){for(c= +d[b].toString(16);b<this.limbs.length-1&&c.length<6;)c="0"+c;a=c+a}return"0x"+a},addM:function(a){if(typeof a!=="object")a=new this.f(a);var b=this.limbs,c=a.limbs;for(a=b.length;a<c.length;a++)b[a]=0;for(a=0;a<c.length;a++)b[a]+=c[a];return this},doubleM:function(){var a,b=0,c,d=this.radix,e=this.radixMask,f=this.limbs;for(a=0;a<f.length;a++){c=f[a];c=c+c+b;f[a]=c&e;b=c>>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)<<d}e[e.length-1]||e.pop();return this},subM:function(a){if(typeof a!=="object")a=new this.f(a);var b=this.limbs,c=a.limbs;for(a=b.length;a<c.length;a++)b[a]=0;for(a=0;a<c.length;a++)b[a]-=c[a];return this},mod:function(a){a=(new sjcl.bn(a)).normalize();for(var b=(new sjcl.bn(this)).normalize(),c=0;b.greaterEquals(a);c++)a.doubleM();for(;c>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<d.limbs.length;f++)g|=d.limbs[f]}while(g);if(!e.equals(1))throw new sjcl.exception.invalid("inverseMod: p and x must be relatively prime");return c},add:function(a){return this.copy().addM(a)}, +sub:function(a){return this.copy().subM(a)},mul:function(a){if(typeof a==="number")a=new this.f(a);var b,c=this.limbs,d=a.limbs,e=c.length,f=d.length,g=new this.f,h=g.limbs,i,j=this.maxMul;for(b=0;b<this.limbs.length+a.limbs.length+1;b++)h[b]=0;for(b=0;b<e;b++){i=c[b];for(a=0;a<f;a++)h[b+a]+=i*d[a];if(!--j){j=this.maxMul;g.cnormalize()}}return g.cnormalize().reduce()},square:function(){return this.mul(this)},power:function(a){if(typeof a==="number")a=[a];else if(a.limbs!==undefined)a=a.normalize().limbs; +var b,c,d=new this.f(1),e=this;for(b=0;b<a.length;b++)for(c=0;c<this.radix;c++){if(a[b]&1<<c)d=d.mul(e);e=e.square()}return d},trim:function(){var a=this.limbs,b;do b=a.pop();while(a.length&&b===0);a.push(b);return this},reduce:function(){return this},fullReduce:function(){return this.normalize()},normalize:function(){var a=0,b,c=this.ipv,d,e=this.limbs,f=e.length,g=this.radixMask;for(b=0;b<f||a!==0&&a!==-1;b++){a=(e[b]||0)+a;d=e[b]=a&g;a=(a-d)*c}if(a===-1)e[b-1]-=this.placeVal;return this},cnormalize:function(){var a= +0,b,c=this.ipv,d,e=this.limbs,f=e.length,g=this.radixMask;for(b=0;b<f-1;b++){a=e[b]+a;d=e[b]=a&g;a=(a-d)*c}e[b]+=a;return this},toBits:function(a){this.fullReduce();a=a||this.exponent||this.limbs.length*this.radix;var b=Math.floor((a-1)/24),c=sjcl.bitArray;a=[c.partial((a+7&-8)%this.radix||this.radix,this.getLimb(b))];for(b--;b>=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);g<f;g+=e.radix)c.unshift(d.extract(a,g,e.radix));b.limbs=c;return b};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; +sjcl.bn.pseudoMersennePrime=function(a,b){function c(g){this.initWith(g)}var d=c.prototype=new sjcl.bn,e,f;e=d.modOffset=Math.ceil(f=a/d.radix);d.exponent=a;d.offset=[];d.factor=[];d.minOffset=e;d.fullMask=0;d.fullOffset=[];d.fullFactor=[];d.modulus=c.modulus=new sjcl.bn(Math.pow(2,a));d.fullMask=0|-Math.pow(2,a%d.radix);for(e=0;e<b.length;e++){d.offset[e]=Math.floor(b[e][0]/d.radix-f);d.fullOffset[e]=Math.ceil(b[e][0]/d.radix-f);d.factor[e]=b[e][1]*Math.pow(0.5,a-b[e][0]+d.offset[e]*d.radix);d.fullFactor[e]= +b[e][1]*Math.pow(0.5,a-b[e][0]+d.fullOffset[e]*d.radix);d.modulus.addM(new sjcl.bn(Math.pow(2,b[e][0])*b[e][1]));d.minOffset=Math.min(d.minOffset,-d.offset[e])}d.f=c;d.modulus.cnormalize();d.reduce=function(){var g,h,i,j=this.modOffset,k=this.limbs,l=this.offset,m=this.offset.length,n=this.factor,o;for(g=this.minOffset;k.length>j;){i=k.pop();o=k.length;for(h=0;h<m;h++)k[o+l[h]]-=n[h]*i;g--;if(!g){k.push(0);this.cnormalize();g=this.minOffset}}this.cnormalize();return this};d.ba=d.fullMask===-1?d.reduce: +function(){var g=this.limbs,h=g.length-1,i,j;this.reduce();if(h===this.modOffset-1){j=g[h]&this.fullMask;g[h]-=j;for(i=0;i<this.fullOffset.length;i++)g[h+this.fullOffset[i]]-=this.fullFactor[i]*j;this.normalize()}};d.fullReduce=function(){var g,h;this.ba();this.addM(this.modulus);this.addM(this.modulus);this.normalize();this.ba();for(h=this.limbs.length;h<this.modOffset;h++)this.limbs[h]=0;g=this.greaterEquals(this.modulus);for(h=0;h<this.limbs.length;h++)this.limbs[h]-=this.modulus.limbs[h]*g;this.cnormalize(); +return this};d.inverse=function(){return this.power(this.modulus.sub(2))};c.fromBits=sjcl.bn.fromBits;return c}; +sjcl.bn.prime={p127:sjcl.bn.pseudoMersennePrime(127,[[0,-1]]),p25519:sjcl.bn.pseudoMersennePrime(255,[[0,-19]]),p192:sjcl.bn.pseudoMersennePrime(192,[[0,-1],[64,-1]]),p224:sjcl.bn.pseudoMersennePrime(224,[[0,1],[96,-1]]),p256:sjcl.bn.pseudoMersennePrime(0x100,[[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]])}; +sjcl.bn.random=function(a,b){if(typeof a!=="object")a=new sjcl.bn(a);for(var c,d,e=a.limbs.length,f=a.limbs[e-1]+1,g=new sjcl.bn;;){do{c=sjcl.random.randomWords(e,b);if(c[e-1]<0)c[e-1]+=0x100000000}while(Math.floor(c[e-1]/f)===Math.floor(0x100000000/f));c[e-1]%=f;for(d=0;d<e-1;d++)c[d]&=a.radixMask;g.limbs=c;if(!g.greaterEquals(a))return g}};sjcl.ecc={};sjcl.ecc.point=function(a,b,c){if(b===undefined)this.isIdentity=true;else{this.x=b;this.y=c;this.isIdentity=false}this.curve=a}; +sjcl.ecc.point.prototype={toJac:function(){return new sjcl.ecc.pointJac(this.curve,this.x,this.y,new this.curve.field(1))},mult:function(a){return this.toJac().mult(a,this).toAffine()},mult2:function(a,b,c){return this.toJac().mult2(a,this,b,c).toAffine()},multiples:function(){var a,b,c;if(this.Z===undefined){c=this.toJac().doubl();a=this.Z=[new sjcl.ecc.point(this.curve),this,c.toAffine()];for(b=3;b<16;b++){c=c.add(this);a.push(c.toAffine())}}return this.Z},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())}};sjcl.ecc.pointJac=function(a,b,c,d){if(b===undefined)this.isIdentity=true;else{this.x=b;this.y=c;this.z=d;this.isIdentity=false}this.curve=a}; +sjcl.ecc.pointJac.prototype={add:function(a){var b,c,d,e;if(this.curve!==a.curve)throw"sjcl['ecc']['add'](): Points must be on the same curve to add them!";if(this.isIdentity)return a.toJac();else if(a.isIdentity)return this;b=this.z.square();c=a.x.mul(b).subM(this.x);if(c.equals(0))return this.y.equals(a.y.mul(b.mul(this.z)))?this.doubl():new sjcl.ecc.pointJac(this.curve);b=a.y.mul(b.mul(this.z)).subM(this.y);d=c.square();a=b.square();e=c.square().mul(c).addM(this.x.add(this.x).mul(d));a=a.subM(e); +b=this.x.mul(d).subM(a).mul(b);d=this.y.mul(c.square().mul(c));b=b.subM(d);c=this.z.mul(c);return new sjcl.ecc.pointJac(this.curve,a,b,c)},doubl:function(){if(this.isIdentity)return this;var a=this.y.square(),b=a.mul(this.x.mul(4)),c=a.square().mul(8);a=this.z.square();var d=this.x.sub(a).mul(3).mul(this.x.add(a));a=d.square().subM(b).subM(b);b=b.sub(a).mul(d).subM(c);c=this.y.add(this.y).mul(this.z);return new sjcl.ecc.pointJac(this.curve,a,b,c)},toAffine:function(){if(this.isIdentity||this.z.equals(0))return new sjcl.ecc.point(this.curve); +var a=this.z.inverse(),b=a.square();return new sjcl.ecc.point(this.curve,this.x.mul(b).fullReduce(),this.y.mul(b.mul(a)).fullReduce())},mult:function(a,b){if(typeof a==="number")a=[a];else if(a.limbs!==undefined)a=a.normalize().limbs;var c,d=(new sjcl.ecc.point(this.curve)).toJac(),e=b.multiples();for(b=a.length-1;b>=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 0000000..b57bb8c --- /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<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); +}); diff --git a/test/cbc_vectors.js b/test/cbc_vectors.js new file mode 100644 index 0000000..0eedc7f --- /dev/null +++ b/test/cbc_vectors.js @@ -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'}, +]; diff --git a/test/ecdh_test.js b/test/ecdh_test.js new file mode 100644 index 0000000..8bcf874 --- /dev/null +++ b/test/ecdh_test.js @@ -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(); +}); diff --git a/test/ecdsa_test.js b/test/ecdsa_test.js new file mode 100644 index 0000000..e305374 --- /dev/null +++ b/test/ecdsa_test.js @@ -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(); +}); diff --git a/test/run_tests_browser.js b/test/run_tests_browser.js index 2abf8c0..6e73758 100644 --- a/test/run_tests_browser.js +++ b/test/run_tests_browser.js @@ -8,12 +8,16 @@ function testCore(coreName, cb) { "ccm_vectors.js", "ocb2_test.js", "ocb2_vectors.js", + "cbc_test.js", + "cbc_vectors.js", "sha256_test.js", "sha256_vectors.js", "sha256_test_brute_force.js", "hmac_test.js", "hmac_vectors.js", - "pbkdf2_test.js" + "pbkdf2_test.js", + "ecdh_test.js", + "ecdsa_test.js" ], i; for (i=1; i<testFiles.length; i++) { |