From 49581200ca11dbca47c57675f0a036edaa8c185c Mon Sep 17 00:00:00 2001
From: Zaran
Date: Mon, 30 Jan 2012 15:05:38 -0800
Subject: Create javascriptmvc application. Remove files which are now tracked
in the submodules.
---
webclient/lib/sjcl.js | 1915 -------------------------------------------------
1 file changed, 1915 deletions(-)
delete mode 100644 webclient/lib/sjcl.js
(limited to 'webclient/lib/sjcl.js')
diff --git a/webclient/lib/sjcl.js b/webclient/lib/sjcl.js
deleted file mode 100644
index 9730862..0000000
--- a/webclient/lib/sjcl.js
+++ /dev/null
@@ -1,1915 +0,0 @@
-/** @fileOverview Javascript cryptography implementation.
- *
- * Crush to remove comments, shorten variable names and
- * generally reduce transmission size.
- *
- * @author Emily Stark
- * @author Mike Hamburg
- * @author Dan Boneh
- */
-
-"use strict";
-/*jslint indent: 2, bitwise: false, nomen: false, plusplus: false, white: false, regexp: false */
-/*global document, window, escape, unescape */
-
-/** @namespace The Stanford Javascript Crypto Library, top-level namespace. */
-var sjcl = {
- /** @namespace Symmetric ciphers. */
- cipher: {},
-
- /** @namespace Hash functions. Right now only SHA256 is implemented. */
- hash: {},
-
- /** @namespace Key exchange functions. Right now only SRP is implemented. */
- keyexchange: {},
-
- /** @namespace Block cipher modes of operation. */
- mode: {},
-
- /** @namespace Miscellaneous. HMAC and PBKDF2. */
- misc: {},
-
- /**
- * @namespace Bit array encoders and decoders.
- *
- * @description
- * The members of this namespace are functions which translate between
- * SJCL's bitArrays and other objects (usually strings). Because it
- * isn't always clear which direction is encoding and which is decoding,
- * the method names are "fromBits" and "toBits".
- */
- codec: {},
-
- /** @namespace Exceptions. */
- exception: {
- /** @class Ciphertext is corrupt. */
- corrupt: function(message) {
- this.toString = function() { return "CORRUPT: "+this.message; };
- this.message = message;
- },
-
- /** @class Invalid parameter. */
- invalid: function(message) {
- this.toString = function() { return "INVALID: "+this.message; };
- this.message = message;
- },
-
- /** @class Bug or missing feature in SJCL. */
- bug: function(message) {
- this.toString = function() { return "BUG: "+this.message; };
- this.message = message;
- },
-
- /** @class Something isn't ready. */
- notReady: function(message) {
- this.toString = function() { return "NOT READY: "+this.message; };
- this.message = message;
- }
- }
-};
-
-if(typeof module != 'undefined' && module.exports){
- module.exports = sjcl;
-}
-/** @fileOverview Low-level AES implementation.
- *
- * This file contains a low-level implementation of AES, optimized for
- * size and for efficiency on several browsers. It is based on
- * OpenSSL's aes_core.c, a public-domain implementation by Vincent
- * Rijmen, Antoon Bosselaers and Paulo Barreto.
- *
- * An older version of this implementation is available in the public
- * domain, but this one is (c) Emily Stark, Mike Hamburg, Dan Boneh,
- * Stanford University 2008-2010 and BSD-licensed for liability
- * reasons.
- *
- * @author Emily Stark
- * @author Mike Hamburg
- * @author Dan Boneh
- */
-
-/**
- * Schedule out an AES key for both encryption and decryption. This
- * is a low-level class. Use a cipher mode to do bulk encryption.
- *
- * @constructor
- * @param {Array} key The key as an array of 4, 6 or 8 words.
- *
- * @class Advanced Encryption Standard (low-level interface)
- */
-sjcl.cipher.aes = function (key) {
- if (!this._tables[0][0][0]) {
- this._precompute();
- }
-
- var i, j, tmp,
- encKey, decKey,
- sbox = this._tables[0][4], decTable = this._tables[1],
- keyLen = key.length, rcon = 1;
-
- if (keyLen !== 4 && keyLen !== 6 && keyLen !== 8) {
- throw new sjcl.exception.invalid("invalid aes key size");
- }
-
- this._key = [encKey = key.slice(0), decKey = []];
-
- // schedule encryption keys
- for (i = keyLen; i < 4 * keyLen + 28; i++) {
- tmp = encKey[i-1];
-
- // apply sbox
- if (i%keyLen === 0 || (keyLen === 8 && i%keyLen === 4)) {
- tmp = sbox[tmp>>>24]<<24 ^ sbox[tmp>>16&255]<<16 ^ sbox[tmp>>8&255]<<8 ^ sbox[tmp&255];
-
- // shift rows and add rcon
- if (i%keyLen === 0) {
- tmp = tmp<<8 ^ tmp>>>24 ^ rcon<<24;
- rcon = rcon<<1 ^ (rcon>>7)*283;
- }
- }
-
- encKey[i] = encKey[i-keyLen] ^ tmp;
- }
-
- // schedule decryption keys
- for (j = 0; i; j++, i--) {
- tmp = encKey[j&3 ? i : i - 4];
- if (i<=4 || j<4) {
- decKey[j] = tmp;
- } else {
- decKey[j] = decTable[0][sbox[tmp>>>24 ]] ^
- decTable[1][sbox[tmp>>16 & 255]] ^
- decTable[2][sbox[tmp>>8 & 255]] ^
- decTable[3][sbox[tmp & 255]];
- }
- }
-};
-
-sjcl.cipher.aes.prototype = {
- // public
- /* Something like this might appear here eventually
- name: "AES",
- blockSize: 4,
- keySizes: [4,6,8],
- */
-
- /**
- * Encrypt an array of 4 big-endian words.
- * @param {Array} data The plaintext.
- * @return {Array} The ciphertext.
- */
- encrypt:function (data) { return this._crypt(data,0); },
-
- /**
- * Decrypt an array of 4 big-endian words.
- * @param {Array} data The ciphertext.
- * @return {Array} The plaintext.
- */
- decrypt:function (data) { return this._crypt(data,1); },
-
- /**
- * The expanded S-box and inverse S-box tables. These will be computed
- * on the client so that we don't have to send them down the wire.
- *
- * There are two tables, _tables[0] is for encryption and
- * _tables[1] is for decryption.
- *
- * The first 4 sub-tables are the expanded S-box with MixColumns. The
- * last (_tables[01][4]) is the S-box itself.
- *
- * @private
- */
- _tables: [[[],[],[],[],[]],[[],[],[],[],[]]],
-
- /**
- * Expand the S-box tables.
- *
- * @private
- */
- _precompute: function () {
- var encTable = this._tables[0], decTable = this._tables[1],
- sbox = encTable[4], sboxInv = decTable[4],
- i, x, xInv, d=[], th=[], x2, x4, x8, s, tEnc, tDec;
-
- // Compute double and third tables
- for (i = 0; i < 256; i++) {
- th[( d[i] = i<<1 ^ (i>>7)*283 )^i]=i;
- }
-
- for (x = xInv = 0; !sbox[x]; x ^= x2 || 1, xInv = th[xInv] || 1) {
- // Compute sbox
- s = xInv ^ xInv<<1 ^ xInv<<2 ^ xInv<<3 ^ xInv<<4;
- s = s>>8 ^ s&255 ^ 99;
- sbox[x] = s;
- sboxInv[s] = x;
-
- // Compute MixColumns
- x8 = d[x4 = d[x2 = d[x]]];
- tDec = x8*0x1010101 ^ x4*0x10001 ^ x2*0x101 ^ x*0x1010100;
- tEnc = d[s]*0x101 ^ s*0x1010100;
-
- for (i = 0; i < 4; i++) {
- encTable[i][x] = tEnc = tEnc<<24 ^ tEnc>>>8;
- decTable[i][s] = tDec = tDec<<24 ^ tDec>>>8;
- }
- }
-
- // Compactify. Considerable speedup on Firefox.
- for (i = 0; i < 5; i++) {
- encTable[i] = encTable[i].slice(0);
- decTable[i] = decTable[i].slice(0);
- }
- },
-
- /**
- * Encryption and decryption core.
- * @param {Array} input Four words to be encrypted or decrypted.
- * @param dir The direction, 0 for encrypt and 1 for decrypt.
- * @return {Array} The four encrypted or decrypted words.
- * @private
- */
- _crypt:function (input, dir) {
- if (input.length !== 4) {
- throw new sjcl.exception.invalid("invalid aes block size");
- }
-
- var key = this._key[dir],
- // state variables a,b,c,d are loaded with pre-whitened data
- a = input[0] ^ key[0],
- b = input[dir ? 3 : 1] ^ key[1],
- c = input[2] ^ key[2],
- d = input[dir ? 1 : 3] ^ key[3],
- a2, b2, c2,
-
- nInnerRounds = key.length/4 - 2,
- i,
- kIndex = 4,
- out = [0,0,0,0],
- table = this._tables[dir],
-
- // load up the tables
- t0 = table[0],
- t1 = table[1],
- t2 = table[2],
- t3 = table[3],
- sbox = table[4];
-
- // Inner rounds. Cribbed from OpenSSL.
- for (i = 0; i < nInnerRounds; i++) {
- a2 = t0[a>>>24] ^ t1[b>>16 & 255] ^ t2[c>>8 & 255] ^ t3[d & 255] ^ key[kIndex];
- b2 = t0[b>>>24] ^ t1[c>>16 & 255] ^ t2[d>>8 & 255] ^ t3[a & 255] ^ key[kIndex + 1];
- c2 = t0[c>>>24] ^ t1[d>>16 & 255] ^ t2[a>>8 & 255] ^ t3[b & 255] ^ key[kIndex + 2];
- d = t0[d>>>24] ^ t1[a>>16 & 255] ^ t2[b>>8 & 255] ^ t3[c & 255] ^ key[kIndex + 3];
- kIndex += 4;
- a=a2; b=b2; c=c2;
- }
-
- // Last round.
- for (i = 0; i < 4; i++) {
- out[dir ? 3&-i : i] =
- sbox[a>>>24 ]<<24 ^
- sbox[b>>16 & 255]<<16 ^
- sbox[c>>8 & 255]<<8 ^
- sbox[d & 255] ^
- key[kIndex++];
- a2=a; a=b; b=c; c=d; d=a2;
- }
-
- return out;
- }
-};
-
-/** @fileOverview Arrays of bits, encoded as arrays of Numbers.
- *
- * @author Emily Stark
- * @author Mike Hamburg
- * @author Dan Boneh
- */
-
-/** @namespace Arrays of bits, encoded as arrays of Numbers.
- *
- * @description
- *
- * These objects are the currency accepted by SJCL's crypto functions.
- *
- *
- *
- * Most of our crypto primitives operate on arrays of 4-byte words internally,
- * but many of them can take arguments that are not a multiple of 4 bytes.
- * This library encodes arrays of bits (whose size need not be a multiple of 8
- * bits) as arrays of 32-bit words. The bits are packed, big-endian, into an
- * array of words, 32 bits at a time. Since the words are double-precision
- * floating point numbers, they fit some extra data. We use this (in a private,
- * possibly-changing manner) to encode the number of bits actually present
- * in the last word of the array.
- *
- *
- *
- * Because bitwise ops clear this out-of-band data, these arrays can be passed
- * to ciphers like AES which want arrays of words.
- *
- */
-sjcl.bitArray = {
- /**
- * Array slices in units of bits.
- * @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.
- * @return {bitArray} The requested slice.
- */
- bitSlice: function (a, bstart, bend) {
- a = sjcl.bitArray._shiftRight(a.slice(bstart/32), 32 - (bstart & 31)).slice(1);
- return (bend === undefined) ? a : sjcl.bitArray.clamp(a, bend-bstart);
- },
-
- /**
- * Extract a number packed into a bit array.
- * @param {bitArray} a The array to slice.
- * @param {Number} bstart The offset to the start of the slice, in bits.
- * @param {Number} length The length of the number to extract.
- * @return {Number} The requested slice.
- */
- extract: function(a, bstart, blength) {
- // FIXME: this Math.floor is not necessary at all, but for some reason
- // seems to suppress a bug in the Chromium JIT.
- var x, sh = Math.floor((-bstart-blength) & 31);
- if ((bstart + blength - 1 ^ bstart) & -32) {
- // it crosses a boundary
- x = (a[bstart/32|0] << (32 - sh)) ^ (a[bstart/32+1|0] >>> sh);
- } else {
- // within a single word
- x = a[bstart/32|0] >>> sh;
- }
- return x & ((1< 0 && len) {
- a[l-1] = sjcl.bitArray.partial(len, a[l-1] & 0x80000000 >> (len-1), 1);
- }
- return a;
- },
-
- /**
- * Make a partial word for a bit array.
- * @param {Number} len The number of bits in the word.
- * @param {Number} x The bits.
- * @param {Number} [0] _end Pass 1 if x has already been shifted to the high side.
- * @return {Number} The partial word.
- */
- partial: function (len, x, _end) {
- if (len === 32) { return x; }
- return (_end ? x|0 : x << (32-len)) + len * 0x10000000000;
- },
-
- /**
- * Get the number of bits used by a partial word.
- * @param {Number} x The partial word.
- * @return {Number} The number of bits used by the partial word.
- */
- getPartial: function (x) {
- return Math.round(x/0x10000000000) || 32;
- },
-
- /**
- * Compare two arrays for equality in a predictable amount of time.
- * @param {bitArray} a The first array.
- * @param {bitArray} b The second array.
- * @return {boolean} true if a == b; false otherwise.
- */
- equal: function (a, b) {
- if (sjcl.bitArray.bitLength(a) !== sjcl.bitArray.bitLength(b)) {
- return false;
- }
- var x = 0, i;
- for (i=0; i= 32; shift -= 32) {
- out.push(carry);
- carry = 0;
- }
- if (shift === 0) {
- return out.concat(a);
- }
-
- for (i=0; i>>shift);
- carry = a[i] << (32-shift);
- }
- last2 = a.length ? a[a.length-1] : 0;
- shift2 = sjcl.bitArray.getPartial(last2);
- out.push(sjcl.bitArray.partial(shift+shift2 & 31, (shift + shift2 > 32) ? carry : out.pop(),1));
- return out;
- },
-
- /** xor a block of 4 words together.
- * @private
- */
- _xor4: function(x,y) {
- return [x[0]^y[0],x[1]^y[1],x[2]^y[2],x[3]^y[3]];
- }
-};
-/** @fileOverview Bit array codec implementations.
- *
- * @author Emily Stark
- * @author Mike Hamburg
- * @author Dan Boneh
- */
-
-/** @namespace UTF-8 strings */
-sjcl.codec.utf8String = {
- /** Convert from a bitArray to a UTF-8 string. */
- fromBits: function (arr) {
- var out = "", bl = sjcl.bitArray.bitLength(arr), i, tmp;
- for (i=0; i>> 24);
- tmp <<= 8;
- }
- return decodeURIComponent(escape(out));
- },
-
- /** Convert from a UTF-8 string to a bitArray. */
- toBits: function (str) {
- str = unescape(encodeURIComponent(str));
- var out = [], i, tmp=0;
- for (i=0; i>>bits) >>> 26);
- if (bits < 6) {
- ta = arr[i] << (6-bits);
- bits += 26;
- i++;
- } else {
- ta <<= 6;
- bits -= 6;
- }
- }
- while ((out.length & 3) && !_noEquals) { out += "="; }
- return out;
- },
-
- /** Convert from a base64 string to a bitArray */
- 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) + '-_';
- for (i=0; i 26) {
- bits -= 26;
- out.push(ta ^ x>>>bits);
- ta = x << (32-bits);
- } else {
- bits += 6;
- ta ^= x << (32-bits);
- }
- }
- if (bits&56) {
- out.push(sjcl.bitArray.partial(bits&56, ta, 1));
- }
- return out;
- }
-};
-
-sjcl.codec.base64url = {
- fromBits: function (arr) { return sjcl.codec.base64.fromBits(arr,1,1); },
- toBits: function (str) { return sjcl.codec.base64.toBits(str,1); }
-};
-/** @fileOverview Javascript SHA-256 implementation.
- *
- * An older version of this implementation is available in the public
- * domain, but this one is (c) Emily Stark, Mike Hamburg, Dan Boneh,
- * Stanford University 2008-2010 and BSD-licensed for liability
- * reasons.
- *
- * Special thanks to Aldo Cortesi for pointing out several bugs in
- * this code.
- *
- * @author Emily Stark
- * @author Mike Hamburg
- * @author Dan Boneh
- */
-
-/**
- * Context for a SHA-256 operation in progress.
- * @constructor
- * @class Secure Hash Algorithm, 256 bits.
- */
-sjcl.hash.sha256 = function (hash) {
- if (!this._key[0]) { this._precompute(); }
- if (hash) {
- this._h = hash._h.slice(0);
- this._buffer = hash._buffer.slice(0);
- this._length = hash._length;
- } else {
- this.reset();
- }
-};
-
-/**
- * Hash a string or an array of words.
- * @static
- * @param {bitArray|String} data the data to hash.
- * @return {bitArray} The hash value, an array of 16 big-endian words.
- */
-sjcl.hash.sha256.hash = function (data) {
- return (new sjcl.hash.sha256()).update(data).finalize();
-};
-
-sjcl.hash.sha256.prototype = {
- /**
- * The hash's block size, in bits.
- * @constant
- */
- blockSize: 512,
-
- /**
- * Reset the hash state.
- * @return this
- */
- reset:function () {
- this._h = this._init.slice(0);
- this._buffer = [];
- this._length = 0;
- return this;
- },
-
- /**
- * Input several words to the hash.
- * @param {bitArray|String} data the data to hash.
- * @return this
- */
- update: function (data) {
- if (typeof data === "string") {
- data = sjcl.codec.utf8String.toBits(data);
- }
- var i, b = this._buffer = sjcl.bitArray.concat(this._buffer, data),
- ol = this._length,
- nl = this._length = ol + sjcl.bitArray.bitLength(data);
- for (i = 512+ol & -512; i <= nl; i+= 512) {
- this._block(b.splice(0,16));
- }
- return this;
- },
-
- /**
- * Complete hashing and output the hash value.
- * @return {bitArray} The hash value, an array of 16 big-endian words.
- */
- finalize:function () {
- var i, b = this._buffer, h = this._h;
-
- // Round out and push the buffer
- b = sjcl.bitArray.concat(b, [sjcl.bitArray.partial(1,1)]);
-
- // Round out the buffer to a multiple of 16 words, less the 2 length words.
- for (i = b.length + 2; i & 15; i++) {
- b.push(0);
- }
-
- // append the length
- b.push(Math.floor(this._length / 0x100000000));
- b.push(this._length | 0);
-
- while (b.length) {
- this._block(b.splice(0,16));
- }
-
- this.reset();
- return h;
- },
-
- /**
- * The SHA-256 initialization vector, to be precomputed.
- * @private
- */
- _init:[],
- /*
- _init:[0x6a09e667,0xbb67ae85,0x3c6ef372,0xa54ff53a,0x510e527f,0x9b05688c,0x1f83d9ab,0x5be0cd19],
- */
-
- /**
- * The SHA-256 hash key, to be precomputed.
- * @private
- */
- _key:[],
- /*
- _key:
- [0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
- 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
- 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
- 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
- 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
- 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
- 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
- 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2],
- */
-
-
- /**
- * Function to precompute _init and _key.
- * @private
- */
- _precompute: function () {
- var i = 0, prime = 2, factor;
-
- function frac(x) { return (x-Math.floor(x)) * 0x100000000 | 0; }
-
- outer: for (; i<64; prime++) {
- for (factor=2; factor*factor <= prime; factor++) {
- if (prime % factor === 0) {
- // not a prime
- continue outer;
- }
- }
-
- if (i<8) {
- this._init[i] = frac(Math.pow(prime, 1/2));
- }
- this._key[i] = frac(Math.pow(prime, 1/3));
- i++;
- }
- },
-
- /**
- * Perform one cycle of SHA-256.
- * @param {bitArray} words one block of words.
- * @private
- */
- _block:function (words) {
- var i, tmp, a, b,
- w = words.slice(0),
- h = this._h,
- k = this._key,
- h0 = h[0], h1 = h[1], h2 = h[2], h3 = h[3],
- h4 = h[4], h5 = h[5], h6 = h[6], h7 = h[7];
-
- /* Rationale for placement of |0 :
- * If a value can overflow is original 32 bits by a factor of more than a few
- * million (2^23 ish), there is a possibility that it might overflow the
- * 53-bit mantissa and lose precision.
- *
- * To avoid this, we clamp back to 32 bits by |'ing with 0 on any value that
- * propagates around the loop, and on the hash state h[]. I don't believe
- * that the clamps on h4 and on h0 are strictly necessary, but it's close
- * (for h4 anyway), and better safe than sorry.
- *
- * The clamps on h[] are necessary for the output to be correct even in the
- * common case and for short inputs.
- */
- for (i=0; i<64; i++) {
- // load up the input word for this round
- if (i<16) {
- tmp = w[i];
- } else {
- a = w[(i+1 ) & 15];
- b = w[(i+14) & 15];
- tmp = w[i&15] = ((a>>>7 ^ a>>>18 ^ a>>>3 ^ a<<25 ^ a<<14) +
- (b>>>17 ^ b>>>19 ^ b>>>10 ^ b<<15 ^ b<<13) +
- w[i&15] + w[(i+9) & 15]) | 0;
- }
-
- tmp = (tmp + h7 + (h4>>>6 ^ h4>>>11 ^ h4>>>25 ^ h4<<26 ^ h4<<21 ^ h4<<7) + (h6 ^ h4&(h5^h6)) + k[i]); // | 0;
-
- // shift register
- h7 = h6; h6 = h5; h5 = h4;
- h4 = h3 + tmp | 0;
- h3 = h2; h2 = h1; h1 = h0;
-
- h0 = (tmp + ((h1&h2) ^ (h3&(h1^h2))) + (h1>>>2 ^ h1>>>13 ^ h1>>>22 ^ h1<<30 ^ h1<<19 ^ h1<<10)) | 0;
- }
-
- h[0] = h[0]+h0 | 0;
- h[1] = h[1]+h1 | 0;
- h[2] = h[2]+h2 | 0;
- h[3] = h[3]+h3 | 0;
- h[4] = h[4]+h4 | 0;
- h[5] = h[5]+h5 | 0;
- h[6] = h[6]+h6 | 0;
- h[7] = h[7]+h7 | 0;
- }
-};
-
-
-/** @fileOverview CCM mode implementation.
- *
- * Special thanks to Roy Nicholson for pointing out a bug in our
- * implementation.
- *
- * @author Emily Stark
- * @author Mike Hamburg
- * @author Dan Boneh
- */
-
-/** @namespace CTR mode with CBC MAC. */
-sjcl.mode.ccm = {
- /** The name of the mode.
- * @constant
- */
- name: "ccm",
-
- /** Encrypt in CCM mode.
- * @static
- * @param {Object} prf The pseudorandom function. 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.
- * @param {Number} [tlen=64] the desired tag length, in bits.
- * @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;
- tlen = tlen || 64;
- adata = adata || [];
-
- if (ivl < 7) {
- throw new sjcl.exception.invalid("ccm: iv must be at least 7 bytes");
- }
-
- // compute the length of the length
- for (L=2; L<4 && ol >>> 8*L; L++) {}
- if (L < 15 - ivl) { L = 15-ivl; }
- iv = w.clamp(iv,8*(15-L));
-
- // compute the tag
- tag = sjcl.mode.ccm._computeTag(prf, plaintext, iv, adata, tlen, L);
-
- // encrypt
- out = sjcl.mode.ccm._ctrMode(prf, out, iv, tag, tlen, L);
-
- return w.concat(out.data, out.tag);
- },
-
- /** Decrypt in CCM mode.
- * @static
- * @param {Object} prf The pseudorandom function. 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.
- * @param {Number} [64] tlen the desired tag length, in bits.
- * @return {bitArray} The decrypted data.
- */
- decrypt: function(prf, ciphertext, iv, adata, tlen) {
- tlen = tlen || 64;
- adata = adata || [];
- var L, i,
- w=sjcl.bitArray,
- ivl = w.bitLength(iv) / 8,
- ol = w.bitLength(ciphertext),
- out = w.clamp(ciphertext, ol - tlen),
- tag = w.bitSlice(ciphertext, ol - tlen), tag2;
-
-
- ol = (ol - tlen) / 8;
-
- if (ivl < 7) {
- throw new sjcl.exception.invalid("ccm: iv must be at least 7 bytes");
- }
-
- // compute the length of the length
- for (L=2; L<4 && ol >>> 8*L; L++) {}
- if (L < 15 - ivl) { L = 15-ivl; }
- iv = w.clamp(iv,8*(15-L));
-
- // decrypt
- out = sjcl.mode.ccm._ctrMode(prf, out, iv, tag, tlen, L);
-
- // check the tag
- tag2 = sjcl.mode.ccm._computeTag(prf, out.data, iv, adata, tlen, L);
- if (!w.equal(out.tag, tag2)) {
- throw new sjcl.exception.corrupt("ccm: tag doesn't match");
- }
-
- return out.data;
- },
-
- /* Compute the (unencrypted) authentication tag, according to the CCM specification
- * @param {Object} prf The pseudorandom function.
- * @param {bitArray} plaintext The plaintext data.
- * @param {bitArray} iv The initialization value.
- * @param {bitArray} adata The authenticated data.
- * @param {Number} tlen the desired tag length, in bits.
- * @return {bitArray} The tag, but not yet encrypted.
- * @private
- */
- _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;
-
- tlen /= 8;
-
- // check tag length and message length
- if (tlen % 2 || tlen < 4 || tlen > 16) {
- throw new sjcl.exception.invalid("ccm: invalid tag length");
- }
-
- if (adata.length > 0xFFFFFFFF || plaintext.length > 0xFFFFFFFF) {
- // I don't want to deal with extracting high words from doubles.
- throw new sjcl.exception.bug("ccm: can't deal with 4GiB or more data");
- }
-
- // mac the flags
- mac = [w.partial(8, (adata.length ? 1<<6 : 0) | (tlen-2) << 2 | L-1)];
-
- // mac the iv and length
- mac = w.concat(mac, iv);
- mac[3] |= w.bitLength(plaintext)/8;
- mac = prf.encrypt(mac);
-
-
- if (adata.length) {
- // mac the associated data. start with its length...
- tmp = w.bitLength(adata)/8;
- if (tmp <= 0xFEFF) {
- macData = [w.partial(16, tmp)];
- } else if (tmp <= 0xFFFFFFFF) {
- macData = w.concat([w.partial(16,0xFFFE)], [tmp]);
- } // else ...
-
- // mac the data itself
- macData = w.concat(macData, adata);
- for (i=0; i>>31,
- x[1]<<1 ^ x[2]>>>31,
- x[2]<<1 ^ x[3]>>>31,
- x[3]<<1 ^ (x[0]>>>31)*0x87];
- }
-};
-/** @fileOverview HMAC implementation.
- *
- * @author Emily Stark
- * @author Mike Hamburg
- * @author Dan Boneh
- */
-
-/** HMAC with the specified hash function.
- * @constructor
- * @param {bitArray} key the key for HMAC.
- * @param {Object} [hash=sjcl.hash.sha256] The hash function to use.
- */
-sjcl.misc.hmac = function (key, Hash) {
- this._hash = Hash = Hash || sjcl.hash.sha256;
- var exKey = [[],[]], i,
- bs = Hash.prototype.blockSize / 32;
- this._baseHash = [new Hash(), new Hash()];
-
- if (key.length > bs) {
- key = Hash.hash(key);
- }
-
- for (i=0; i
- * This random number generator is a derivative of Ferguson and Schneier's
- * generator Fortuna. It collects entropy from various events into several
- * pools, implemented by streaming SHA-256 instances. It differs from
- * ordinary Fortuna in a few ways, though.
- *
- *
- *
- * Most importantly, it has an entropy estimator. This is present because
- * there is a strong conflict here between making the generator available
- * as soon as possible, and making sure that it doesn't "run on empty".
- * In Fortuna, there is a saved state file, and the system is likely to have
- * time to warm up.
- *
- *
- *
- * Second, because users are unlikely to stay on the page for very long,
- * and to speed startup time, the number of pools increases logarithmically:
- * a new pool is created when the previous one is actually used for a reseed.
- * This gives the same asymptotic guarantees as Fortuna, but gives more
- * entropy to early reseeds.
- *
- *
- *
- * The entire mechanism here feels pretty klunky. Furthermore, there are
- * several improvements that should be made, including support for
- * dedicated cryptographic functions that may be present in some browsers;
- * state files in local storage; cookies containing randomness; etc. So
- * look for improvements in future versions.
- *
- */
-sjcl.random = {
- /** Generate several random words, and return them in an array
- * @param {Number} nwords The number of words to generate.
- */
- randomWords: function (nwords, paranoia) {
- var out = [], i, readiness = this.isReady(paranoia), g;
-
- if (readiness === this._NOT_READY) {
- throw new sjcl.exception.notReady("generator isn't seeded");
- } else if (readiness & this._REQUIRES_RESEED) {
- this._reseedFromPools(!(readiness & this._READY));
- }
-
- for (i=0; i0) {
- estimatedEntropy++;
- tmp = tmp >>> 1;
- }
- }
- }
- this._pools[robin].update([id,this._eventId++,ty||2,estimatedEntropy,t,data.length].concat(data));
- break;
-
- case "string":
- if (estimatedEntropy === undefined) {
- /* English text has just over 1 bit per character of entropy.
- * But this might be HTML or something, and have far less
- * entropy than English... Oh well, let's just say one bit.
- */
- estimatedEntropy = data.length;
- }
- this._pools[robin].update([id,this._eventId++,3,estimatedEntropy,t,data.length]);
- this._pools[robin].update(data);
- break;
-
- default:
-
- throw new sjcl.exception.bug("random: addEntropy only supports number, array or string");
- }
-
- /* record the new strength */
- this._poolEntropy[robin] += estimatedEntropy;
- this._poolStrength += estimatedEntropy;
-
- /* fire off events */
- if (oldReady === this._NOT_READY) {
- if (this.isReady() !== this._NOT_READY) {
- this._fireEvent("seeded", Math.max(this._strength, this._poolStrength));
- }
- this._fireEvent("progress", this.getProgress());
- }
- },
-
- /** Is the generator ready? */
- isReady: function (paranoia) {
- var entropyRequired = this._PARANOIA_LEVELS[ (paranoia !== undefined) ? paranoia : this._defaultParanoia ];
-
- if (this._strength && this._strength >= entropyRequired) {
- return (this._poolEntropy[0] > this._BITS_PER_RESEED && (new Date()).valueOf() > this._nextReseed) ?
- this._REQUIRES_RESEED | this._READY :
- this._READY;
- } else {
- return (this._poolStrength >= entropyRequired) ?
- this._REQUIRES_RESEED | this._NOT_READY :
- this._NOT_READY;
- }
- },
-
- /** Get the generator's progress toward readiness, as a fraction */
- getProgress: function (paranoia) {
- var entropyRequired = this._PARANOIA_LEVELS[ paranoia ? paranoia : this._defaultParanoia ];
-
- if (this._strength >= entropyRequired) {
- return 1.0;
- } else {
- return (this._poolStrength > entropyRequired) ?
- 1.0 :
- this._poolStrength / entropyRequired;
- }
- },
-
- /** start the built-in entropy collectors */
- startCollectors: function () {
- if (this._collectorsStarted) { return; }
-
- if (window.addEventListener) {
- window.addEventListener("load", this._loadTimeCollector, false);
- window.addEventListener("mousemove", this._mouseCollector, false);
- } else if (document.attachEvent) {
- document.attachEvent("onload", this._loadTimeCollector);
- document.attachEvent("onmousemove", this._mouseCollector);
- }
- else {
- throw new sjcl.exception.bug("can't attach event");
- }
-
- this._collectorsStarted = true;
- },
-
- /** stop the built-in entropy collectors */
- stopCollectors: function () {
- if (!this._collectorsStarted) { return; }
-
- if (window.removeEventListener) {
- window.removeEventListener("load", this._loadTimeCollector, false);
- window.removeEventListener("mousemove", this._mouseCollector, false);
- } else if (window.detachEvent) {
- window.detachEvent("onload", this._loadTimeCollector);
- window.detachEvent("onmousemove", this._mouseCollector);
- }
- this._collectorsStarted = false;
- },
-
- /* use a cookie to store entropy.
- useCookie: function (all_cookies) {
- throw new sjcl.exception.bug("random: useCookie is unimplemented");
- },*/
-
- /** add an event listener for progress or seeded-ness. */
- addEventListener: function (name, callback) {
- this._callbacks[name][this._callbackI++] = callback;
- },
-
- /** remove an event listener for progress or seeded-ness */
- removeEventListener: function (name, cb) {
- var i, j, cbs=this._callbacks[name], jsTemp=[];
-
- /* I'm not sure if this is necessary; in C++, iterating over a
- * collection and modifying it at the same time is a no-no.
- */
-
- for (j in cbs) {
- if (cbs.hasOwnProperty(j) && cbs[j] === cb) {
- jsTemp.push(j);
- }
- }
-
- for (i=0; i= 1 << this._pools.length) {
- this._pools.push(new sjcl.hash.sha256());
- this._poolEntropy.push(0);
- }
-
- /* how strong was this reseed? */
- this._poolStrength -= strength;
- if (strength > this._strength) {
- this._strength = strength;
- }
-
- this._reseedCount ++;
- this._reseed(reseedData);
- },
-
- _mouseCollector: function (ev) {
- var x = ev.x || ev.clientX || ev.offsetX, y = ev.y || ev.clientY || ev.offsetY;
- sjcl.random.addEntropy([x,y], 2, "mouse");
- },
-
- _loadTimeCollector: function (ev) {
- var d = new Date();
- sjcl.random.addEntropy(d, 2, "loadtime");
- },
-
- _fireEvent: function (name, arg) {
- var j, cbs=sjcl.random._callbacks[name], cbsTemp=[];
- /* TODO: there is a race condition between removing collectors and firing them */
-
- /* I'm not sure if this is necessary; in C++, iterating over a
- * collection and modifying it at the same time is a no-no.
- */
-
- for (j in cbs) {
- if (cbs.hasOwnProperty(j)) {
- cbsTemp.push(cbs[j]);
- }
- }
-
- for (j=0; j 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);
- p.salt = tmp.salt;
- }
- if (typeof plaintext === "string") {
- plaintext = sjcl.codec.utf8String.toBits(plaintext);
- }
- 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, p.adata, p.ts);
-
- return j.encode(j._subtract(p, j.defaults));
- },
-
- /** 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) {
- 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;
- 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) ||
- (p.ts !== 64 && p.ts !== 96 && p.ts !== 128) ||
- (p.ks !== 128 && p.ks !== 192 && p.ks !== 256) ||
- (!p.iv) ||
- (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);
- p.salt = tmp.salt;
- }
- prp = new sjcl.cipher[p.cipher](password);
-
- /* do the decryption */
- ct = sjcl.mode[p.mode].decrypt(prp, p.ct, p.iv, p.adata, p.ts);
-
- /* return the json data */
- j._add(rp, p);
- rp.key = password;
-
- return sjcl.codec.utf8String.fromBits(ct);
- },
-
- /** Encode a flat structure into a JSON string.
- * @param {Object} obj The structure to encode.
- * @return {String} A JSON string.
- * @throws {sjcl.exception.invalid} if obj has a non-alphanumeric property.
- * @throws {sjcl.exception.bug} if a parameter has an unsupported type.
- */
- encode: function (obj) {
- var i, out='{', comma='';
- for (i in obj) {
- if (obj.hasOwnProperty(i)) {
- if (!i.match(/^[a-z0-9]+$/i)) {
- throw new sjcl.exception.invalid("json encode: invalid property name");
- }
- 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],1) + '"';
- break;
-
- default:
- throw new sjcl.exception.bug("json encode: unsupported type");
- }
- }
- }
- return out+'}';
- },
-
- /** Decode a simple (flat) JSON string into a structure. The ciphertext,
- * adata, salt and iv will be base64-decoded.
- * @param {String} str The string.
- * @return {Object} The decoded structure.
- * @throws {sjcl.exception.invalid} if str isn't (simple) JSON.
- */
- decode: function (str) {
- str = str.replace(/\s/g,'');
- if (!str.match(/^\{.*\}$/)) {
- throw new sjcl.exception.invalid("json decode: this isn't json!");
- }
- var a = str.replace(/^\{|\}$/g, '').split(/,/), out={}, i, m;
- for (i=0; i