From 3204998fcb6f31d6c90532a737a4adb8a1e420f6 Mon Sep 17 00:00:00 2001 From: Geert Weening Date: Mon, 1 Dec 2014 17:47:22 -0800 Subject: [PATCH] [TASK] update sjcl - native support for k256 - improved entropy by taking advantage of platform crypto - remove unnecessary sjcl overrides from sjcl-secp256k1.js - updated ripple-lib curve instantiations to use k256 - add curve override so c256 points to k256 https://github.com/bitwiseshiftleft/sjcl/commit/16dde36fa2a58845f639429acd5bc4e4ebb5a0f1 --- src/js/ripple/keypair.js | 4 +- src/js/ripple/seed.js | 2 +- .../sjcl-ecdsa-recoverablepublickey.js | 4 +- src/js/sjcl-custom/sjcl-secp256k1.js | 32 +- src/js/sjcl/.gitignore | 2 + src/js/sjcl/.travis.yml | 9 + src/js/sjcl/Makefile | 19 +- src/js/sjcl/README.md | 21 ++ src/js/sjcl/bower.json | 12 + src/js/sjcl/browserTest/browserUtil.js | 2 +- src/js/sjcl/browserTest/entropy.html | 88 ++++++ src/js/sjcl/browserTest/nodeUtil.js | 44 +++ src/js/sjcl/compress/digitize.pl | 2 +- src/js/sjcl/configure | 11 +- src/js/sjcl/core/bitArray.js | 16 +- src/js/sjcl/core/bn.js | 48 ++- src/js/sjcl/core/cbc.js | 16 +- src/js/sjcl/core/ccm.js | 8 +- src/js/sjcl/core/codecBase32.js | 64 ++++ src/js/sjcl/core/codecBase64.js | 8 +- src/js/sjcl/core/codecHex.js | 2 +- src/js/sjcl/core/convenience.js | 113 ++++--- src/js/sjcl/core/ecc.js | 279 +++++++++++++----- src/js/sjcl/core/gcm.js | 2 +- src/js/sjcl/core/hmac.js | 26 +- src/js/sjcl/core/pbkdf2.js | 6 +- src/js/sjcl/core/random.js | 198 ++++++++++--- src/js/sjcl/core/sha1.js | 3 +- src/js/sjcl/core/sha512.js | 2 +- src/js/sjcl/core/sjcl.js | 9 +- src/js/sjcl/demo/index.html | 2 +- src/js/sjcl/package.json | 16 + src/js/sjcl/sjcl.js | 84 +++--- src/js/sjcl/test/bitArray_test.js | 115 ++++++++ src/js/sjcl/test/bitArray_vectors.js | 163 ++++++++++ src/js/sjcl/test/ecc_conv.js | 2 +- src/js/sjcl/test/hmac_test.js | 16 +- src/js/sjcl/test/hmac_vectors.js | 1 + src/js/sjcl/test/json_test.js | 126 ++++++++ src/js/sjcl/test/run_tests_node.js | 16 + test/sjcl-ecdsa-recoverablepublickey-test.js | 36 ++- 41 files changed, 1339 insertions(+), 290 deletions(-) create mode 100644 src/js/sjcl/.gitignore create mode 100644 src/js/sjcl/.travis.yml create mode 100644 src/js/sjcl/README.md create mode 100644 src/js/sjcl/bower.json create mode 100644 src/js/sjcl/browserTest/entropy.html create mode 100644 src/js/sjcl/browserTest/nodeUtil.js create mode 100644 src/js/sjcl/core/codecBase32.js create mode 100644 src/js/sjcl/package.json create mode 100644 src/js/sjcl/test/bitArray_test.js create mode 100644 src/js/sjcl/test/bitArray_vectors.js create mode 100644 src/js/sjcl/test/json_test.js create mode 100644 src/js/sjcl/test/run_tests_node.js diff --git a/src/js/ripple/keypair.js b/src/js/ripple/keypair.js index a5f4a8e1..3a556a5c 100644 --- a/src/js/ripple/keypair.js +++ b/src/js/ripple/keypair.js @@ -5,7 +5,7 @@ var UInt256 = require('./uint256').UInt256; var Base = require('./base').Base; function KeyPair() { - this._curve = sjcl.ecc.curves.c256; + this._curve = sjcl.ecc.curves.k256; this._secret = null; this._pubkey = null; }; @@ -15,7 +15,7 @@ KeyPair.from_bn_secret = function(j) { }; KeyPair.prototype.parse_bn_secret = function(j) { - this._secret = new sjcl.ecc.ecdsa.secretKey(sjcl.ecc.curves.c256, j); + this._secret = new sjcl.ecc.ecdsa.secretKey(sjcl.ecc.curves.k256, j); return this; }; diff --git a/src/js/ripple/seed.js b/src/js/ripple/seed.js index 7755d661..e36cce84 100644 --- a/src/js/ripple/seed.js +++ b/src/js/ripple/seed.js @@ -16,7 +16,7 @@ var KeyPair = require('./keypair').KeyPair; var Seed = extend(function () { // Internal form: NaN or BigInteger - this._curve = sjcl.ecc.curves.c256; + this._curve = sjcl.ecc.curves.k256; this._value = NaN; }, UInt); diff --git a/src/js/sjcl-custom/sjcl-ecdsa-recoverablepublickey.js b/src/js/sjcl-custom/sjcl-ecdsa-recoverablepublickey.js index 3365342c..25eb0824 100644 --- a/src/js/sjcl-custom/sjcl-ecdsa-recoverablepublickey.js +++ b/src/js/sjcl-custom/sjcl-ecdsa-recoverablepublickey.js @@ -65,7 +65,7 @@ sjcl.ecc.ecdsa.secretKey.prototype.signWithRecoverablePublicKey = function(hash, * * @param {bitArray} hash * @param {bitArray} signature - * @param {sjcl.ecc.curve} [sjcl.ecc.curves['c256']] curve + * @param {sjcl.ecc.curve} [sjcl.ecc.curves['k256']] curve * @returns {sjcl.ecc.ecdsa.publicKey} Public key */ sjcl.ecc.ecdsa.publicKey.recoverFromSignature = function(hash, signature, curve) { @@ -75,7 +75,7 @@ sjcl.ecc.ecdsa.publicKey.recoverFromSignature = function(hash, signature, curve) } if (!curve) { - curve = sjcl.ecc.curves['c256']; + curve = sjcl.ecc.curves['k256']; } // Convert hash to bits and determine encoding for output diff --git a/src/js/sjcl-custom/sjcl-secp256k1.js b/src/js/sjcl-custom/sjcl-secp256k1.js index a17eccf0..5b81b537 100755 --- a/src/js/sjcl-custom/sjcl-secp256k1.js +++ b/src/js/sjcl-custom/sjcl-secp256k1.js @@ -1,17 +1,16 @@ // ----- for secp256k1 ------ -// Overwrite NIST-P256 with secp256k1 -sjcl.ecc.curves.c256 = new sjcl.ecc.curve( - sjcl.bn.pseudoMersennePrime(256, [[0,-1],[4,-1],[6,-1],[7,-1],[8,-1],[9,-1],[32,-1]]), - "0x14551231950b75fc4402da1722fc9baee", - 0, - 7, - "0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", - "0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8" -); +sjcl.ecc.point.prototype.toBytesCompressed = function () { + var header = this.y.mod(2).toString() == "0x0" ? 0x02 : 0x03; + return [header].concat(sjcl.codec.bytes.fromBits(this.x.toBits())) +}; // Replace point addition and doubling algorithms // NIST-P256 is a=-3, we need algorithms for a=0 +// +// This is a custom point addition formula that +// only works for a=-3 Jacobian curve. It's much +// faster than the generic implementation sjcl.ecc.pointJac.prototype.add = function(T) { var S = this; if (S.curve !== T.curve) { @@ -43,7 +42,7 @@ sjcl.ecc.pointJac.prototype.add = function(T) { var j = h.mul(i); var r = s2.sub(S.y).doubleM(); var v = S.x.mul(i); - + var x = r.square().subM(j).subM(v.copy().doubleM()); var y = r.mul(v.sub(x)).subM(S.y.mul(j).doubleM()); var z = S.z.add(h).square().subM(z1z1).subM(hh); @@ -51,6 +50,9 @@ sjcl.ecc.pointJac.prototype.add = function(T) { return new sjcl.ecc.pointJac(this.curve,x,y,z); }; +// This is a custom doubling algorithm that +// only works for a=-3 Jacobian curve. It's much +// faster than the generic implementation sjcl.ecc.pointJac.prototype.doubl = function () { if (this.isIdentity) { return this; } @@ -66,7 +68,9 @@ sjcl.ecc.pointJac.prototype.doubl = function () { return new sjcl.ecc.pointJac(this.curve, x, y, z); }; -sjcl.ecc.point.prototype.toBytesCompressed = function () { - var header = this.y.mod(2).toString() == "0x0" ? 0x02 : 0x03; - return [header].concat(sjcl.codec.bytes.fromBits(this.x.toBits())) -}; +// DEPRECATED: +// previously the c256 curve was overridden with the secp256k1 curve +// since then, sjcl has been updated to support k256 +// this override exist to keep supporting the old c256 with k256 behavior +// this will be removed in future release +sjcl.ecc.curves.c256 = sjcl.ecc.curves.k256; \ No newline at end of file diff --git a/src/js/sjcl/.gitignore b/src/js/sjcl/.gitignore new file mode 100644 index 00000000..3e0187e9 --- /dev/null +++ b/src/js/sjcl/.gitignore @@ -0,0 +1,2 @@ +core.js +core_closure.js diff --git a/src/js/sjcl/.travis.yml b/src/js/sjcl/.travis.yml new file mode 100644 index 00000000..502b4e83 --- /dev/null +++ b/src/js/sjcl/.travis.yml @@ -0,0 +1,9 @@ +before_script: ./configure --with-all + +language: node_js +node_js: + - "0.11" + - "0.10" + - "0.8" +# 0.6 appears to be unreliable on Travis at the moment. +# - "0.6" diff --git a/src/js/sjcl/Makefile b/src/js/sjcl/Makefile index 30515b25..6b09ee33 100644 --- a/src/js/sjcl/Makefile +++ b/src/js/sjcl/Makefile @@ -54,10 +54,11 @@ lint: core.js core/*.js test/*.js browserTest/*.js lint/coding_guidelines.pl lint/coding_guidelines.pl core/*.js test/*.js browserTest/*.js -TEST_COMMON= browserTest/rhinoUtil.js test/test.js +TEST_COMMON= browserTest/nodeUtil.js test/test.js TEST_SCRIPTS= $(TEST_COMMON) \ test/aes_vectors.js test/aes_test.js \ + test/bitArray_vectors.js test/bitArray_test.js \ test/ocb2_vectors.js test/ocb2_test.js \ test/ccm_vectors.js test/ccm_test.js \ test/cbc_vectors.js test/cbc_test.js \ @@ -70,18 +71,14 @@ TEST_SCRIPTS= $(TEST_COMMON) \ test/hmac_vectors.js test/hmac_test.js \ test/pbkdf2_test.js \ test/bn_vectors.js test/bn_test.js \ - test/ecdsa_test.js test/ecdsa_vectors.js test/ecdh_test.js + test/ecdsa_test.js test/ecdsa_vectors.js test/ecdh_test.js \ + test/srp_vectors.js test/srp_test.js \ + test/json_test.js -TEST_SCRIPTS_OPT= $(TEST_COMMON) \ - test/srp_vectors.js test/srp_test.js +# Run all tests in node.js. -# Rhino fails at -O 0. Probably because the big files full of test vectors blow the -# bytecode limit. So, run most tests with -O -1. But modular exponentiation is -# currently very slow (on Rhino), so run the SRP test with optimizations on. - -test: sjcl.js $(TEST_SCRIPTS) test/run_tests_rhino.js - @rhino -O -1 -w test/run_tests_rhino.js $< $(TEST_SCRIPTS) - @rhino -O 9 -w test/run_tests_rhino.js $< $(TEST_SCRIPTS_OPT) +test: sjcl.js $(TEST_SCRIPTS) test/run_tests_node.js + node test/run_tests_node.js $< $(TEST_SCRIPTS) tidy: find . -name '*~' -delete diff --git a/src/js/sjcl/README.md b/src/js/sjcl/README.md new file mode 100644 index 00000000..cc774a8b --- /dev/null +++ b/src/js/sjcl/README.md @@ -0,0 +1,21 @@ +sjcl +==== + +[![Build Status](https://travis-ci.org/bitwiseshiftleft/sjcl.png)](https://travis-ci.org/bitwiseshiftleft/sjcl) + +Stanford Javascript Crypto Library + +Security Advisories +=== +* 12.02.2014: the current development version has a paranoia bug in the ecc module. The bug was introduced in commit [ac0b3fe0](https://github.com/bitwiseshiftleft/sjcl/commit/ac0b3fe0) and might affect ecc key generation on platforms without a platform random number generator. +* + +Security Contact +==== +Security Mail: sjcl@ovt.me +OpenPGP-Key Fingerprint: 0D54 3E52 87B4 EC06 3FA9 0115 72ED A6C7 7AAF 48ED +Keyserver: pool.sks-keyservers.net + +Documentation +==== +The documentation is available [here](http://bitwiseshiftleft.github.io/sjcl/doc/) \ No newline at end of file diff --git a/src/js/sjcl/bower.json b/src/js/sjcl/bower.json new file mode 100644 index 00000000..dc9d7170 --- /dev/null +++ b/src/js/sjcl/bower.json @@ -0,0 +1,12 @@ +{ + "name": "sjcl", + "version": "1.0.0", + "main": ["./sjcl.js"], + "ignore": [ + "**/*", + "!README.md", + "!README/*", + "!bower.json", + "!sjcl.js" + ] +} diff --git a/src/js/sjcl/browserTest/browserUtil.js b/src/js/sjcl/browserTest/browserUtil.js index 9c23d01f..004a92cf 100644 --- a/src/js/sjcl/browserTest/browserUtil.js +++ b/src/js/sjcl/browserTest/browserUtil.js @@ -1,6 +1,6 @@ browserUtil = {}; -browserUtil.isRhino = (typeof(window) === 'undefined'); +browserUtil.isNodeJS = (typeof(window) === 'undefined'); /** * Pause (for the graphics to update and the script timer to clear), then run the diff --git a/src/js/sjcl/browserTest/entropy.html b/src/js/sjcl/browserTest/entropy.html new file mode 100644 index 00000000..4458ba73 --- /dev/null +++ b/src/js/sjcl/browserTest/entropy.html @@ -0,0 +1,88 @@ + + + +Entropy Generator Progress + + + + + + + + + + +

Entropy Generator Progress

+ +

Target: 192 bits, available at paranoia level 5.

+ +

Corresponding paranoia level from [0,1..10]: (the idea being that you can see the progress bar advance gently from empty/black to full/yellow after you press this)

+ +

(also consumes 192 bits with every keypress in the text field; use key repeat to consume swiftly)

+ +
+
+
+ +

Please move your mouse, play around and generally introduce entropy into your environment.

+ + + \ No newline at end of file diff --git a/src/js/sjcl/browserTest/nodeUtil.js b/src/js/sjcl/browserTest/nodeUtil.js new file mode 100644 index 00000000..9ccb6b94 --- /dev/null +++ b/src/js/sjcl/browserTest/nodeUtil.js @@ -0,0 +1,44 @@ +browserUtil = { + isNodeJS: true, + + pauseAndThen: function (cb) { cb(); }, + + cpsIterate: function (f, start, end, pause, callback) { + function go() { + var called = false; + if (start >= end) { + callback && callback(); + } else { + f(start, function () { + if (!called) { called = true; start++; go(); } + }); + } + } + go (start); + }, + + cpsMap: function (map, list, pause, callback) { + browserUtil.cpsIterate(function (i, cb) { map(list[i], i, list.length, cb); }, + 0, list.length, pause, callback); + }, + + loadScripts: function(scriptNames, callback) { + for (i=0; i) { - s/([^a-zA-Z0-9_])(\d+)/$1 . digitize $2/eg; + s/([^a-zA-Z0-9_"])(\d+)/$1 . digitize $2/eg; print; } diff --git a/src/js/sjcl/configure b/src/js/sjcl/configure index f5465cdc..65368f42 100755 --- a/src/js/sjcl/configure +++ b/src/js/sjcl/configure @@ -4,12 +4,13 @@ use strict; my ($arg, $i, $j, $targ); -my @targets = qw/sjcl aes bitArray codecString codecHex codecBase64 codecBytes sha256 sha512 sha1 ccm cbc ocb2 gcm hmac pbkdf2 random convenience bn ecc srp/; +my @targets = qw/sjcl aes bitArray codecString codecHex codecBase32 codecBase64 codecBytes sha256 sha512 sha1 ccm cbc ocb2 gcm hmac pbkdf2 random convenience bn ecc srp/; my %deps = ('aes'=>'sjcl', 'bitArray'=>'sjcl', 'codecString'=>'bitArray', 'codecHex'=>'bitArray', 'codecBase64'=>'bitArray', + 'codecBase32'=>'bitArray', 'codecBytes'=>'bitArray', 'sha256'=>'codecString', 'sha512'=>'codecString', @@ -32,10 +33,10 @@ my %enabled = (); $enabled{$_} = 0 foreach (@targets); # by default, all but codecBytes, srp, bn -$enabled{$_} = 1 foreach (qw/aes bitArray codecString codecHex codecBase64 sha256 ccm ocb2 gcm hmac pbkdf2 random convenience/); +$enabled{$_} = 1 foreach (qw/aes bitArray codecString codecHex codecBase32 codecBase64 sha256 ccm ocb2 gcm hmac pbkdf2 random convenience/); # argument parsing -while ($arg = shift @ARGV) { +while (my $arg = shift @ARGV) { if ($arg =~ /^--?with-all$/) { foreach (@targets) { if ($enabled{$_} == 0) { @@ -97,7 +98,7 @@ my $config = ''; my $pconfig; # dependency analysis: forbidden -foreach $i (@targets) { +foreach my $i (@targets) { if ($enabled{$i} > 0) { foreach $j (split /,/, $deps{$i}) { if ($enabled{$j} == -1) { @@ -114,7 +115,7 @@ foreach $i (@targets) { } # reverse -foreach $i (reverse @targets) { +foreach my $i (reverse @targets) { if ($enabled{$i} > 0) { foreach $j (split /,/, $deps{$i}) { if ($enabled{$j} < $enabled{$i}) { diff --git a/src/js/sjcl/core/bitArray.js b/src/js/sjcl/core/bitArray.js index a6d06171..54112ac6 100644 --- a/src/js/sjcl/core/bitArray.js +++ b/src/js/sjcl/core/bitArray.js @@ -74,7 +74,7 @@ sjcl.bitArray = { return a1.concat(a2); } - var out, i, last = a1[a1.length-1], shift = sjcl.bitArray.getPartial(last); + var last = a1[a1.length-1], shift = sjcl.bitArray.getPartial(last); if (shift === 32) { return a1.concat(a2); } else { @@ -183,5 +183,19 @@ sjcl.bitArray = { */ _xor4: function(x,y) { return [x[0]^y[0],x[1]^y[1],x[2]^y[2],x[3]^y[3]]; + }, + + /** byteswap a word array inplace. + * (does not handle partial words) + * @param {sjcl.bitArray} a word array + * @return {sjcl.bitArray} byteswapped array + */ + byteswapM: function(a) { + var i, v, m = 0xff00; + for (i = 0; i < a.length; ++i) { + v = a[i]; + a[i] = (v >>> 24) | ((v >>> 8) & m) | ((v & m) << 8) | (v << 24); + } + return a; } }; diff --git a/src/js/sjcl/core/bn.js b/src/js/sjcl/core/bn.js index d5a6b63e..e6e410a4 100644 --- a/src/js/sjcl/core/bn.js +++ b/src/js/sjcl/core/bn.js @@ -19,7 +19,7 @@ sjcl.bn.prototype = { * Initializes this with it, either as a bn, a number, or a hex string. */ initWith: function(it) { - var i=0, k, n, l; + var i=0, k; switch(typeof it) { case "object": this.limbs = it.limbs.slice(0); @@ -328,7 +328,7 @@ sjcl.bn.prototype = { carry = (l-m)*ipv; } if (carry === -1) { - limbs[i-1] -= this.placeVal; + limbs[i-1] -= pv; } return this; }, @@ -370,7 +370,9 @@ sjcl.bn.prototype = { } }; -/** @this { sjcl.bn } */ +/** @memberOf sjcl.bn +* @this { sjcl.bn } +*/ 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; @@ -394,7 +396,9 @@ sjcl.bn.prototype.radixMask = (1 << sjcl.bn.prototype.radix) - 1; * 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) { - /** @constructor */ + /** @constructor + * @private + */ function p(it) { this.initWith(it); /*if (this.limbs[this.modOffset]) { @@ -427,10 +431,11 @@ sjcl.bn.pseudoMersennePrime = function(exponent, coeff) { ppr.modulus.cnormalize(); /** Approximate reduction mod p. May leave a number which is negative or slightly larger than p. - * @this {sjcl.bn} + * @memberof sjcl.bn + * @this { sjcl.bn } */ 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; + var i, k, l, mo = this.modOffset, limbs = this.limbs, off = this.offset, ol = this.offset.length, fac = this.factor, ll; i = this.minOffset; while (limbs.length > mo) { @@ -452,7 +457,9 @@ sjcl.bn.pseudoMersennePrime = function(exponent, coeff) { return this; }; - /** @this {sjcl.bn} */ + /** @memberof sjcl.bn + * @this { sjcl.bn } + */ ppr._strongReduce = (ppr.fullMask === -1) ? ppr.reduce : function() { var limbs = this.limbs, i = limbs.length - 1, k, l; this.reduce(); @@ -467,7 +474,8 @@ sjcl.bn.pseudoMersennePrime = function(exponent, coeff) { }; /** mostly constant-time, very expensive full reduction. - * @this {sjcl.bn} + * @memberof sjcl.bn + * @this { sjcl.bn } */ ppr.fullReduce = function() { var greater, i; @@ -501,7 +509,9 @@ sjcl.bn.pseudoMersennePrime = function(exponent, coeff) { }; - /** @this {sjcl.bn} */ + /** @memberof sjcl.bn + * @this { sjcl.bn } + */ ppr.inverse = function() { return (this.power(this.modulus.sub(2))); }; @@ -512,18 +522,24 @@ sjcl.bn.pseudoMersennePrime = function(exponent, coeff) { }; // a small Mersenne prime +var sbp = sjcl.bn.pseudoMersennePrime; sjcl.bn.prime = { - p127: sjcl.bn.pseudoMersennePrime(127, [[0,-1]]), + p127: sbp(127, [[0,-1]]), // Bernstein's prime for Curve25519 - p25519: sjcl.bn.pseudoMersennePrime(255, [[0,-19]]), + p25519: sbp(255, [[0,-19]]), + + // Koblitz primes + p192k: sbp(192, [[32,-1],[12,-1],[8,-1],[7,-1],[6,-1],[3,-1],[0,-1]]), + p224k: sbp(224, [[32,-1],[12,-1],[11,-1],[9,-1],[7,-1],[4,-1],[1,-1],[0,-1]]), + p256k: sbp(256, [[32,-1],[9,-1],[8,-1],[7,-1],[6,-1],[4,-1],[0,-1]]), // NIST primes - p192: sjcl.bn.pseudoMersennePrime(192, [[0,-1],[64,-1]]), - p224: sjcl.bn.pseudoMersennePrime(224, [[0,1],[96,-1]]), - p256: sjcl.bn.pseudoMersennePrime(256, [[0,-1],[96,1],[192,1],[224,-1]]), - p384: sjcl.bn.pseudoMersennePrime(384, [[0,-1],[32,1],[96,-1],[128,-1]]), - p521: sjcl.bn.pseudoMersennePrime(521, [[0,-1]]) + p192: sbp(192, [[0,-1],[64,-1]]), + p224: sbp(224, [[0,1],[96,-1]]), + p256: sbp(256, [[0,-1],[96,1],[192,1],[224,-1]]), + p384: sbp(384, [[0,-1],[32,1],[96,-1],[128,-1]]), + p521: sbp(521, [[0,-1]]) }; sjcl.bn.random = function(modulus, paranoia) { diff --git a/src/js/sjcl/core/cbc.js b/src/js/sjcl/core/cbc.js index 9a98ed8f..39026cd8 100644 --- a/src/js/sjcl/core/cbc.js +++ b/src/js/sjcl/core/cbc.js @@ -5,18 +5,18 @@ * @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() { + /** @namespace + * Dangerous: CBC mode with PKCS#5 padding. + * + * @author Emily Stark + * @author Mike Hamburg + * @author Dan Boneh + */ sjcl.mode.cbc = { /** The name of the mode. * @constant @@ -100,7 +100,7 @@ sjcl.beware["CBC mode is dangerous because it doesn't protect message integrity. /* check and remove the pad */ bi = output[i-1] & 255; - if (bi == 0 || bi > 16) { + if (bi === 0 || bi > 16) { throw new sjcl.exception.corrupt("pkcs#5 padding corrupt"); } bo = bi * 0x1010101; diff --git a/src/js/sjcl/core/ccm.js b/src/js/sjcl/core/ccm.js index 8a32c5ae..273f0b06 100644 --- a/src/js/sjcl/core/ccm.js +++ b/src/js/sjcl/core/ccm.js @@ -25,7 +25,7 @@ sjcl.mode.ccm = { * @return {bitArray} The encrypted data, an array of bytes. */ encrypt: function(prf, plaintext, iv, adata, tlen) { - var L, i, out = plaintext.slice(0), tag, w=sjcl.bitArray, ivl = w.bitLength(iv) / 8, ol = w.bitLength(out) / 8; + var L, out = plaintext.slice(0), tag, w=sjcl.bitArray, ivl = w.bitLength(iv) / 8, ol = w.bitLength(out) / 8; tlen = tlen || 64; adata = adata || []; @@ -59,7 +59,7 @@ sjcl.mode.ccm = { decrypt: function(prf, ciphertext, iv, adata, tlen) { tlen = tlen || 64; adata = adata || []; - var L, i, + var L, w=sjcl.bitArray, ivl = w.bitLength(iv) / 8, ol = w.bitLength(ciphertext), @@ -101,7 +101,7 @@ sjcl.mode.ccm = { */ _computeTag: function(prf, plaintext, iv, adata, tlen, L) { // compute B[0] - var q, mac, field = 0, offset = 24, tmp, i, macData = [], w=sjcl.bitArray, xor = w._xor4; + var mac, tmp, i, macData = [], w=sjcl.bitArray, xor = w._xor4; tlen /= 8; @@ -161,7 +161,7 @@ sjcl.mode.ccm = { * @private */ _ctrMode: function(prf, data, iv, tag, tlen, L) { - var enc, i, w=sjcl.bitArray, xor = w._xor4, ctr, b, l = data.length, bl=w.bitLength(data); + var enc, i, w=sjcl.bitArray, xor = w._xor4, ctr, l = data.length, bl=w.bitLength(data); // start the ctr ctr = w.concat([w.partial(8,L-1)],iv).concat([0,0,0]).slice(0,4); diff --git a/src/js/sjcl/core/codecBase32.js b/src/js/sjcl/core/codecBase32.js new file mode 100644 index 00000000..9120bb1c --- /dev/null +++ b/src/js/sjcl/core/codecBase32.js @@ -0,0 +1,64 @@ +/** @fileOverview Bit array codec implementations. + * + * @author Nils Kenneweg + */ + +/** @namespace Base32 encoding/decoding */ +sjcl.codec.base32 = { + /** The base32 alphabet. + * @private + */ + _chars: "0123456789abcdefghjkmnpqrstvwxyz", + + /* bits in an array */ + BITS: 32, + /* base to encode at (2^x) */ + BASE: 5, + /* bits - base */ + REMAINING: 27, + + /** Convert from a bitArray to a base32 string. */ + fromBits: function (arr, _noEquals) { + var BITS = sjcl.codec.base32.BITS, BASE = sjcl.codec.base32.BASE, REMAINING = sjcl.codec.base32.REMAINING; + var out = "", i, bits=0, c = sjcl.codec.base32._chars, ta=0, bl = sjcl.bitArray.bitLength(arr); + + for (i=0; out.length * BASE <= bl; ) { + out += c.charAt((ta ^ arr[i]>>>bits) >>> REMAINING); + if (bits < BASE) { + ta = arr[i] << (BASE-bits); + bits += REMAINING; + i++; + } else { + ta <<= BASE; + bits -= BASE; + } + } + + return out; + }, + + /** Convert from a base32 string to a bitArray */ + toBits: function(str) { + var BITS = sjcl.codec.base32.BITS, BASE = sjcl.codec.base32.BASE, REMAINING = sjcl.codec.base32.REMAINING; + var out = [], i, bits=0, c = sjcl.codec.base32._chars, ta=0, x; + + for (i=0; i REMAINING) { + bits -= REMAINING; + out.push(ta ^ x>>>bits); + ta = x << (BITS-bits); + } else { + bits += BASE; + ta ^= x << (BITS-bits); + } + } + if (bits&56) { + out.push(sjcl.bitArray.partial(bits&56, ta, 1)); + } + return out; + } +}; diff --git a/src/js/sjcl/core/codecBase64.js b/src/js/sjcl/core/codecBase64.js index 33b2b7a0..f5180836 100644 --- a/src/js/sjcl/core/codecBase64.js +++ b/src/js/sjcl/core/codecBase64.js @@ -15,7 +15,9 @@ sjcl.codec.base64 = { /** Convert from a bitArray to a base64 string. */ fromBits: function (arr, _noEquals, _url) { var out = "", i, bits=0, c = sjcl.codec.base64._chars, ta=0, bl = sjcl.bitArray.bitLength(arr); - if (_url) c = c.substr(0,62) + '-_'; + if (_url) { + c = c.substr(0,62) + '-_'; + } for (i=0; out.length * 6 < bl; ) { out += c.charAt((ta ^ arr[i]>>>bits) >>> 26); if (bits < 6) { @@ -35,7 +37,9 @@ sjcl.codec.base64 = { toBits: function(str, _url) { str = str.replace(/\s|=/g,''); var out = [], i, bits=0, c = sjcl.codec.base64._chars, ta=0, x; - if (_url) c = c.substr(0,62) + '-_'; + if (_url) { + c = c.substr(0,62) + '-_'; + } for (i=0; i 4)) { throw new sjcl.exception.invalid("json encrypt: invalid parameters"); } - + if (typeof password === "string") { tmp = sjcl.misc.cachedPbkdf2(password, p); password = tmp.key.slice(0,p.ks/32); @@ -58,39 +58,52 @@ adata = sjcl.codec.utf8String.toBits(adata); } prp = new sjcl.cipher[p.cipher](password); - + /* return the json data */ j._add(rp, p); rp.key = password; - + /* do the encryption */ p.ct = sjcl.mode[p.mode].encrypt(prp, plaintext, p.iv, adata, p.ts); - + //return j.encode(j._subtract(p, j.defaults)); + return p; + }, + + /** Simple encryption function. + * @param {String|bitArray} password The password or key. + * @param {String} plaintext The data to encrypt. + * @param {Object} [params] The parameters including tag, iv and salt. + * @param {Object} [rp] A returned version with filled-in parameters. + * @return {String} The ciphertext serialized data. + * @throws {sjcl.exception.invalid} if a parameter is invalid. + */ + encrypt: function (password, plaintext, params, rp) { + var j = sjcl.json, p = j._encrypt.apply(j, arguments); return j.encode(p); }, - + /** Simple decryption function. * @param {String|bitArray} password The password or key. - * @param {String} ciphertext The ciphertext to decrypt. + * @param {Object} ciphertext The cipher raw data to decrypt. * @param {Object} [params] Additional non-default parameters. * @param {Object} [rp] A returned object with filled parameters. * @return {String} The plaintext. * @throws {sjcl.exception.invalid} if a parameter is invalid. * @throws {sjcl.exception.corrupt} if the ciphertext is corrupt. */ - decrypt: function (password, ciphertext, params, rp) { + _decrypt: function (password, ciphertext, params, rp) { params = params || {}; rp = rp || {}; - - var j = sjcl.json, p = j._add(j._add(j._add({},j.defaults),j.decode(ciphertext)), params, true), ct, tmp, prp, adata=p.adata; + + var j = sjcl.json, p = j._add(j._add(j._add({},j.defaults),ciphertext), params, true), ct, tmp, prp, adata=p.adata; if (typeof p.salt === "string") { p.salt = sjcl.codec.base64.toBits(p.salt); } if (typeof p.iv === "string") { p.iv = sjcl.codec.base64.toBits(p.iv); } - + if (!sjcl.mode[p.mode] || !sjcl.cipher[p.cipher] || (typeof password === "string" && p.iter <= 100) || @@ -100,7 +113,7 @@ (p.iv.length < 2 || p.iv.length > 4)) { throw new sjcl.exception.invalid("json decrypt: invalid parameters"); } - + if (typeof password === "string") { tmp = sjcl.misc.cachedPbkdf2(password, p); password = tmp.key.slice(0,p.ks/32); @@ -112,15 +125,33 @@ adata = sjcl.codec.utf8String.toBits(adata); } prp = new sjcl.cipher[p.cipher](password); - + /* do the decryption */ ct = sjcl.mode[p.mode].decrypt(prp, p.ct, p.iv, adata, p.ts); - + /* return the json data */ j._add(rp, p); rp.key = password; - - return sjcl.codec.utf8String.fromBits(ct); + + if (params.raw === 1) { + return ct; + } else { + return sjcl.codec.utf8String.fromBits(ct); + } + }, + + /** Simple decryption function. + * @param {String|bitArray} password The password or key. + * @param {String} ciphertext The ciphertext to decrypt. + * @param {Object} [params] Additional non-default parameters. + * @param {Object} [rp] A returned object with filled parameters. + * @return {String} The plaintext. + * @throws {sjcl.exception.invalid} if a parameter is invalid. + * @throws {sjcl.exception.corrupt} if the ciphertext is corrupt. + */ + decrypt: function (password, ciphertext, params, rp) { + var j = sjcl.json; + return j._decrypt(password, j.decode(ciphertext), params, rp); }, /** Encode a flat structure into a JSON string. @@ -138,23 +169,23 @@ } out += comma + '"' + i + '":'; comma = ','; - + switch (typeof obj[i]) { - case 'number': - case 'boolean': - out += obj[i]; - break; - - case 'string': - out += '"' + escape(obj[i]) + '"'; - break; - - case 'object': - out += '"' + sjcl.codec.base64.fromBits(obj[i],0) + '"'; - break; - - default: - throw new sjcl.exception.bug("json encode: unsupported type"); + case 'number': + case 'boolean': + out += obj[i]; + break; + + case 'string': + out += '"' + escape(obj[i]) + '"'; + break; + + case 'object': + out += '"' + sjcl.codec.base64.fromBits(obj[i],0) + '"'; + break; + + default: + throw new sjcl.exception.bug("json encode: unsupported type"); } } } @@ -174,13 +205,15 @@ } var a = str.replace(/^\{|\}$/g, '').split(/,/), out={}, i, m; for (i=0; i this._curveBitLength) { - hash = sjcl.bitArray.clamp(hash, this._curveBitLength); - } - var R = this._curve.r, - l = R.bitLength(), - k = fixedKForTesting || sjcl.bn.random(R.sub(1), paranoia).add(1), - r = this._curve.G.mult(k).x.mod(R), - ss = sjcl.bn.fromBits(hash).add(r.mul(this._exponent)), - s = fakeLegacyVersion ? ss.inverseMod(R).mul(k).mod(R) - : ss.mul(k.inverseMod(R)).mod(R); - return sjcl.bitArray.concat(r.toBits(l), s.toBits(l)); - } +/** ecdsa keys */ +sjcl.ecc.ecdsa = { + /** generate keys + * @function + * @param curve + * @param {int} paranoia Paranoia for generation (default 6) + * @param {secretKey} sec secret Key to use. used to get the publicKey for ones secretKey + */ + generateKeys: sjcl.ecc.basicKey.generateKeys("ecdsa") }; +/** ecdsa publicKey. +* @constructor +* @augments sjcl.ecc.basicKey.publicKey +*/ +sjcl.ecc.ecdsa.publicKey = function (curve, point) { + sjcl.ecc.basicKey.publicKey.apply(this, arguments); +}; + +/** specific functions for ecdsa publicKey. */ sjcl.ecc.ecdsa.publicKey.prototype = { + /** Diffie-Hellmann function + * @param {bitArray} hash hash to verify. + * @param {bitArray} rs signature bitArray. + * @param {boolean} fakeLegacyVersion use old legacy version + */ verify: function(hash, rs, fakeLegacyVersion) { if (sjcl.bitArray.bitLength(hash) > this._curveBitLength) { hash = sjcl.bitArray.clamp(hash, this._curveBitLength); @@ -418,3 +511,33 @@ sjcl.ecc.ecdsa.publicKey.prototype = { return true; } }; + +/** ecdsa secretKey +* @constructor +* @augments sjcl.ecc.basicKey.publicKey +*/ +sjcl.ecc.ecdsa.secretKey = function (curve, exponent) { + sjcl.ecc.basicKey.secretKey.apply(this, arguments); +}; + +/** specific functions for ecdsa secretKey. */ +sjcl.ecc.ecdsa.secretKey.prototype = { + /** Diffie-Hellmann function + * @param {bitArray} hash hash to sign. + * @param {int} paranoia paranoia for random number generation + * @param {boolean} fakeLegacyVersion use old legacy version + */ + sign: function(hash, paranoia, fakeLegacyVersion, fixedKForTesting) { + if (sjcl.bitArray.bitLength(hash) > this._curveBitLength) { + hash = sjcl.bitArray.clamp(hash, this._curveBitLength); + } + var R = this._curve.r, + l = R.bitLength(), + k = fixedKForTesting || sjcl.bn.random(R.sub(1), paranoia).add(1), + r = this._curve.G.mult(k).x.mod(R), + ss = sjcl.bn.fromBits(hash).add(r.mul(this._exponent)), + s = fakeLegacyVersion ? ss.inverseMod(R).mul(k).mod(R) + : ss.mul(k.inverseMod(R)).mod(R); + return sjcl.bitArray.concat(r.toBits(l), s.toBits(l)); + } +}; diff --git a/src/js/sjcl/core/gcm.js b/src/js/sjcl/core/gcm.js index b39cb6a6..61bf59d4 100644 --- a/src/js/sjcl/core/gcm.js +++ b/src/js/sjcl/core/gcm.js @@ -120,7 +120,7 @@ sjcl.mode.gcm = { * @param {Number} tlen The length of the tag, in bits. */ _ctrMode: function(encrypt, prf, data, adata, iv, tlen) { - var H, J0, S0, enc, i, ctr, tag, last, l, bl, abl, ivbl, w=sjcl.bitArray, xor=w._xor4; + var H, J0, S0, enc, i, ctr, tag, last, l, bl, abl, ivbl, w=sjcl.bitArray; // Calculate data lengths l = data.length; diff --git a/src/js/sjcl/core/hmac.js b/src/js/sjcl/core/hmac.js index 59dea191..84f9a15f 100644 --- a/src/js/sjcl/core/hmac.js +++ b/src/js/sjcl/core/hmac.js @@ -27,13 +27,35 @@ sjcl.misc.hmac = function (key, Hash) { this._baseHash[0].update(exKey[0]); this._baseHash[1].update(exKey[1]); + this._resultHash = new Hash(this._baseHash[0]); }; /** HMAC with the specified hash function. Also called encrypt since it's a prf. * @param {bitArray|String} data The data to mac. */ sjcl.misc.hmac.prototype.encrypt = sjcl.misc.hmac.prototype.mac = function (data) { - var w = new (this._hash)(this._baseHash[0]).update(data).finalize(); - return new (this._hash)(this._baseHash[1]).update(w).finalize(); + if (!this._updated) { + this.update(data); + return this.digest(data); + } else { + throw new sjcl.exception.invalid("encrypt on already updated hmac called!"); + } }; +sjcl.misc.hmac.prototype.reset = function () { + this._resultHash = new this._hash(this._baseHash[0]); + this._updated = false; +}; + +sjcl.misc.hmac.prototype.update = function (data) { + this._updated = true; + this._resultHash.update(data); +}; + +sjcl.misc.hmac.prototype.digest = function () { + var w = this._resultHash.finalize(), result = new (this._hash)(this._baseHash[1]).update(w).finalize(); + + this.reset(); + + return result; +}; \ No newline at end of file diff --git a/src/js/sjcl/core/pbkdf2.js b/src/js/sjcl/core/pbkdf2.js index 869e4dfa..3e9aa3f6 100644 --- a/src/js/sjcl/core/pbkdf2.js +++ b/src/js/sjcl/core/pbkdf2.js @@ -12,7 +12,7 @@ * This is the method specified by RSA's PKCS #5 standard. * * @param {bitArray|String} password The password. - * @param {bitArray} salt The salt. Should have lots of entropy. + * @param {bitArray|String} salt The salt. Should have lots of entropy. * @param {Number} [count=1000] The number of iterations. Higher numbers make the function slower but more secure. * @param {Number} [length] The length of the derived key. Defaults to the output size of the hash function. @@ -30,6 +30,10 @@ sjcl.misc.pbkdf2 = function (password, salt, count, length, Prff) { password = sjcl.codec.utf8String.toBits(password); } + if (typeof salt === "string") { + salt = sjcl.codec.utf8String.toBits(salt); + } + Prff = Prff || sjcl.misc.hmac; var prf = new Prff(password), diff --git a/src/js/sjcl/core/random.js b/src/js/sjcl/core/random.js index e8de1446..fed0ebfe 100644 --- a/src/js/sjcl/core/random.js +++ b/src/js/sjcl/core/random.js @@ -3,12 +3,13 @@ * @author Emily Stark * @author Mike Hamburg * @author Dan Boneh + * @author Michael Brooks */ /** @constructor * @class Random number generator - * * @description + * Use sjcl.random as a singleton for this class! *

* This random number generator is a derivative of Ferguson and Schneier's * generator Fortuna. It collects entropy from various events into several @@ -74,10 +75,11 @@ sjcl.prng = function(defaultParanoia) { this._PARANOIA_LEVELS = [0,48,64,96,128,192,256,384,512,768,1024]; this._MILLISECONDS_PER_RESEED = 30000; this._BITS_PER_RESEED = 80; -} +}; sjcl.prng.prototype = { - /** Generate several random words, and return them in an array + /** Generate several random words, and return them in an array. + * A word consists of 32 bits (4 bytes) * @param {Number} nwords The number of words to generate. */ randomWords: function (nwords, paranoia) { @@ -102,7 +104,11 @@ sjcl.prng.prototype = { return out.slice(0,nwords); }, - setDefaultParanoia: function (paranoia) { + setDefaultParanoia: function (paranoia, allowZeroParanoia) { + if (paranoia === 0 && allowZeroParanoia !== "Setting paranoia=0 will ruin your security; use it only for testing") { + throw "Setting paranoia=0 will ruin your security; use it only for testing"; + } + this._defaultParanoia = paranoia; }, @@ -119,7 +125,7 @@ sjcl.prng.prototype = { i, tmp, t = (new Date()).valueOf(), robin = this._robins[source], - oldReady = this.isReady(), err = 0; + oldReady = this.isReady(), err = 0, objName; id = this._collectorIds[source]; if (id === undefined) { id = this._collectorIds[source] = this._collectorIdNext ++; } @@ -137,7 +143,7 @@ sjcl.prng.prototype = { break; case "object": - var objName = Object.prototype.toString.call(data); + objName = Object.prototype.toString.call(data); if (objName === "[object Uint32Array]") { tmp = []; for (i = 0; i < data.length; i++) { @@ -149,7 +155,7 @@ sjcl.prng.prototype = { err = 1; } for (i=0; i>> 0) < (chl >>> 0) ? 1 : 0); t1l += krl; t1h += krh + ((t1l >>> 0) < (krl >>> 0) ? 1 : 0); - t1l += wrl; + t1l = t1l + wrl|0; // FF32..FF34 perf issue https://bugzilla.mozilla.org/show_bug.cgi?id=1054972 t1h += wrh + ((t1l >>> 0) < (wrl >>> 0) ? 1 : 0); // t2 = sigma0 + maj diff --git a/src/js/sjcl/core/sjcl.js b/src/js/sjcl/core/sjcl.js index d2da8e9c..8c9425d8 100644 --- a/src/js/sjcl/core/sjcl.js +++ b/src/js/sjcl/core/sjcl.js @@ -10,7 +10,7 @@ "use strict"; /*jslint indent: 2, bitwise: false, nomen: false, plusplus: false, white: false, regexp: false */ -/*global document, window, escape, unescape */ +/*global document, window, escape, unescape, module, require, Uint32Array */ /** @namespace The Stanford Javascript Crypto Library, top-level namespace. */ var sjcl = { @@ -68,6 +68,11 @@ var sjcl = { } }; -if(typeof module != 'undefined' && module.exports){ +if(typeof module !== 'undefined' && module.exports){ module.exports = sjcl; } +if (typeof define === "function") { + define([], function () { + return sjcl; + }); +} diff --git a/src/js/sjcl/demo/index.html b/src/js/sjcl/demo/index.html index 68f78d5d..5c0890d4 100644 --- a/src/js/sjcl/demo/index.html +++ b/src/js/sjcl/demo/index.html @@ -36,7 +36,7 @@

Key Derivation

- + random
diff --git a/src/js/sjcl/package.json b/src/js/sjcl/package.json new file mode 100644 index 00000000..4fe50005 --- /dev/null +++ b/src/js/sjcl/package.json @@ -0,0 +1,16 @@ +{ + "name": "sjcl", + "version": "1.0.1", + "description": "Stanford Javascript Crypto Library", + "main": "sjcl.js", + "author": "bitwiseshiftleft", + "keywords": ["encryption", "high-level", "crypto"], + "repository" : { + "type": "git", + "url": "https://github.com/bitwiseshiftleft/sjcl.git" + }, + "scripts": { + "test": "make test" + }, + "engines": { "node": "*" } +} \ No newline at end of file diff --git a/src/js/sjcl/sjcl.js b/src/js/sjcl/sjcl.js index fc651054..3bdf43f6 100644 --- a/src/js/sjcl/sjcl.js +++ b/src/js/sjcl/sjcl.js @@ -1,48 +1,54 @@ "use strict";function q(a){throw a;}var t=void 0,u=!1;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"NOT READY: "+this.message};this.message=a}}}; -"undefined"!=typeof module&&module.exports&&(module.exports=sjcl); -sjcl.cipher.aes=function(a){this.j[0][0][0]||this.D();var b,c,d,e,f=this.j[0][4],g=this.j[1];b=a.length;var h=1;4!==b&&(6!==b&&8!==b)&&q(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(0===a%b||8===b&&4===a%b)c=f[c>>>24]<<24^f[c>>16&255]<<16^f[c>>8&255]<<8^f[c&255],0===a%b&&(c=c<<8^c>>>24^h<<24,h=h<<1^283*(h>>7));d[a]=d[a-b]^c}for(b=0;a;b++,a--)c=d[b&3?a:a-4],e[b]=4>=a||4>b?c:g[0][f[c>>>24]]^g[1][f[c>>16&255]]^g[2][f[c>>8&255]]^g[3][f[c& +"undefined"!==typeof module&&module.exports&&(module.exports=sjcl);"function"===typeof define&&define([],function(){return sjcl}); +sjcl.cipher.aes=function(a){this.k[0][0][0]||this.D();var b,c,d,e,f=this.k[0][4],g=this.k[1];b=a.length;var h=1;4!==b&&(6!==b&&8!==b)&&q(new sjcl.exception.invalid("invalid aes key size"));this.b=[d=a.slice(0),e=[]];for(a=b;a<4*b+28;a++){c=d[a-1];if(0===a%b||8===b&&4===a%b)c=f[c>>>24]<<24^f[c>>16&255]<<16^f[c>>8&255]<<8^f[c&255],0===a%b&&(c=c<<8^c>>>24^h<<24,h=h<<1^283*(h>>7));d[a]=d[a-b]^c}for(b=0;a;b++,a--)c=d[b&3?a:a-4],e[b]=4>=a||4>b?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 y(this,a,0)},decrypt:function(a){return y(this,a,1)},j:[[[],[],[],[],[]],[[],[],[],[],[]]],D:function(){var a=this.j[0],b=this.j[1],c=a[4],d=b[4],e,f,g,h=[],l=[],k,n,m,p;for(e=0;0x100>e;e++)l[(h[e]=e<<1^283*(e>>7))^e]=e;for(f=g=0;!c[f];f^=k||1,g=l[g]||1){m=g^g<<1^g<<2^g<<3^g<<4;m=m>>8^m&255^99;c[f]=m;d[m]=f;n=h[e=h[k=h[f]]];p=0x1010101*n^0x10001*e^0x101*k^0x1010100*f;n=0x101*h[m]^0x1010100*m;for(e=0;4>e;e++)a[e][f]=n=n<<24^n>>>8,b[e][m]=p=p<<24^p>>>8}for(e= +sjcl.cipher.aes.prototype={encrypt:function(a){return y(this,a,0)},decrypt:function(a){return y(this,a,1)},k:[[[],[],[],[],[]],[[],[],[],[],[]]],D:function(){var a=this.k[0],b=this.k[1],c=a[4],d=b[4],e,f,g,h=[],l=[],k,n,m,p;for(e=0;0x100>e;e++)l[(h[e]=e<<1^283*(e>>7))^e]=e;for(f=g=0;!c[f];f^=k||1,g=l[g]||1){m=g^g<<1^g<<2^g<<3^g<<4;m=m>>8^m&255^99;c[f]=m;d[m]=f;n=h[e=h[k=h[f]]];p=0x1010101*n^0x10001*e^0x101*k^0x1010100*f;n=0x101*h[m]^0x1010100*m;for(e=0;4>e;e++)a[e][f]=n=n<<24^n>>>8,b[e][m]=p=p<<24^p>>>8}for(e= 0;5>e;e++)a[e]=a[e].slice(0),b[e]=b[e].slice(0)}}; -function y(a,b,c){4!==b.length&&q(new sjcl.exception.invalid("invalid aes block size"));var d=a.a[c],e=b[0]^d[0],f=b[c?3:1]^d[1],g=b[2]^d[2];b=b[c?1:3]^d[3];var h,l,k,n=d.length/4-2,m,p=4,s=[0,0,0,0];h=a.j[c];a=h[0];var r=h[1],v=h[2],w=h[3],x=h[4];for(m=0;m>>24]^r[f>>16&255]^v[g>>8&255]^w[b&255]^d[p],l=a[f>>>24]^r[g>>16&255]^v[b>>8&255]^w[e&255]^d[p+1],k=a[g>>>24]^r[b>>16&255]^v[e>>8&255]^w[f&255]^d[p+2],b=a[b>>>24]^r[e>>16&255]^v[f>>8&255]^w[g&255]^d[p+3],p+=4,e=h,f=l,g=k;for(m=0;4> +function y(a,b,c){4!==b.length&&q(new sjcl.exception.invalid("invalid aes block size"));var d=a.b[c],e=b[0]^d[0],f=b[c?3:1]^d[1],g=b[2]^d[2];b=b[c?1:3]^d[3];var h,l,k,n=d.length/4-2,m,p=4,s=[0,0,0,0];h=a.k[c];a=h[0];var r=h[1],v=h[2],w=h[3],x=h[4];for(m=0;m>>24]^r[f>>16&255]^v[g>>8&255]^w[b&255]^d[p],l=a[f>>>24]^r[g>>16&255]^v[b>>8&255]^w[e&255]^d[p+1],k=a[g>>>24]^r[b>>16&255]^v[e>>8&255]^w[f&255]^d[p+2],b=a[b>>>24]^r[e>>16&255]^v[f>>8&255]^w[g&255]^d[p+3],p+=4,e=h,f=l,g=k;for(m=0;4> m;m++)s[c?3&-m:m]=x[e>>>24]<<24^x[f>>16&255]<<16^x[g>>8&255]<<8^x[b&255]^d[p++],h=e,e=f,f=g,g=b,b=h;return s} -sjcl.bitArray={bitSlice:function(a,b,c){a=sjcl.bitArray.O(a.slice(b/32),32-(b&31)).slice(1);return c===t?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<>>d:a[b/32|0]>>>d)&(1<>b-1,1));return a},partial:function(a,b,c){return 32===a?b:(c?b|0:b<<32-a)+0x10000000000*a},getPartial:function(a){return Math.round(a/0x10000000000)||32},equal:function(a,b){if(sjcl.bitArray.bitLength(a)!==sjcl.bitArray.bitLength(b))return u;var c=0,d;for(d=0;d>>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,32>>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,32>>24|c>>>8&0xff00|(c&0xff00)<<8|c<<24;return a}}; sjcl.codec.utf8String={fromBits:function(a){var b="",c=sjcl.bitArray.bitLength(a),d,e;for(d=0;d>>24),e<<=8;return decodeURIComponent(escape(b))},toBits:function(a){a=unescape(encodeURIComponent(a));var b=[],c,d=0;for(c=0;c>>e)>>>26),6>e?(g=a[c]<<6-e,e+=26,c++):(g<<=6,e-=6);for(;d.length&3&&!b;)d+="=";return d},toBits:function(a,b){a=a.replace(/\s|=/g,"");var c=[],d,e=0,f=sjcl.codec.base64.I,g=0,h;b&&(f=f.substr(0,62)+"-_");for(d=0;dh&&q(new sjcl.exception.invalid("this isn't base64!")),26>>e),g=h<<32-e):(e+=6,g^=h<<32-e);e&56&&c.push(sjcl.bitArray.partial(e&56,g,1));return c}};sjcl.codec.base64url={fromBits:function(a){return sjcl.codec.base64.fromBits(a,1,1)},toBits:function(a){return sjcl.codec.base64.toBits(a,1)}};sjcl.hash.sha256=function(a){this.a[0]||this.D();a?(this.q=a.q.slice(0),this.m=a.m.slice(0),this.g=a.g):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.q=this.M.slice(0);this.m=[];this.g=0;return this},update:function(a){"string"===typeof a&&(a=sjcl.codec.utf8String.toBits(a));var b,c=this.m=sjcl.bitArray.concat(this.m,a);b=this.g;a=this.g=b+sjcl.bitArray.bitLength(a);for(b=512+b&-512;b<=a;b+=512)z(this,c.splice(0,16));return this},finalize:function(){var a,b=this.m,c=this.q,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.g/ -4294967296));for(b.push(this.g|0);b.length;)z(this,b.splice(0,16));this.reset();return c},M:[],a:[],D:function(){function a(a){return 0x100000000*(a-Math.floor(a))|0}var b=0,c=2,d;a:for(;64>b;c++){for(d=2;d*d<=c;d++)if(0===c%d)continue a;8>b&&(this.M[b]=a(Math.pow(c,0.5)));this.a[b]=a(Math.pow(c,1/3));b++}}}; -function z(a,b){var c,d,e,f=b.slice(0),g=a.q,h=a.a,l=g[0],k=g[1],n=g[2],m=g[3],p=g[4],s=g[5],r=g[6],v=g[7];for(c=0;64>c;c++)16>c?d=f[c]:(d=f[c+1&15],e=f[c+14&15],d=f[c&15]=(d>>>7^d>>>18^d>>>3^d<<25^d<<14)+(e>>>17^e>>>19^e>>>10^e<<15^e<<13)+f[c&15]+f[c+9&15]|0),d=d+v+(p>>>6^p>>>11^p>>>25^p<<26^p<<21^p<<7)+(r^p&(s^r))+h[c],v=r,r=s,s=p,p=m+d|0,m=n,n=k,k=l,l=d+(k&n^m&(k^n))+(k>>>2^k>>>13^k>>>22^k<<30^k<<19^k<<10)|0;g[0]=g[0]+l|0;g[1]=g[1]+k|0;g[2]=g[2]+n|0;g[3]=g[3]+m|0;g[4]=g[4]+p|0;g[5]=g[5]+s|0;g[6]= +sjcl.codec.base64={J:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",fromBits:function(a,b,c){var d="",e=0,f=sjcl.codec.base64.J,g=0,h=sjcl.bitArray.bitLength(a);c&&(f=f.substr(0,62)+"-_");for(c=0;6*d.length>>e)>>>26),6>e?(g=a[c]<<6-e,e+=26,c++):(g<<=6,e-=6);for(;d.length&3&&!b;)d+="=";return d},toBits:function(a,b){a=a.replace(/\s|=/g,"");var c=[],d,e=0,f=sjcl.codec.base64.J,g=0,h;b&&(f=f.substr(0,62)+"-_");for(d=0;dh&&q(new sjcl.exception.invalid("this isn't base64!")),26>>e),g=h<<32-e):(e+=6,g^=h<<32-e);e&56&&c.push(sjcl.bitArray.partial(e&56,g,1));return c}};sjcl.codec.base64url={fromBits:function(a){return sjcl.codec.base64.fromBits(a,1,1)},toBits:function(a){return sjcl.codec.base64.toBits(a,1)}};sjcl.hash.sha256=function(a){this.b[0]||this.D();a?(this.r=a.r.slice(0),this.o=a.o.slice(0),this.h=a.h):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.r=this.N.slice(0);this.o=[];this.h=0;return this},update:function(a){"string"===typeof a&&(a=sjcl.codec.utf8String.toBits(a));var b,c=this.o=sjcl.bitArray.concat(this.o,a);b=this.h;a=this.h=b+sjcl.bitArray.bitLength(a);for(b=512+b&-512;b<=a;b+=512)z(this,c.splice(0,16));return this},finalize:function(){var a,b=this.o,c=this.r,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.h/ +4294967296));for(b.push(this.h|0);b.length;)z(this,b.splice(0,16));this.reset();return c},N:[],b:[],D:function(){function a(a){return 0x100000000*(a-Math.floor(a))|0}var b=0,c=2,d;a:for(;64>b;c++){for(d=2;d*d<=c;d++)if(0===c%d)continue a;8>b&&(this.N[b]=a(Math.pow(c,0.5)));this.b[b]=a(Math.pow(c,1/3));b++}}}; +function z(a,b){var c,d,e,f=b.slice(0),g=a.r,h=a.b,l=g[0],k=g[1],n=g[2],m=g[3],p=g[4],s=g[5],r=g[6],v=g[7];for(c=0;64>c;c++)16>c?d=f[c]:(d=f[c+1&15],e=f[c+14&15],d=f[c&15]=(d>>>7^d>>>18^d>>>3^d<<25^d<<14)+(e>>>17^e>>>19^e>>>10^e<<15^e<<13)+f[c&15]+f[c+9&15]|0),d=d+v+(p>>>6^p>>>11^p>>>25^p<<26^p<<21^p<<7)+(r^p&(s^r))+h[c],v=r,r=s,s=p,p=m+d|0,m=n,n=k,k=l,l=d+(k&n^m&(k^n))+(k>>>2^k>>>13^k>>>22^k<<30^k<<19^k<<10)|0;g[0]=g[0]+l|0;g[1]=g[1]+k|0;g[2]=g[2]+n|0;g[3]=g[3]+m|0;g[4]=g[4]+p|0;g[5]=g[5]+s|0;g[6]= g[6]+r|0;g[7]=g[7]+v|0} -sjcl.mode.ccm={name:"ccm",encrypt:function(a,b,c,d,e){var f,g=b.slice(0),h=sjcl.bitArray,l=h.bitLength(c)/8,k=h.bitLength(g)/8;e=e||64;d=d||[];7>l&&q(new sjcl.exception.invalid("ccm: iv must be at least 7 bytes"));for(f=2;4>f&&k>>>8*f;f++);f<15-l&&(f=15-l);c=h.clamp(c,8*(15-f));b=sjcl.mode.ccm.K(a,b,c,d,e,f);g=sjcl.mode.ccm.n(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),l=f.clamp(b,h-e),k=f.bitSlice(b, -h-e),h=(h-e)/8;7>g&&q(new sjcl.exception.invalid("ccm: iv must be at least 7 bytes"));for(b=2;4>b&&h>>>8*b;b++);b<15-g&&(b=15-g);c=f.clamp(c,8*(15-b));l=sjcl.mode.ccm.n(a,l,c,k,e,b);a=sjcl.mode.ccm.K(a,l.data,c,d,e,b);f.equal(l.tag,a)||q(new sjcl.exception.corrupt("ccm: tag doesn't match"));return l.data},K:function(a,b,c,d,e,f){var g=[],h=sjcl.bitArray,l=h.k;e/=8;(e%2||4>e||16=c?g=[h.partial(16,c)]:0xffffffff>=c&&(g=h.concat([h.partial(16,65534)],[c]));g=h.concat(g,d);for(d=0;dl&&q(new sjcl.exception.invalid("ccm: iv must be at least 7 bytes"));for(f=2;4>f&&k>>>8*f;f++);f<15-l&&(f=15-l);c=h.clamp(c,8*(15-f));b=sjcl.mode.ccm.L(a,b,c,d,e,f);g=sjcl.mode.ccm.p(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),l=f.clamp(b,h-e),k=f.bitSlice(b, +h-e),h=(h-e)/8;7>g&&q(new sjcl.exception.invalid("ccm: iv must be at least 7 bytes"));for(b=2;4>b&&h>>>8*b;b++);b<15-g&&(b=15-g);c=f.clamp(c,8*(15-b));l=sjcl.mode.ccm.p(a,l,c,k,e,b);a=sjcl.mode.ccm.L(a,l.data,c,d,e,b);f.equal(l.tag,a)||q(new sjcl.exception.corrupt("ccm: tag doesn't match"));return l.data},L:function(a,b,c,d,e,f){var g=[],h=sjcl.bitArray,l=h.l;e/=8;(e%2||4>e||16=c?g=[h.partial(16,c)]:0xffffffff>=c&&(g=h.concat([h.partial(16,65534)],[c]));g=h.concat(g,d);for(d=0;de.bitLength(c)&&(h=f(h,d(h)),c=e.concat(c,[-2147483648,0,0,0]));g=f(g,c);return a.encrypt(f(d(f(h, -d(h))),g))},G:function(a){return[a[0]<<1^a[1]>>>31,a[1]<<1^a[2]>>>31,a[2]<<1^a[3]>>>31,a[3]<<1^135*(a[0]>>>31)]}}; -sjcl.mode.gcm={name:"gcm",encrypt:function(a,b,c,d,e){var f=b.slice(0);b=sjcl.bitArray;d=d||[];a=sjcl.mode.gcm.n(!0,a,f,d,c,e||128);return b.concat(a.data,a.tag)},decrypt:function(a,b,c,d,e){var f=b.slice(0),g=sjcl.bitArray,h=g.bitLength(f);e=e||128;d=d||[];e<=h?(b=g.bitSlice(f,h-e),f=g.bitSlice(f,0,h-e)):(b=f,f=[]);a=sjcl.mode.gcm.n(u,a,f,d,c,e);g.equal(a.tag,b)||q(new sjcl.exception.corrupt("gcm: tag doesn't match"));return a.data},U:function(a,b){var c,d,e,f,g,h=sjcl.bitArray.k;e=[0,0,0,0];f=b.slice(0); -for(c=0;128>c;c++){(d=0!==(a[Math.floor(c/32)]&1<<31-c%32))&&(e=h(e,f));g=0!==(f[3]&1);for(d=3;0>>1|(f[d-1]&1)<<31;f[0]>>>=1;g&&(f[0]^=-0x1f000000)}return e},f:function(a,b,c){var d,e=c.length;b=b.slice(0);for(d=0;de&&(a=b.hash(a));for(d=0;dd||0>c)&&q(sjcl.exception.invalid("invalid params to pbkdf2"));"string"===typeof a&&(a=sjcl.codec.utf8String.toBits(a));e=e||sjcl.misc.hmac;a=new e(a);var f,g,h,l,k=[],n=sjcl.bitArray;for(l=1;32*k.length<(d||1);l++){e=f=a.encrypt(n.concat(b,[l]));for(g=1;gg;g++)e.push(0x100000000*Math.random()|0);for(g=0;g=1<this.i&&(this.i=f);this.F++; -this.a=sjcl.hash.sha256.hash(this.a.concat(e));this.A=new sjcl.cipher.aes(this.a);for(d=0;4>d&&!(this.e[d]=this.e[d]+1|0,this.e[d]);d++);}for(d=0;d>>=1;this.b[g].update([d,this.C++,2,b,f,a.length].concat(a))}break;case "string":b===t&&(b=a.length);this.b[g].update([d,this.C++,3,b,f,a.length]);this.b[g].update(a); -break;default:l=1}l&&q(new sjcl.exception.bug("random: addEntropy only supports number, array of numbers or string"));this.h[g]+=b;this.c+=b;h===this.l&&(this.isReady()!==this.l&&C("seeded",Math.max(this.i,this.c)),C("progress",this.getProgress()))},isReady:function(a){a=this.H[a!==t?a:this.B];return this.i&&this.i>=a?this.h[0]>this.P&&(new Date).valueOf()>this.N?this.w|this.u:this.u:this.c>=a?this.w|this.l:this.l},getProgress:function(a){a=this.H[a?a:this.B];return this.i>=a?1:this.c>a?1:this.c/ -a},startCollectors:function(){this.p||(window.addEventListener?(window.addEventListener("load",this.r,u),window.addEventListener("mousemove",this.s,u)):document.attachEvent?(document.attachEvent("onload",this.r),document.attachEvent("onmousemove",this.s)):q(new sjcl.exception.bug("can't attach event")),this.p=!0)},stopCollectors:function(){this.p&&(window.removeEventListener?(window.removeEventListener("load",this.r,u),window.removeEventListener("mousemove",this.s,u)):window.detachEvent&&(window.detachEvent("onload", -this.r),window.detachEvent("onmousemove",this.s)),this.p=u)},addEventListener:function(a,b){this.z[a][this.S++]=b},removeEventListener:function(a,b){var c,d,e=this.z[a],f=[];for(d in e)e.hasOwnProperty(d)&&e[d]===b&&f.push(d);for(c=0;cb&&!(a.e[b]=a.e[b]+1|0,a.e[b]);b++);return a.A.encrypt(a.e)}sjcl.random=new sjcl.prng(6);try{var D=new Uint32Array(32);crypto.getRandomValues(D);sjcl.random.addEntropy(D,1024,"crypto['getRandomValues']")}catch(E){} -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.d({iv:sjcl.random.randomWords(4,0)},e.defaults),g;e.d(f,c);c=f.adata;"string"===typeof f.salt&&(f.salt=sjcl.codec.base64.toBits(f.salt));"string"===typeof f.iv&&(f.iv=sjcl.codec.base64.toBits(f.iv));(!sjcl.mode[f.mode]||!sjcl.cipher[f.cipher]||"string"===typeof a&&100>=f.iter||64!==f.ts&&96!==f.ts&&128!==f.ts||128!==f.ks&&192!==f.ks&&0x100!==f.ks||2>f.iv.length|| -4=b.iter||64!==b.ts&&96!==b.ts&&128!==b.ts||128!==b.ks&&192!==b.ks&&0x100!==b.ks||!b.iv||2>b.iv.length||4e.bitLength(c)&&(h=f(h,d(h)),c=e.concat(c,[-2147483648,0,0,0]));g=f(g,c);return a.encrypt(f(d(f(h, +d(h))),g))},H:function(a){return[a[0]<<1^a[1]>>>31,a[1]<<1^a[2]>>>31,a[2]<<1^a[3]>>>31,a[3]<<1^135*(a[0]>>>31)]}}; +sjcl.mode.gcm={name:"gcm",encrypt:function(a,b,c,d,e){var f=b.slice(0);b=sjcl.bitArray;d=d||[];a=sjcl.mode.gcm.p(!0,a,f,d,c,e||128);return b.concat(a.data,a.tag)},decrypt:function(a,b,c,d,e){var f=b.slice(0),g=sjcl.bitArray,h=g.bitLength(f);e=e||128;d=d||[];e<=h?(b=g.bitSlice(f,h-e),f=g.bitSlice(f,0,h-e)):(b=f,f=[]);a=sjcl.mode.gcm.p(u,a,f,d,c,e);g.equal(a.tag,b)||q(new sjcl.exception.corrupt("gcm: tag doesn't match"));return a.data},Z:function(a,b){var c,d,e,f,g,h=sjcl.bitArray.l;e=[0,0,0,0];f=b.slice(0); +for(c=0;128>c;c++){(d=0!==(a[Math.floor(c/32)]&1<<31-c%32))&&(e=h(e,f));g=0!==(f[3]&1);for(d=3;0>>1|(f[d-1]&1)<<31;f[0]>>>=1;g&&(f[0]^=-0x1f000000)}return e},g:function(a,b,c){var d,e=c.length;b=b.slice(0);for(d=0;de&&(a=b.hash(a));for(d=0;dd||0>c)&&q(sjcl.exception.invalid("invalid params to pbkdf2"));"string"===typeof a&&(a=sjcl.codec.utf8String.toBits(a));"string"===typeof b&&(b=sjcl.codec.utf8String.toBits(b));e=e||sjcl.misc.hmac;a=new e(a);var f,g,h,l,k=[],n=sjcl.bitArray;for(l=1;32*k.length<(d||1);l++){e=f=a.encrypt(n.concat(b,[l]));for(g=1;gg;g++)e.push(0x100000000*Math.random()|0);for(g=0;g=1<this.j&&(this.j=f);this.F++; +this.b=sjcl.hash.sha256.hash(this.b.concat(e));this.A=new sjcl.cipher.aes(this.b);for(d=0;4>d&&!(this.f[d]=this.f[d]+1|0,this.f[d]);d++);}for(d=0;d>>=1;this.c[g].update([d,this.C++,2,b,f,a.length].concat(a))}break;case "string":b===t&&(b=a.length);this.c[g].update([d,this.C++,3,b,f,a.length]);this.c[g].update(a);break;default:l=1}l&&q(new sjcl.exception.bug("random: addEntropy only supports number, array of numbers or string"));this.i[g]+=b;this.d+=b;h===this.m&&(this.isReady()!==this.m&&C("seeded",Math.max(this.j,this.d)),C("progress",this.getProgress()))},isReady:function(a){a=this.I[a!==t?a:this.B];return this.j&&this.j>=a?this.i[0]>this.R&& +(new Date).valueOf()>this.O?this.u|this.t:this.t:this.d>=a?this.u|this.m:this.m},getProgress:function(a){a=this.I[a?a:this.B];return this.j>=a?1:this.d>a?1:this.d/a},startCollectors:function(){this.q||(this.a={loadTimeCollector:D(this,this.aa),mouseCollector:D(this,this.ba),keyboardCollector:D(this,this.$),accelerometerCollector:D(this,this.U)},window.addEventListener?(window.addEventListener("load",this.a.loadTimeCollector,u),window.addEventListener("mousemove",this.a.mouseCollector,u),window.addEventListener("keypress", +this.a.keyboardCollector,u),window.addEventListener("devicemotion",this.a.accelerometerCollector,u)):document.attachEvent?(document.attachEvent("onload",this.a.loadTimeCollector),document.attachEvent("onmousemove",this.a.mouseCollector),document.attachEvent("keypress",this.a.keyboardCollector)):q(new sjcl.exception.bug("can't attach event")),this.q=!0)},stopCollectors:function(){this.q&&(window.removeEventListener?(window.removeEventListener("load",this.a.loadTimeCollector,u),window.removeEventListener("mousemove", +this.a.mouseCollector,u),window.removeEventListener("keypress",this.a.keyboardCollector,u),window.removeEventListener("devicemotion",this.a.accelerometerCollector,u)):document.detachEvent&&(document.detachEvent("onload",this.a.loadTimeCollector),document.detachEvent("onmousemove",this.a.mouseCollector),document.detachEvent("keypress",this.a.keyboardCollector)),this.q=u)},addEventListener:function(a,b){this.w[a][this.V++]=b},removeEventListener:function(a,b){var c,d,e=this.w[a],f=[];for(d in e)e.hasOwnProperty(d)&& +e[d]===b&&f.push(d);for(c=0;cb&&!(a.f[b]=a.f[b]+1|0,a.f[b]);b++);return a.A.encrypt(a.f)}function D(a,b){return function(){b.apply(a,arguments)}}sjcl.random=new sjcl.prng(6); +a:try{var F,G,H,I;if(I="undefined"!==typeof module){var J;if(J=module.exports){var K;try{K=require("crypto")}catch(L){K=null}J=(G=K)&&G.randomBytes}I=J}if(I)F=G.randomBytes(128),F=new Uint32Array((new Uint8Array(F)).buffer),sjcl.random.addEntropy(F,1024,"crypto['randomBytes']");else if("undefined"!==typeof window&&"undefined"!==typeof Uint32Array){H=new Uint32Array(32);if(window.crypto&&window.crypto.getRandomValues)window.crypto.getRandomValues(H);else if(window.msCrypto&&window.msCrypto.getRandomValues)window.msCrypto.getRandomValues(H); +else break a;sjcl.random.addEntropy(H,1024,"crypto['getRandomValues']")}}catch(M){"undefined"!==typeof window&&window.console&&(console.log("There was an error collecting entropy from the browser:"),console.log(M))} +sjcl.json={defaults:{v:1,iter:1E3,ks:128,ts:64,mode:"ccm",adata:"",cipher:"aes"},Y:function(a,b,c,d){c=c||{};d=d||{};var e=sjcl.json,f=e.e({iv:sjcl.random.randomWords(4,0)},e.defaults),g;e.e(f,c);c=f.adata;"string"===typeof f.salt&&(f.salt=sjcl.codec.base64.toBits(f.salt));"string"===typeof f.iv&&(f.iv=sjcl.codec.base64.toBits(f.iv));(!sjcl.mode[f.mode]||!sjcl.cipher[f.cipher]||"string"===typeof a&&100>=f.iter||64!==f.ts&&96!==f.ts&&128!==f.ts||128!==f.ks&&192!==f.ks&&0x100!==f.ks||2>f.iv.length||4< +f.iv.length)&&q(new sjcl.exception.invalid("json encrypt: invalid parameters"));"string"===typeof a?(g=sjcl.misc.cachedPbkdf2(a,f),a=g.key.slice(0,f.ks/32),f.salt=g.salt):sjcl.ecc&&a instanceof sjcl.ecc.elGamal.publicKey&&(g=a.kem(),f.kemtag=g.tag,a=g.key.slice(0,f.ks/32));"string"===typeof b&&(b=sjcl.codec.utf8String.toBits(b));"string"===typeof c&&(c=sjcl.codec.utf8String.toBits(c));g=new sjcl.cipher[f.cipher](a);e.e(d,f);d.key=a;f.ct=sjcl.mode[f.mode].encrypt(g,b,f.iv,c,f.ts);return f},encrypt:function(a, +b,c,d){var e=sjcl.json,f=e.Y.apply(e,arguments);return e.encode(f)},X:function(a,b,c,d){c=c||{};d=d||{};var e=sjcl.json;b=e.e(e.e(e.e({},e.defaults),b),c,!0);var f,g;f=b.adata;"string"===typeof b.salt&&(b.salt=sjcl.codec.base64.toBits(b.salt));"string"===typeof b.iv&&(b.iv=sjcl.codec.base64.toBits(b.iv));(!sjcl.mode[b.mode]||!sjcl.cipher[b.cipher]||"string"===typeof a&&100>=b.iter||64!==b.ts&&96!==b.ts&&128!==b.ts||128!==b.ks&&192!==b.ks&&0x100!==b.ks||!b.iv||2>b.iv.length||4>> (32 - tv[0].length)); // unsigned shift, convert to signed word + this.require(b === (tv[1]|0), t + "array entry shifted is number: " + word2hex(b) + " == " + word2hex(tv[1])); + } + + cb && cb(); + }); + + + new sjcl.test.TestCase("bitArray concat, slicing, shifting and clamping", function (cb) { + if (!sjcl.bitArray) { + this.unimplemented(); + cb && cb(); + return; + } + + var i, j, kat = sjcl.test.vector.bitArray.slices, tv, a, a1, b, bitlen, t; + for (i=0; i