diff --git a/manifest.json b/manifest.json
new file mode 100644
index 0000000..0aa0b26
--- /dev/null
+++ b/manifest.json
@@ -0,0 +1,30 @@
+{
+ "manifest_version": 2,
+
+ "name": "1Passwordanywhere Extension",
+ "description": "Fill in your 1Password passwords using 1Passwordanywhere on any platform",
+ "version": "0.1",
+
+ "commands": {
+ "_execute_page_action": {
+ "suggested_key": {
+ "default": "Ctrl+Shift+Y"
+ }
+ }
+ },
+
+ "browser_action": {
+ "default_popup": "popup.html",
+ "default_title": "1Passwordanywhere Extension"
+ },
+
+ "permissions": [
+ "http://*/*",
+ "https://*/*",
+ "tabs",
+ "storage"
+ ],
+ "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
+
+ "options_page": "options.html"
+}
diff --git a/options.html b/options.html
new file mode 100644
index 0000000..55199ee
--- /dev/null
+++ b/options.html
@@ -0,0 +1,15 @@
+
+
+
+ 1password anywhere extension
+
+
+
+
+ Baseurl:
+
+
+
+
+
+
diff --git a/popup.html b/popup.html
new file mode 100644
index 0000000..c60dd4e
--- /dev/null
+++ b/popup.html
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/scripts/1passwordanywhere.include.js b/scripts/1passwordanywhere.include.js
new file mode 100644
index 0000000..cb4e49b
--- /dev/null
+++ b/scripts/1passwordanywhere.include.js
@@ -0,0 +1,1573 @@
+// sha256.js
+// A JavaScript implementation of the Secure Hash Standard
+// Version 0.3 Copyright Angel Marin 2003-2004 - http://anmar.eu.org/
+// Distributed under the BSD License
+// Some bits taken from Paul Johnston's SHA-1 implementation
+//
+
+// bits per input character. 8 - ASCII; 16 - Unicode
+var chrsz = 8;
+
+// hex output format. 0 - lowercase; 1 - uppercase
+var hexcase = 0;
+
+function safe_add (x, y) {
+ var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+ var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+ return (msw << 16) | (lsw & 0xFFFF);
+}
+
+function S (X, n) {return ( X >>> n ) | (X << (32 - n));}
+
+function R (X, n) {return ( X >>> n );}
+
+function Ch(x, y, z) {return ((x & y) ^ ((~x) & z));}
+
+function Maj(x, y, z) {return ((x & y) ^ (x & z) ^ (y & z));}
+
+function Sigma0256(x) {return (S(x, 2) ^ S(x, 13) ^ S(x, 22));}
+
+function Sigma1256(x) {return (S(x, 6) ^ S(x, 11) ^ S(x, 25));}
+
+function Gamma0256(x) {return (S(x, 7) ^ S(x, 18) ^ R(x, 3));}
+
+function Gamma1256(x) {return (S(x, 17) ^ S(x, 19) ^ R(x, 10));}
+
+function Sigma0512(x) {return (S(x, 28) ^ S(x, 34) ^ S(x, 39));}
+
+function Sigma1512(x) {return (S(x, 14) ^ S(x, 18) ^ S(x, 41));}
+
+function Gamma0512(x) {return (S(x, 1) ^ S(x, 8) ^ R(x, 7));}
+
+function Gamma1512(x) {return (S(x, 19) ^ S(x, 61) ^ R(x, 6));}
+
+function core_sha256 (m, l) {
+ var K = new Array(0x428A2F98,0x71374491,0xB5C0FBCF,0xE9B5DBA5,0x3956C25B,0x59F111F1,0x923F82A4,0xAB1C5ED5,0xD807AA98,0x12835B01,0x243185BE,0x550C7DC3,0x72BE5D74,0x80DEB1FE,0x9BDC06A7,0xC19BF174,0xE49B69C1,0xEFBE4786,0xFC19DC6,0x240CA1CC,0x2DE92C6F,0x4A7484AA,0x5CB0A9DC,0x76F988DA,0x983E5152,0xA831C66D,0xB00327C8,0xBF597FC7,0xC6E00BF3,0xD5A79147,0x6CA6351,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);
+ var HASH = new Array(0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19);
+ var W = new Array(64);
+ var a, b, c, d, e, f, g, h, i, j;
+ var T1, T2;
+
+ // append padding
+ m[l >> 5] |= 0x80 << (24 - l % 32);
+ m[((l + 64 >> 9) << 4) + 15] = l;
+
+ for ( var i = 0; i>5] |= (str.charCodeAt(i / chrsz) & mask) << (24 - i%32);
+ return bin;
+}
+
+function binb2str (bin) {
+ var str = "";
+ var mask = (1 << chrsz) - 1;
+ for(var i = 0; i < bin.length * 32; i += chrsz)
+ str += String.fromCharCode((bin[i>>5] >>> (24 - i%32)) & mask);
+ return str;
+}
+
+function binb2hex (binarray) {
+ var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
+ var str = "";
+ for(var i = 0; i < binarray.length * 4; i++)
+ {
+ str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
+ hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
+ }
+ return str;
+}
+
+function binb2b64 (binarray) {
+ var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ var str = "";
+ for(var i = 0; i < binarray.length * 4; i += 3)
+ {
+ var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16)
+ | (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
+ | ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
+ for(var j = 0; j < 4; j++)
+ {
+ if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
+ else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
+ }
+ }
+ return str;
+}
+
+function hex_sha256(s){return binb2hex(core_sha256(str2binb(s),s.length * chrsz));}
+function b64_sha256(s){return binb2b64(core_sha256(str2binb(s),s.length * chrsz));}
+function str_sha256(s){return binb2str(core_sha256(str2binb(s),s.length * chrsz));}
+
+// sha1.js -->
+//
+// A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
+// in FIPS PUB 180-1
+// Version 2.1a Copyright Paul Johnston 2000 - 2002.
+// Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+// Distributed under the BSD License
+// See http://pajhome.org.uk/crypt/md5 for details.
+//
+
+//
+// Configurable variables. You may need to tweak these to be compatible with
+// the server-side, but the defaults work in most cases.
+//
+
+// hex output format. 0 - lowercase; 1 - uppercase
+var hexcase = 0;
+
+// base-64 pad character. "=" for strict RFC compliance
+var b64pad = "";
+
+// bits per input character. 8 - ASCII; 16 - Unicode
+var chrsz = 8;
+
+// These are the functions you'll usually want to call
+// They take string arguments and return either hex or base-64 encoded strings
+function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
+function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));}
+function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
+function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
+function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
+function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}
+
+//Perform a simple self-test to see if the VM is working
+function sha1_vm_test()
+{
+ return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
+}
+
+// Calculate the SHA-1 of an array of big-endian words, and a bit length
+function core_sha1(x, len)
+{
+ // append padding
+ x[len >> 5] |= 0x80 << (24 - len % 32);
+ x[((len + 64 >> 9) << 4) + 15] = len;
+
+ var w = Array(80);
+ var a = 1732584193;
+ var b = -271733879;
+ var c = -1732584194;
+ var d = 271733878;
+ var e = -1009589776;
+
+ for(var i = 0; i < x.length; i += 16)
+ {
+ var olda = a;
+ var oldb = b;
+ var oldc = c;
+ var oldd = d;
+ var olde = e;
+
+ for(var j = 0; j < 80; j++)
+ {
+ if(j < 16) w[j] = x[i + j];
+ else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
+ var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
+ safe_add(safe_add(e, w[j]), sha1_kt(j)));
+ e = d;
+ d = c;
+ c = rol(b, 30);
+ b = a;
+ a = t;
+ }
+
+ a = safe_add(a, olda);
+ b = safe_add(b, oldb);
+ c = safe_add(c, oldc);
+ d = safe_add(d, oldd);
+ e = safe_add(e, olde);
+ }
+ return Array(a, b, c, d, e);
+
+}
+
+// Perform the appropriate triplet combination function for the current
+// iteration
+function sha1_ft(t, b, c, d)
+{
+ if(t < 20) return (b & c) | ((~b) & d);
+ if(t < 40) return b ^ c ^ d;
+ if(t < 60) return (b & c) | (b & d) | (c & d);
+ return b ^ c ^ d;
+}
+
+// Determine the appropriate additive constant for the current iteration
+function sha1_kt(t)
+{
+ return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
+ (t < 60) ? -1894007588 : -899497514;
+}
+
+// Calculate the HMAC-SHA1 of a key and some data
+function core_hmac_sha1(key, data)
+{
+ var bkey = str2binb(key);
+ if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);
+
+ var ipad = Array(16), opad = Array(16);
+ for(var i = 0; i < 16; i++)
+ {
+ ipad[i] = bkey[i] ^ 0x36363636;
+ opad[i] = bkey[i] ^ 0x5C5C5C5C;
+ }
+
+ var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
+ return core_sha1(opad.concat(hash), 512 + 160);
+}
+
+// Add integers, wrapping at 2^32. This uses 16-bit operations internally
+// to work around bugs in some JS interpreters.
+function safe_add(x, y)
+{
+ var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+ var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+ return (msw << 16) | (lsw & 0xFFFF);
+}
+
+// Bitwise rotate a 32-bit number to the left.
+function rol(num, cnt)
+{
+ return (num << cnt) | (num >>> (32 - cnt));
+}
+
+// Convert an 8-bit or 16-bit string to an array of big-endian words
+// In 8-bit function, characters >255 have their hi-byte silently ignored.
+function str2binb(str)
+{
+ var bin = Array();
+ var mask = (1 << chrsz) - 1;
+ for(var i = 0; i < str.length * chrsz; i += chrsz)
+ bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
+ return bin;
+}
+
+// Convert an array of big-endian words to a string
+function binb2str(bin)
+{
+ var str = "";
+ var mask = (1 << chrsz) - 1;
+ for(var i = 0; i < bin.length * 32; i += chrsz)
+ str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
+ return str;
+}
+
+// Convert an array of big-endian words to a hex string.
+function binb2hex(binarray)
+{
+ var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
+ var str = "";
+ for(var i = 0; i < binarray.length * 4; i++)
+ {
+ str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
+ hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
+ }
+ return str;
+}
+
+function hex2bin(hex_str)
+{
+ var char_str = "";
+ var num_str = "";
+ var i;
+ for(i=0; i < hex_str.length; i+=2) {
+ char_str += String.fromCharCode(parseInt(hex_str.substring(i, i+2), 16));
+ }
+ return char_str;
+}
+
+
+// Convert an array of big-endian words to a base-64 string
+function binb2b64(binarray)
+{
+ var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ var str = "";
+ for(var i = 0; i < binarray.length * 4; i += 3)
+ {
+ var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16)
+ | (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
+ | ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
+ for(var j = 0; j < 4; j++)
+ {
+ if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
+ else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
+ }
+ }
+ return str;
+}
+
+// gibberish-aes.js -->
+// Gibberish-AES
+// A lightweight Javascript Libray for OpenSSL compatible AES CBC encryption.
+//
+// Author: Mark Percival
+// Email: mark@mpercival.com
+// Copyright: Mark Percival - http://mpercival.com 2008
+// Josh Davis - http://www.josh-davis.org/ecmaScrypt 2007
+// Chris Veness - http://www.movable-type.co.uk/scripts/aes.html 2007
+// Michel I. Gallant - http://www.jensign.com/
+//
+// License: MIT
+// Usage: Gibberish.encrypt("secret", "password", 256)
+// Outputs: AES Encrypted text encoded in Base64
+
+var GibberishAES = {
+ // Spells out 'Salted__'
+ SALTED_PREFIX: [83, 97, 108, 116, 101, 100, 95, 95],
+ ZERO_IV: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+
+ Nr: 14,
+ // Default to 256 Bit Encryption
+ Nb: 4,
+ Nk: 8,
+ Decrypt: false,
+
+ enc_utf8: function(s)
+ {
+ try {
+ return unescape(encodeURIComponent(s));
+ }
+ catch(e) {
+ throw 'Error on UTF-8 encode';
+ }
+ },
+
+ dec_utf8: function(s)
+ {
+ try {
+ return decodeURIComponent(escape(s));
+ }
+ catch(e) {
+ throw ('Bad Key');
+ }
+ },
+
+ padBlock: function(byteArr)
+ {
+ var array = [];
+ if (byteArr.length < 16) {
+ var cpad = 16 - byteArr.length;
+ var array = [cpad, cpad, cpad, cpad, cpad, cpad, cpad, cpad, cpad, cpad, cpad, cpad, cpad, cpad, cpad, cpad];
+ }
+ for (var i = 0; i < byteArr.length; i++)
+ {
+ array[i] = byteArr[i]
+ }
+ return array;
+ },
+
+ block2s: function(block, lastBlock)
+ {
+ var string = '';
+ if (lastBlock) {
+ var padding = block[15];
+ if (padding > 16) {
+ throw ('Decryption error: Maybe bad key');
+ }
+ if (padding == 16) {
+ return '';
+ }
+ for (var i = 0; i < 16 - padding; i++) {
+ string += String.fromCharCode(block[i]);
+ }
+ } else {
+ for (i = 0; i < 16; i++) {
+ string += String.fromCharCode(block[i]);
+ }
+ }
+ return string;
+ },
+
+ a2h: function(numArr)
+ {
+ var string = '';
+ for (var i = 0; i < numArr.length; i++) {
+ string += (numArr[i] < 16 ? '0': '') + numArr[i].toString(16);
+ }
+ return string;
+ },
+
+ h2a: function(s)
+ {
+ var ret = [];
+ s.replace(/(..)/g,
+ function(s) {
+ ret.push(parseInt(s, 16));
+ });
+ return ret;
+ },
+
+ s2a: function(string) {
+ var array = [];
+
+ for (var i = 0; i < string.length; i++)
+ {
+ array[i] = string.charCodeAt(i);
+ }
+ return array;
+ },
+
+ a2s: function(inArray) {
+ var result = "";
+
+ for (var i = 0; i < inArray.length; i++)
+ {
+ result += String.fromCharCode(inArray[i]);
+ }
+ return result;
+ },
+
+ size: function(newsize)
+ {
+ switch (newsize)
+ {
+ case 128:
+ this.Nr = 10;
+ this.Nk = 4;
+ break;
+ case 192:
+ this.Nr = 12;
+ this.Nk = 6;
+ break;
+ case 256:
+ this.Nr = 14;
+ this.Nk = 8;
+ break;
+ default:
+ throw ('Invalid Key Size Specified:' + newsize);
+ }
+ },
+
+ randArr: function(num) {
+ var result = []
+ for (var i = 0; i < num; i++) {
+ result = result.concat(Math.floor(Math.random() * 256));
+ }
+ return result;
+ },
+
+ openSSLKey: function(passwordArr, saltArr) {
+ // Number of rounds depends on the size of the AES in use
+ // 3 rounds for 256
+ // 2 rounds for the key, 1 for the IV
+ // 2 rounds for 128
+ // 1 round for the key, 1 round for the IV
+ // 3 rounds for 192 since it's not evenly divided by 128 bits
+ var rounds = this.Nr >= 12 ? 3: 2;
+ var key = [];
+ var iv = [];
+ var md5_hash = [];
+ var result = [];
+ data00 = passwordArr.concat(saltArr);
+ md5_hash[0] = GibberishAES.Hash.MD5(data00);
+ result = md5_hash[0];
+ for (var i = 1; i < rounds; i++) {
+ md5_hash[i] = GibberishAES.Hash.MD5(md5_hash[i - 1].concat(data00));
+ result = result.concat(md5_hash[i]);
+ }
+ key = result.slice(0, 4 * this.Nk);
+ iv = result.slice(4 * this.Nk, 4 * this.Nk + 16);
+ return {
+ key: key,
+ iv: iv
+ };
+ },
+
+ rawEncrypt: function(plaintext, key, iv) {
+ // plaintext, key and iv as byte arrays
+ key = this.expandKey(key);
+ var numBlocks = Math.ceil(plaintext.length / 16);
+ var blocks = [];
+ for (var i = 0; i < numBlocks; i++) {
+ blocks[i] = this.padBlock(plaintext.slice(i * 16, i * 16 + 16));
+ }
+ if (plaintext.length % 16 === 0) {
+ blocks.push([16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16]);
+ // CBC OpenSSL padding scheme
+ numBlocks++;
+ }
+ var cipherBlocks = [];
+ for (var i = 0; i < blocks.length; i++) {
+ blocks[i] = (i === 0) ? this.xorBlocks(blocks[i], iv) : this.xorBlocks(blocks[i], cipherBlocks[i - 1]);
+ cipherBlocks[i] = this.encryptBlock(blocks[i], key);
+ }
+ return cipherBlocks;
+ },
+
+ decryptBinaryUsingKeyAndIvec: function(cryptArr, key, iv) {
+
+ // cryptArr, key and iv as byte arrays
+ key = this.expandKey(key);
+ var numBlocks = cryptArr.length / 16;
+ var cipherBlocks = [];
+ for (var i = 0; i < numBlocks; i++) {
+ cipherBlocks.push(cryptArr.slice(i * 16, (i + 1) * 16));
+ }
+ var plainBlocks = [];
+
+ for (var i = cipherBlocks.length - 1; i >= 0; i--) {
+ plainBlocks[i] = this.decryptBlock(cipherBlocks[i], key);
+ plainBlocks[i] = (i === 0) ? this.xorBlocks(plainBlocks[i], iv) : this.xorBlocks(plainBlocks[i], cipherBlocks[i - 1]);
+ }
+ var string = '';
+ for (var i = 0; i < numBlocks - 1; i++) {
+ string += this.block2s(plainBlocks[i]);
+ }
+ string += this.block2s(plainBlocks[i], true);
+ return string;
+ },
+
+ encryptBlock: function(block, words) {
+ this.Decrypt = false;
+ var state = this.addRoundKey(block, words, 0);
+ for (var round = 1; round < (this.Nr + 1); round++) {
+ state = this.subBytes(state);
+ state = this.shiftRows(state);
+ if (round < this.Nr) {
+ state = this.mixColumns(state);
+ }
+ //last round? don't mixColumns
+ state = this.addRoundKey(state, words, round);
+ }
+
+ return state;
+ },
+
+ decryptBlock: function(block, words) {
+ this.Decrypt = true;
+ var state = this.addRoundKey(block, words, this.Nr);
+ for (var round = this.Nr - 1; round > -1; round--) {
+ state = this.shiftRows(state);
+ state = this.subBytes(state);
+ state = this.addRoundKey(state, words, round);
+ if (round > 0) {
+ state = this.mixColumns(state);
+ }
+ //last round? don't mixColumns
+ }
+
+ return state;
+ },
+
+ subBytes: function(state) {
+ var S = this.Decrypt ? this.SBoxInv: this.SBox;
+ var temp = [];
+ for (var i = 0; i < 16; i++) {
+ temp[i] = S[state[i]];
+ }
+ return temp;
+ },
+
+ shiftRows: function(state) {
+ var temp = [];
+ var shiftBy = this.Decrypt ? [0, 13, 10, 7, 4, 1, 14, 11, 8, 5, 2, 15, 12, 9, 6, 3] : [0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11];
+ for (var i = 0; i < 16; i++) {
+ temp[i] = state[shiftBy[i]];
+ }
+ return temp;
+ },
+
+ mixColumns: function(state) {
+ var t = [];
+ if (!this.Decrypt) {
+ for (var c = 0; c < 4; c++) {
+ t[c * 4] = this.G2X[state[c * 4]] ^ this.G3X[state[1 + c * 4]] ^ state[2 + c * 4] ^ state[3 + c * 4];
+ t[1 + c * 4] = state[c * 4] ^ this.G2X[state[1 + c * 4]] ^ this.G3X[state[2 + c * 4]] ^ state[3 + c * 4];
+ t[2 + c * 4] = state[c * 4] ^ state[1 + c * 4] ^ this.G2X[state[2 + c * 4]] ^ this.G3X[state[3 + c * 4]];
+ t[3 + c * 4] = this.G3X[state[c * 4]] ^ state[1 + c * 4] ^ state[2 + c * 4] ^ this.G2X[state[3 + c * 4]];
+ }
+ }else {
+ for (var c = 0; c < 4; c++) {
+ t[c*4] = this.GEX[state[c*4]] ^ this.GBX[state[1+c*4]] ^ this.GDX[state[2+c*4]] ^ this.G9X[state[3+c*4]];
+ t[1+c*4] = this.G9X[state[c*4]] ^ this.GEX[state[1+c*4]] ^ this.GBX[state[2+c*4]] ^ this.GDX[state[3+c*4]];
+ t[2+c*4] = this.GDX[state[c*4]] ^ this.G9X[state[1+c*4]] ^ this.GEX[state[2+c*4]] ^ this.GBX[state[3+c*4]];
+ t[3+c*4] = this.GBX[state[c*4]] ^ this.GDX[state[1+c*4]] ^ this.G9X[state[2+c*4]] ^ this.GEX[state[3+c*4]];
+ }
+ }
+
+ return t;
+ },
+
+ addRoundKey: function(state, words, round) {
+ var temp = [];
+ for (var i = 0; i < 16; i++) {
+ temp[i] = state[i] ^ words[round][i];
+ }
+ return temp;
+ },
+
+ xorBlocks: function(block1, block2) {
+ var temp = [];
+ for (var i = 0; i < 16; i++) {
+ temp[i] = block1[i] ^ block2[i];
+ }
+ return temp;
+ },
+
+ expandKey: function(key) {
+ // Expects a 1d number array
+ var Nb = this.Nb;
+ var Nr = this.Nr;
+ var Nk = this.Nk;
+
+ var w = [];
+ var temp = [];
+
+ for (var i = 0; i < Nk; i++) {
+ var r = [key[4 * i], key[4 * i + 1], key[4 * i + 2], key[4 * i + 3]];
+ w[i] = r;
+ }
+
+ for (var i = Nk; i < (4 * (Nr + 1)); i++) {
+ w[i] = [];
+ for (var t = 0; t < 4; t++) {
+ temp[t] = w[i - 1][t];
+ }
+ if (i % Nk === 0) {
+ temp = this.subWord(this.rotWord(temp));
+ temp[0] ^= this.Rcon[i / Nk - 1];
+ } else if (Nk > 6 && i % Nk == 4) {
+ temp = this.subWord(temp);
+ }
+ for (var t = 0; t < 4; t++) {
+ w[i][t] = w[i - Nk][t] ^ temp[t];
+ }
+ }
+ var flat = [];
+ for (var i = 0; i < (Nr + 1); i++) {
+ flat[i] = [];
+ for (var j = 0; j < 4; j++) {
+ flat[i].push(w[i * 4 + j][0], w[i * 4 + j][1], w[i * 4 + j][2], w[i * 4 + j][3]);
+ }
+ }
+ return flat;
+ },
+
+ subWord: function(w) {
+ // apply SBox to 4-byte word w
+ for (var i = 0; i < 4; i++) {
+ w[i] = this.SBox[w[i]];
+ }
+ return w;
+ },
+
+ rotWord: function(w) {
+ // rotate 4-byte word w left by one byte
+ var tmp = w[0];
+ for (var i = 0; i < 4; i++) {
+ w[i] = w[i + 1];
+ }
+ w[3] = tmp;
+ return w;
+ },
+
+
+ // S-box
+ SBox: [
+ 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171,
+ 118, 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164,
+ 114, 192, 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113,
+ 216, 49, 21, 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226,
+ 235, 39, 178, 117, 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214,
+ 179, 41, 227, 47, 132, 83, 209, 0, 237, 32, 252, 177, 91, 106, 203,
+ 190, 57, 74, 76, 88, 207, 208, 239, 170, 251, 67, 77, 51, 133, 69,
+ 249, 2, 127, 80, 60, 159, 168, 81, 163, 64, 143, 146, 157, 56, 245,
+ 188, 182, 218, 33, 16, 255, 243, 210, 205, 12, 19, 236, 95, 151, 68,
+ 23, 196, 167, 126, 61, 100, 93, 25, 115, 96, 129, 79, 220, 34, 42,
+ 144, 136, 70, 238, 184, 20, 222, 94, 11, 219, 224, 50, 58, 10, 73,
+ 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121, 231, 200, 55, 109,
+ 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, 186, 120, 37,
+ 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, 112, 62,
+ 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, 225,
+ 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
+ 140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187,
+ 22],
+
+ // Precomputed lookup table for the inverse SBox
+ SBoxInv: [
+ 82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215,
+ 251, 124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222,
+ 233, 203, 84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66,
+ 250, 195, 78, 8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73,
+ 109, 139, 209, 37, 114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92,
+ 204, 93, 101, 182, 146, 108, 112, 72, 80, 253, 237, 185, 218, 94, 21,
+ 70, 87, 167, 141, 157, 132, 144, 216, 171, 0, 140, 188, 211, 10, 247,
+ 228, 88, 5, 184, 179, 69, 6, 208, 44, 30, 143, 202, 63, 15, 2,
+ 193, 175, 189, 3, 1, 19, 138, 107, 58, 145, 17, 65, 79, 103, 220,
+ 234, 151, 242, 207, 206, 240, 180, 230, 115, 150, 172, 116, 34, 231, 173,
+ 53, 133, 226, 249, 55, 232, 28, 117, 223, 110, 71, 241, 26, 113, 29,
+ 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27, 252, 86, 62, 75,
+ 198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244, 31, 221, 168,
+ 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95, 96, 81,
+ 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239, 160,
+ 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97,
+ 23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12,
+ 125],
+ // Rijndael Rcon
+ Rcon: [1, 2, 4, 8, 16, 32, 64, 128, 27, 54, 108, 216, 171, 77, 154, 47, 94,
+ 188, 99, 198, 151, 53, 106, 212, 179, 125, 250, 239, 197, 145],
+
+ G2X: [
+ 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16,
+ 0x18, 0x1a, 0x1c, 0x1e, 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e,
+ 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, 0x40, 0x42, 0x44, 0x46,
+ 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
+ 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76,
+ 0x78, 0x7a, 0x7c, 0x7e, 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e,
+ 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e, 0xa0, 0xa2, 0xa4, 0xa6,
+ 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
+ 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6,
+ 0xd8, 0xda, 0xdc, 0xde, 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee,
+ 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe, 0x1b, 0x19, 0x1f, 0x1d,
+ 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05,
+ 0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d,
+ 0x23, 0x21, 0x27, 0x25, 0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55,
+ 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45, 0x7b, 0x79, 0x7f, 0x7d,
+ 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65,
+ 0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d,
+ 0x83, 0x81, 0x87, 0x85, 0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5,
+ 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5, 0xdb, 0xd9, 0xdf, 0xdd,
+ 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5,
+ 0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed,
+ 0xe3, 0xe1, 0xe7, 0xe5
+ ],
+
+ G3X: [
+ 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d,
+ 0x14, 0x17, 0x12, 0x11, 0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39,
+ 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21, 0x60, 0x63, 0x66, 0x65,
+ 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71,
+ 0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d,
+ 0x44, 0x47, 0x42, 0x41, 0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9,
+ 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1, 0xf0, 0xf3, 0xf6, 0xf5,
+ 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1,
+ 0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd,
+ 0xb4, 0xb7, 0xb2, 0xb1, 0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99,
+ 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81, 0x9b, 0x98, 0x9d, 0x9e,
+ 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a,
+ 0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6,
+ 0xbf, 0xbc, 0xb9, 0xba, 0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2,
+ 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea, 0xcb, 0xc8, 0xcd, 0xce,
+ 0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda,
+ 0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46,
+ 0x4f, 0x4c, 0x49, 0x4a, 0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62,
+ 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a, 0x3b, 0x38, 0x3d, 0x3e,
+ 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a,
+ 0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16,
+ 0x1f, 0x1c, 0x19, 0x1a
+ ],
+
+ G9X: [
+ 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53,
+ 0x6c, 0x65, 0x7e, 0x77, 0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf,
+ 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7, 0x3b, 0x32, 0x29, 0x20,
+ 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
+ 0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8,
+ 0xc7, 0xce, 0xd5, 0xdc, 0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49,
+ 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01, 0xe6, 0xef, 0xf4, 0xfd,
+ 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91,
+ 0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e,
+ 0x21, 0x28, 0x33, 0x3a, 0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2,
+ 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa, 0xec, 0xe5, 0xfe, 0xf7,
+ 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b,
+ 0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f,
+ 0x10, 0x19, 0x02, 0x0b, 0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8,
+ 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0, 0x47, 0x4e, 0x55, 0x5c,
+ 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30,
+ 0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9,
+ 0xf6, 0xff, 0xe4, 0xed, 0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35,
+ 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d, 0xa1, 0xa8, 0xb3, 0xba,
+ 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6,
+ 0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62,
+ 0x5d, 0x54, 0x4f, 0x46
+ ],
+
+ GBX: [
+ 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45,
+ 0x74, 0x7f, 0x62, 0x69, 0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81,
+ 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9, 0x7b, 0x70, 0x6d, 0x66,
+ 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12,
+ 0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e,
+ 0xbf, 0xb4, 0xa9, 0xa2, 0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7,
+ 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f, 0x46, 0x4d, 0x50, 0x5b,
+ 0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f,
+ 0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8,
+ 0xf9, 0xf2, 0xef, 0xe4, 0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c,
+ 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54, 0xf7, 0xfc, 0xe1, 0xea,
+ 0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e,
+ 0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02,
+ 0x33, 0x38, 0x25, 0x2e, 0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd,
+ 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5, 0x3c, 0x37, 0x2a, 0x21,
+ 0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55,
+ 0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44,
+ 0x75, 0x7e, 0x63, 0x68, 0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80,
+ 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8, 0x7a, 0x71, 0x6c, 0x67,
+ 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13,
+ 0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f,
+ 0xbe, 0xb5, 0xa8, 0xa3
+ ],
+
+ GDX: [
+ 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f,
+ 0x5c, 0x51, 0x46, 0x4b, 0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3,
+ 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b, 0xbb, 0xb6, 0xa1, 0xac,
+ 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0,
+ 0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14,
+ 0x37, 0x3a, 0x2d, 0x20, 0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e,
+ 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26, 0xbd, 0xb0, 0xa7, 0xaa,
+ 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6,
+ 0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9,
+ 0x8a, 0x87, 0x90, 0x9d, 0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25,
+ 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d, 0xda, 0xd7, 0xc0, 0xcd,
+ 0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91,
+ 0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75,
+ 0x56, 0x5b, 0x4c, 0x41, 0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42,
+ 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a, 0xb1, 0xbc, 0xab, 0xa6,
+ 0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa,
+ 0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8,
+ 0xeb, 0xe6, 0xf1, 0xfc, 0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44,
+ 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c, 0x0c, 0x01, 0x16, 0x1b,
+ 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47,
+ 0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3,
+ 0x80, 0x8d, 0x9a, 0x97
+ ],
+
+ GEX: [
+ 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62,
+ 0x48, 0x46, 0x54, 0x5a, 0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca,
+ 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba, 0xdb, 0xd5, 0xc7, 0xc9,
+ 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81,
+ 0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59,
+ 0x73, 0x7d, 0x6f, 0x61, 0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87,
+ 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7, 0x4d, 0x43, 0x51, 0x5f,
+ 0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17,
+ 0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14,
+ 0x3e, 0x30, 0x22, 0x2c, 0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc,
+ 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc, 0x41, 0x4f, 0x5d, 0x53,
+ 0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b,
+ 0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3,
+ 0xe9, 0xe7, 0xf5, 0xfb, 0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0,
+ 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0, 0x7a, 0x74, 0x66, 0x68,
+ 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20,
+ 0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e,
+ 0xa4, 0xaa, 0xb8, 0xb6, 0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26,
+ 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56, 0x37, 0x39, 0x2b, 0x25,
+ 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d,
+ 0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5,
+ 0x9f, 0x91, 0x83, 0x8d
+ ],
+
+ enc: function(string, pass) {
+ // string, password in plaintext
+ return this.encryptUsingPassword(string, pass, true);
+ },
+
+ encryptUsingPassword: function(string, password, salted) {
+ var key = GibberishAES.Hash.MD5(this.s2a(password));
+ return this.encryptUsingKey(string, key, salted);
+ },
+
+ encryptUsingKey: function(string, inKeyArray, salted) {
+ var key, iv;
+
+ if (salted) {
+ var salt = this.randArr(8);
+ var pbe = this.openSSLKey(inKeyArray, salt);
+ key = pbe.key;
+ iv = pbe.iv;
+ }
+ else {
+ key = inKeyArray;
+ iv = this.ZERO_IV;
+ }
+
+ string = this.s2a(string);
+ var cipherBlocks = this.rawEncrypt(string, key, iv);
+
+ if (salted) {
+ var saltBlock = [this.SALTED_PREFIX.concat(salt)];
+ cipherBlocks = saltBlock.concat(cipherBlocks);
+ }
+
+ return this.Base64.encode(cipherBlocks);
+ },
+
+ dec: function(string, pass) {
+ // string, password in plaintext
+ return this.decryptBase64UsingKey(string, this.s2a(pass));
+ },
+
+ decryptUsingPBKDF2: function(data, password, iterations) {
+ var binaryArr = GibberishAES.Base64.decode(data);
+
+ var saltArr = this.ZERO_IV;
+ if (this.isSalted(binaryArr)) {
+ saltArr = binaryArr.slice(8, 16);
+ binaryArr = binaryArr.slice(16);
+ }
+
+ var t0 = new Date();
+ var mypbkdf2 = new PBKDF2(password, this.a2s(saltArr), iterations, 32); // key is 16bytes; ivec is 16bytes
+ var derivedKey = mypbkdf2.deriveKey();
+
+ var t1 = new Date();
+// alert ("Key generation time: " + (t1.getTime() - t0.getTime()));
+
+ var key = derivedKey.slice(0, 16);
+ var iv = derivedKey.slice(16);
+ try {
+ return this.decryptBinaryUsingKeyAndIvec(binaryArr, key, iv);
+ }catch(e) {
+ return null;
+ }
+ },
+
+ decryptBase64UsingKey: function(string, inKeyArray) {
+ var binaryArr = this.Base64.decode(string);
+ return this.decryptBinaryUsingKey(binaryArr, inKeyArray);
+ },
+
+ decryptBinaryUsingKey: function(binaryArr, inKeyArray) {
+ var salted = this.isSalted(binaryArr);
+ var key, iv;
+
+ if (salted) {
+ var salt = binaryArr.slice(8, 16);
+
+ var pbe = this.openSSLKey(inKeyArray, salt);
+ key = pbe.key;
+ iv = pbe.iv;
+ binaryArr = binaryArr.slice(16, binaryArr.length);
+ }
+ else {
+ key = GibberishAES.Hash.MD5(inKeyArray);
+ iv = this.ZERO_IV;
+ }
+
+ try {
+ return this.decryptBinaryUsingKeyAndIvec(binaryArr, key, iv);
+ }
+ catch (e) {
+// alert('Caught error ' + e);
+ return null;
+ }
+ },
+
+ isSalted: function(cryptArr) {
+ for (var i=0; i < 8; i++) {
+ if (this.SALTED_PREFIX[i] != cryptArr[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+};
+
+GibberishAES.Hash = {
+
+ MD5: function(numArr) {
+
+ function RotateLeft(lValue, iShiftBits) {
+ return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
+ }
+
+ function AddUnsigned(lX, lY) {
+ var lX4,
+ lY4,
+ lX8,
+ lY8,
+ lResult;
+ lX8 = (lX & 0x80000000);
+ lY8 = (lY & 0x80000000);
+ lX4 = (lX & 0x40000000);
+ lY4 = (lY & 0x40000000);
+ lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
+ if (lX4 & lY4) {
+ return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
+ }
+ if (lX4 | lY4) {
+ if (lResult & 0x40000000) {
+ return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
+ } else {
+ return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
+ }
+ } else {
+ return (lResult ^ lX8 ^ lY8);
+ }
+ }
+
+ function F(x, y, z) {
+ return (x & y) | ((~x) & z);
+ }
+ function G(x, y, z) {
+ return (x & z) | (y & (~z));
+ }
+ function H(x, y, z) {
+ return (x ^ y ^ z);
+ }
+ function I(x, y, z) {
+ return (y ^ (x | (~z)));
+ }
+
+ function FF(a, b, c, d, x, s, ac) {
+ a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
+ return AddUnsigned(RotateLeft(a, s), b);
+ };
+
+ function GG(a, b, c, d, x, s, ac) {
+ a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
+ return AddUnsigned(RotateLeft(a, s), b);
+ };
+
+ function HH(a, b, c, d, x, s, ac) {
+ a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
+ return AddUnsigned(RotateLeft(a, s), b);
+ };
+
+ function II(a, b, c, d, x, s, ac) {
+ a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
+ return AddUnsigned(RotateLeft(a, s), b);
+ };
+
+ function ConvertToWordArray(numArr) {
+ var lWordCount;
+ var lMessageLength = numArr.length;
+ var lNumberOfWords_temp1 = lMessageLength + 8;
+ var lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64;
+ var lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16;
+ var lWordArray = Array(lNumberOfWords - 1);
+ var lBytePosition = 0;
+ var lByteCount = 0;
+ while (lByteCount < lMessageLength) {
+ lWordCount = (lByteCount - (lByteCount % 4)) / 4;
+ lBytePosition = (lByteCount % 4) * 8;
+ lWordArray[lWordCount] = (lWordArray[lWordCount] | (numArr[lByteCount] << lBytePosition));
+ lByteCount++;
+ }
+ lWordCount = (lByteCount - (lByteCount % 4)) / 4;
+ lBytePosition = (lByteCount % 4) * 8;
+ lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
+ lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
+ lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
+ return lWordArray;
+ };
+
+ function WordToHex(lValue) {
+ var WordToHexValue = "",
+ WordToHexValue_temp = "",
+ lByte,
+ lCount;
+ var WordToHexArr = []
+ for (lCount = 0; lCount <= 3; lCount++) {
+ lByte = (lValue >>> (lCount * 8)) & 255;
+ WordToHexArr = WordToHexArr.concat(lByte)
+ }
+ return WordToHexArr;
+ };
+
+ function Utf8Encode(string) {
+ string = string.replace(/\r\n/g, "\n");
+ var utftext = "";
+
+ for (var n = 0; n < string.length; n++) {
+
+ var c = string.charCodeAt(n);
+
+ if (c < 128) {
+ utftext += String.fromCharCode(c);
+ }
+ else if ((c > 127) && (c < 2048)) {
+ utftext += String.fromCharCode((c >> 6) | 192);
+ utftext += String.fromCharCode((c & 63) | 128);
+ }
+ else {
+ utftext += String.fromCharCode((c >> 12) | 224);
+ utftext += String.fromCharCode(((c >> 6) & 63) | 128);
+ utftext += String.fromCharCode((c & 63) | 128);
+ }
+
+ }
+
+ return utftext;
+ };
+
+ var x = Array();
+ var k,
+ AA,
+ BB,
+ CC,
+ DD,
+ a,
+ b,
+ c,
+ d;
+ var S11 = 7,
+ S12 = 12,
+ S13 = 17,
+ S14 = 22;
+ var S21 = 5,
+ S22 = 9,
+ S23 = 14,
+ S24 = 20;
+ var S31 = 4,
+ S32 = 11,
+ S33 = 16,
+ S34 = 23;
+ var S41 = 6,
+ S42 = 10,
+ S43 = 15,
+ S44 = 21;
+
+ x = ConvertToWordArray(numArr);
+
+ a = 0x67452301;
+ b = 0xEFCDAB89;
+ c = 0x98BADCFE;
+ d = 0x10325476;
+
+ for (k = 0; k < x.length; k += 16) {
+ AA = a;
+ BB = b;
+ CC = c;
+ DD = d;
+ a = FF(a, b, c, d, x[k + 0], S11, 0xD76AA478);
+ d = FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756);
+ c = FF(c, d, a, b, x[k + 2], S13, 0x242070DB);
+ b = FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE);
+ a = FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF);
+ d = FF(d, a, b, c, x[k + 5], S12, 0x4787C62A);
+ c = FF(c, d, a, b, x[k + 6], S13, 0xA8304613);
+ b = FF(b, c, d, a, x[k + 7], S14, 0xFD469501);
+ a = FF(a, b, c, d, x[k + 8], S11, 0x698098D8);
+ d = FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF);
+ c = FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1);
+ b = FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE);
+ a = FF(a, b, c, d, x[k + 12], S11, 0x6B901122);
+ d = FF(d, a, b, c, x[k + 13], S12, 0xFD987193);
+ c = FF(c, d, a, b, x[k + 14], S13, 0xA679438E);
+ b = FF(b, c, d, a, x[k + 15], S14, 0x49B40821);
+ a = GG(a, b, c, d, x[k + 1], S21, 0xF61E2562);
+ d = GG(d, a, b, c, x[k + 6], S22, 0xC040B340);
+ c = GG(c, d, a, b, x[k + 11], S23, 0x265E5A51);
+ b = GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA);
+ a = GG(a, b, c, d, x[k + 5], S21, 0xD62F105D);
+ d = GG(d, a, b, c, x[k + 10], S22, 0x2441453);
+ c = GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681);
+ b = GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8);
+ a = GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6);
+ d = GG(d, a, b, c, x[k + 14], S22, 0xC33707D6);
+ c = GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87);
+ b = GG(b, c, d, a, x[k + 8], S24, 0x455A14ED);
+ a = GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905);
+ d = GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8);
+ c = GG(c, d, a, b, x[k + 7], S23, 0x676F02D9);
+ b = GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A);
+ a = HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942);
+ d = HH(d, a, b, c, x[k + 8], S32, 0x8771F681);
+ c = HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122);
+ b = HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C);
+ a = HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44);
+ d = HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9);
+ c = HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60);
+ b = HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70);
+ a = HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6);
+ d = HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA);
+ c = HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085);
+ b = HH(b, c, d, a, x[k + 6], S34, 0x4881D05);
+ a = HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039);
+ d = HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5);
+ c = HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8);
+ b = HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665);
+ a = II(a, b, c, d, x[k + 0], S41, 0xF4292244);
+ d = II(d, a, b, c, x[k + 7], S42, 0x432AFF97);
+ c = II(c, d, a, b, x[k + 14], S43, 0xAB9423A7);
+ b = II(b, c, d, a, x[k + 5], S44, 0xFC93A039);
+ a = II(a, b, c, d, x[k + 12], S41, 0x655B59C3);
+ d = II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92);
+ c = II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D);
+ b = II(b, c, d, a, x[k + 1], S44, 0x85845DD1);
+ a = II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F);
+ d = II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0);
+ c = II(c, d, a, b, x[k + 6], S43, 0xA3014314);
+ b = II(b, c, d, a, x[k + 13], S44, 0x4E0811A1);
+ a = II(a, b, c, d, x[k + 4], S41, 0xF7537E82);
+ d = II(d, a, b, c, x[k + 11], S42, 0xBD3AF235);
+ c = II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB);
+ b = II(b, c, d, a, x[k + 9], S44, 0xEB86D391);
+ a = AddUnsigned(a, AA);
+ b = AddUnsigned(b, BB);
+ c = AddUnsigned(c, CC);
+ d = AddUnsigned(d, DD);
+ }
+
+ var temp = WordToHex(a).concat(WordToHex(b), WordToHex(c), WordToHex(d));
+ return temp;
+ }
+};
+
+GibberishAES.Base64 = {
+ // Takes a Nx16x1 byte array and converts it to Base64
+ chars: [
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+ 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+ 'w', 'x', 'y', 'z', '0', '1', '2', '3',
+ '4', '5', '6', '7', '8', '9', '+', '/'],
+
+ encode: function(b, withBreaks) {
+ var flatArr = [];
+ var b64 = '';
+ totalChunks = Math.floor(b.length * 16 / 3)
+ for (var i = 0; i < b.length * 16; i++) {
+ flatArr.push(b[Math.floor(i / 16)][i % 16]);
+ }
+ for (var i = 0; i < flatArr.length; i = i + 3) {
+ b64 += this.chars[flatArr[i] >> 2];
+ b64 += this.chars[((flatArr[i] & 3) << 4) | (flatArr[i + 1] >> 4)];
+ if (! (flatArr[i + 1] == null)) {
+ b64 += this.chars[((flatArr[i + 1] & 15) << 2) | (flatArr[i + 2] >> 6)];
+ } else {
+ b64 += '='
+ }
+ if (! (flatArr[i + 2] == null)) {
+ b64 += this.chars[flatArr[i + 2] & 63];
+ } else {
+ b64 += '='
+ }
+ }
+ // OpenSSL is super particular about line breaks
+ var broken_b64 = b64.slice(0, 64) + '\n';
+ for (var i = 1; i < (Math.ceil(b64.length / 64)); i++) {
+ broken_b64 += b64.slice(i * 64, i * 64 + 64) + (Math.ceil(b64.length / 64) == i + 1 ? '': '\n');
+ }
+ return broken_b64
+ },
+
+ decode: function(string) {
+ string = string.replace(/\n/g, '');
+ var flatArr = [];
+ var c = [];
+ var b = [];
+ for (var i = 0; i < string.length; i = i + 4) {
+ c[0] = this.chars.indexOf(string.charAt(i));
+ c[1] = this.chars.indexOf(string.charAt(i + 1));
+ c[2] = this.chars.indexOf(string.charAt(i + 2));
+ c[3] = this.chars.indexOf(string.charAt(i + 3));
+
+ b[0] = (c[0] << 2) | (c[1] >> 4);
+ b[1] = ((c[1] & 15) << 4) | (c[2] >> 2);
+ b[2] = ((c[2] & 3) << 6) | c[3];
+ flatArr.push(b[0], b[1], b[2]);
+ }
+ flatArr = flatArr.slice(0, flatArr.length - (flatArr.length % 16));
+ return flatArr;
+ },
+
+};
+
+
+
+
+//
+// JavaScript implementation of Password-Based Key Derivation Function 2
+// (PBKDF2) as defined in RFC 2898.
+// Version 1.1
+// Copyright (c) 2007, Parvez Anandam
+// parvez.anandam@cern.ch
+// http://anandam.name/pbkdf2
+//
+// Distributed under the BSD license
+//
+// (Uses Paul Johnston's excellent SHA-1 JavaScript library sha1.js)
+// Thanks to Felix Gartsman for pointing out a bug in version 1.0
+//
+
+// The four arguments to the constructor of the PBKDF2 object are
+// the password, salt, number of iterations and number of bytes in
+// generated key. This follows the RFC 2898 definition: PBKDF2 (P, S, c, dkLen)
+//
+// The method deriveKey takes two parameters, both callback functions:
+// the first is used to provide status on the computation, the second
+// is called with the result of the computation (the generated key in hex).
+//
+function PBKDF2(password, salt, num_iterations, num_bytes)
+{
+ // Remember the password and salt
+ var m_bpassword = str2binb(password);
+ var m_salt = salt;
+
+ // Total number of iterations
+ var m_total_iterations = num_iterations;
+
+ // Run iterations in chunks instead of all at once, so as to not block.
+ // Define size of chunk here; adjust for slower or faster machines if necessary.
+ var m_iterations_in_chunk = 100;
+
+ // Iteration counter
+ var m_iterations_done = 0;
+
+ // Key length, as number of bytes
+ var m_key_length = num_bytes;
+
+ // The length (number of bytes) of the output of the pseudo-random function.
+ // Since HMAC-SHA1 is the standard, and what is used here, it's 20 bytes.
+ var m_hash_length = 20;
+
+ // Number of hash-sized blocks in the derived key (called 'l' in RFC2898)
+ var m_total_blocks = Math.ceil(m_key_length/m_hash_length);
+
+ // Start computation with the first block
+ var m_current_block = 1;
+
+ // Used in the HMAC-SHA1 computations
+ var m_ipad = new Array(16);
+ var m_opad = new Array(16);
+
+ // This is where the result of the iterations gets sotred
+ var m_buffer = new Array(0x0,0x0,0x0,0x0,0x0);
+
+ // The result
+ var m_key = "";
+
+ // The function to call with the result
+ var m_result_func;
+
+ // The function to call with status after computing every chunk
+ var m_status_func;
+
+ // Set up the HMAC-SHA1 computations
+ if (m_bpassword.length > 16) m_bpassword = core_sha1(m_bpassword, password.length * chrsz);
+ for(var i = 0; i < 16; ++i)
+ {
+ m_ipad[i] = m_bpassword[i] ^ 0x36363636;
+ m_opad[i] = m_bpassword[i] ^ 0x5C5C5C5C;
+ }
+
+ // Starts the computation
+ this.deriveKey = function()
+ {
+ return this.do_PBKDF2_iterations();
+ }
+
+
+ // The workhorse
+ this.do_PBKDF2_iterations = function()
+ {
+ while(1) {
+ var iterations = m_total_iterations;
+
+ for(var i=0; i> 24 & 0xF) +
+ String.fromCharCode(m_current_block >> 16 & 0xF) +
+ String.fromCharCode(m_current_block >> 8 & 0xF) +
+ String.fromCharCode(m_current_block & 0xF);
+
+ m_hash = core_sha1(m_ipad.concat(str2binb(salt_block)), 512 + salt_block.length * 8);
+ m_hash = core_sha1(m_opad.concat(m_hash), 512 + 160);
+ }
+ else {
+ m_hash = core_sha1(m_ipad.concat(m_hash), 512 + m_hash.length * 32);
+ m_hash = core_sha1(m_opad.concat(m_hash), 512 + 160);
+ }
+
+ for(var j=0; j
+// Date Format 1.2.2
+// (c) 2007-2008 Steven Levithan
+// MIT license
+// Includes enhancements by Scott Trenda and Kris Kowal
+//
+// Accepts a date, a mask, or a date and a mask.
+// Returns a formatted version of the given date.
+// The date defaults to the current date/time.
+// The mask defaults to dateFormat.masks.default.
+//
+var dateFormat = function () {
+ var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,
+ timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
+ timezoneClip = /[^-+\dA-Z]/g,
+ pad = function (val, len) {
+ val = String(val);
+ len = len || 2;
+ while (val.length < len) val = "0" + val;
+ return val;
+ };
+
+ // Regexes and supporting functions are cached through closure
+ return function (date, mask, utc) {
+ var dF = dateFormat;
+
+ // You can't provide utc if you skip other args (use the "UTC:" mask prefix)
+ if (arguments.length == 1 && (typeof date == "string" || date instanceof String) && !/\d/.test(date)) {
+ mask = date;
+ date = undefined;
+ }
+
+ // Passing date through Date applies Date.parse, if necessary
+ date = date ? new Date(date) : new Date();
+ if (isNaN(date)) throw new SyntaxError("invalid date");
+
+ mask = String(dF.masks[mask] || mask || dF.masks["default"]);
+
+ // Allow setting the utc argument via the mask
+ if (mask.slice(0, 4) == "UTC:") {
+ mask = mask.slice(4);
+ utc = true;
+ }
+
+ var _ = utc ? "getUTC" : "get",
+ d = date[_ + "Date"](),
+ D = date[_ + "Day"](),
+ m = date[_ + "Month"](),
+ y = date[_ + "FullYear"](),
+ H = date[_ + "Hours"](),
+ M = date[_ + "Minutes"](),
+ s = date[_ + "Seconds"](),
+ L = date[_ + "Milliseconds"](),
+ o = utc ? 0 : date.getTimezoneOffset(),
+ flags = {
+ d: d,
+ dd: pad(d),
+ ddd: dF.i18n.dayNames[D],
+ dddd: dF.i18n.dayNames[D + 7],
+ m: m + 1,
+ mm: pad(m + 1),
+ mmm: dF.i18n.monthNames[m],
+ mmmm: dF.i18n.monthNames[m + 12],
+ yy: String(y).slice(2),
+ yyyy: y,
+ h: H % 12 || 12,
+ hh: pad(H % 12 || 12),
+ H: H,
+ HH: pad(H),
+ M: M,
+ MM: pad(M),
+ s: s,
+ ss: pad(s),
+ l: pad(L, 3),
+ L: pad(L > 99 ? Math.round(L / 10) : L),
+ t: H < 12 ? "a" : "p",
+ tt: H < 12 ? "am" : "pm",
+ T: H < 12 ? "A" : "P",
+ TT: H < 12 ? "AM" : "PM",
+ Z: utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""),
+ o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
+ S: ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
+ };
+
+ return mask.replace(token, function ($0) {
+ return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
+ });
+ };
+}();
+
+// Some common format strings
+dateFormat.masks = {
+ "default": "ddd mmm dd yyyy HH:MM:ss",
+ shortDate: "m/d/yy",
+ mediumDate: "mmm d, yyyy",
+ longDate: "mmmm d, yyyy",
+ fullDate: "dddd, mmmm d, yyyy",
+ shortTime: "h:MM TT",
+ mediumTime: "h:MM:ss TT",
+ longTime: "h:MM:ss TT Z",
+ isoDate: "yyyy-mm-dd",
+ isoTime: "HH:MM:ss",
+ isoDateTime: "yyyy-mm-dd'T'HH:MM:ss",
+ isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"
+};
+
+// Internationalization strings
+dateFormat.i18n = {
+ dayNames: [
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
+ ],
+ monthNames: [
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
+ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
+ ]
+};
+
+// For convenience...
+Date.prototype.format = function (mask, utc) {
+ return dateFormat(this, mask, utc);
+};
diff --git a/scripts/1passwordanywhere.js b/scripts/1passwordanywhere.js
new file mode 100644
index 0000000..e872951
--- /dev/null
+++ b/scripts/1passwordanywhere.js
@@ -0,0 +1,216 @@
+var INDEX_UUID=0, INDEX_TYPE=1, INDEX_NAME=2, INDEX_URL=3, INDEX_DATE=4, INDEX_FOLDER=5, INDEX_PASSWORD_STRENGTH=6, INDEX_TRASHED=7;
+var TYPE_WEBFORMS='webforms.WebForm', TYPE_FOLDERS='system.folder.Regular', TYPE_NOTES='securenotes.SecureNote', TYPE_IDENTITIES='identities.Identity', TYPE_PASSWORDS='passwords.Password', TYPE_WALLET='wallet', TYPE_SOFTWARE_LICENSES='wallet.computer.License', TYPE_TRASHED='trashed', TYPE_ACCOUNT='account', TYPE_ACCOUNT_ONLINESERVICE='wallet.onlineservices.', TYPE_ACCOUNT_COMPUTER='wallet.computer.';
+var ERROR_BAD_DECRYPT = "Decryption failed", ERROR_INVALID_JSON = "Decryption passed but JSON was invalid", ERROR_OK = "OK";
+
+String.prototype.startsWith = function(str) {
+ return (this.match("^"+str) == str);
+};
+
+String.prototype.escapeHTML = function() {
+ return this.replace(/&/g,'&').replace(//g,'>');
+};
+
+function Keychain() {
+ this.AUTOLOCK_LENGTH = 1 * 60 * 1000;
+ this.autoLogoutTime = null;
+ this.contents = { webforms:[], wallet:[], notes:[], identities:[], passwords:[], folders:[] };
+ this.encryptionKeys = null;
+ this._all = null;
+ this.masterPassword = null;
+ this.encryptionKeysLoaded = false;
+}
+
+Keychain.prototype.setEncryptionKeys = function(keys) {
+ this.encryptionKeys = keys;
+ this.encryptionKeysLoaded = true;
+};
+
+Keychain.prototype.verifyPassword = function(password) {
+ GibberishAES.size(128);
+ this.encryptionKeys.decryptedKeys = {};
+ var key = this.decryptEncryptionKey("SL5", password);
+ if (!key) return false;
+
+ this.masterPassword = password;
+ return true;
+};
+
+Keychain.prototype.decryptEncryptionKey = function(sl, password) {
+ for (var i=0; i < this.encryptionKeys["list"].length; i++) {
+ var item = this.encryptionKeys["list"][i];
+
+ if (item['identifier'] == this.encryptionKeys[sl]) {
+ var iterations = parseInt(item['iterations'] || "0", 10);
+ if (iterations < 1000) iterations = 1000;
+
+ var decryptedKey = GibberishAES.decryptUsingPBKDF2(item["data"], password, iterations);
+ if (!decryptedKey) return null;
+
+ var verification = GibberishAES.decryptBase64UsingKey(item["validation"],GibberishAES.s2a(decryptedKey));
+ if (verification != decryptedKey) return null;
+
+ this.encryptionKeys.decryptedKeys[sl] = decryptedKey;
+ return decryptedKey;
+ }
+ }
+
+ return null;
+};
+
+Keychain.prototype.keyForItem = function(item) {
+ if (item.securityLevel === null) {
+ return this.encryptionKeys.decryptedKeys["SL5"];
+ }
+
+ var key = this.encryptionKeys.decryptedKeys[item.securityLevel];
+ if (!key) {
+ key = this.decryptEncryptionKey(item.securityLevel, this.masterPassword);
+ }
+ return key;
+};
+
+Keychain.prototype.rescheduleAutoLogout = function () {
+ this.autoLogoutTime = new Date().getTime() + this.AUTOLOCK_LENGTH;
+};
+
+Keychain.prototype.setContents = function(itemArray) {
+ this._all = [];
+
+ this.contents[TYPE_WEBFORMS] = [];
+ this.contents[TYPE_NOTES] = [];
+ this.contents[TYPE_WALLET] = [];
+ this.contents[TYPE_PASSWORDS] = [];
+ this.contents[TYPE_IDENTITIES] = [];
+ this.contents[TYPE_SOFTWARE_LICENSES] = [];
+ this.contents['folders'] = [];
+ this.contents[TYPE_ACCOUNT] = [];
+ this.contents[TYPE_TRASHED] = [];
+
+ for (var itemIndex in itemArray) {
+ var item = new KeychainItemOverview(itemArray[itemIndex]);
+ if (item.type.startsWith("system.")) continue;
+
+ this._all[item.uuid] = item;
+
+ var category = null;
+ if (item.trashed == "Y") {
+ category = TYPE_TRASHED;
+ }
+ else {
+ if (item.type == TYPE_SOFTWARE_LICENSES) category = TYPE_SOFTWARE_LICENSES;
+ else if (item.type == TYPE_WEBFORMS) category = TYPE_WEBFORMS;
+ else if (item.type == TYPE_NOTES) category = TYPE_NOTES;
+ else if (item.type == TYPE_IDENTITIES) category = TYPE_IDENTITIES;
+ else if (item.type == TYPE_IDENTITIES) category = TYPE_IDENTITIES;
+ else if (item.type == TYPE_PASSWORDS) category = TYPE_PASSWORDS;
+ else if (item.type.startsWith(TYPE_FOLDERS)) category = 'folders';
+ else if (item.type.startsWith("wallet.membership")) category = TYPE_WALLET;
+ else if (item.type.startsWith("wallet.financial")) category = TYPE_WALLET;
+ else if (item.type.startsWith("wallet.government")) category = TYPE_WALLET;
+ }
+
+ if (category === null) category = TYPE_ACCOUNT;
+
+ var itemsByType = this.contents[category];
+ if (!itemsByType) {
+ alert(category);
+ }
+ itemsByType.push(item);
+ }
+
+ this.rescheduleAutoLogout();
+
+ window.setTimeout(this._autoLogout, 1000);
+};
+
+Keychain.prototype.itemsOfType = function(name) {
+ return this.contents[name];
+};
+
+Keychain.prototype.itemWithUuid = function(uuid) {
+ return this._all[uuid];
+};
+
+Keychain.prototype._autoLogout = function() {
+ return;
+ var now = new Date();
+
+ if (now.getTime() < this.autoLogoutTime) {
+ window.setTimeout(this._autoLogout, 1000);
+ return;
+ }
+ logout(true);
+};
+
+Keychain.prototype.lock = function() {
+ if (this.encryptionKeys) {
+ this.encryptionKeys.decryptedKeys = null;
+ }
+ this.masterPassword = null;
+ this.encryptionKeysLoaded = false;
+};
+
+function KeychainItemOverview(data) {
+ this.uuid = data[INDEX_UUID];
+ this.type = data[INDEX_TYPE];
+ this.title = data[INDEX_NAME];
+ this.domain = data[INDEX_URL];
+ this.updatedAtMs = data[INDEX_DATE] * 1000;
+ this.trashed = data[INDEX_TRASHED];
+
+ var date = new Date();
+ date.setTime(this.updatedAtMs);
+ this.updatedAt = date.format("mmm d, yyyy, h:MM:ss TT");
+}
+
+KeychainItemOverview.prototype.matches = function(s) {
+ if (this.title.toLowerCase().indexOf(s) >= 0) return true;
+ if (this.domain.toLowerCase().indexOf(s) >= 0) return true;
+ return false;
+};
+
+function KeychainItem(data, keychain) {
+ this.updatedAt = null; // TODO -- confirm that it can be deleted
+
+ this.data = data;
+ this.folderUuid = data.folderUuid;
+ this.encrypted_contents = data.encrypted;
+ this.decrypted = false;
+ this.decrypted_secure_contents = null;
+
+ this.uuid = data.uuid;
+ this.type = data.typeName;
+ this.title = data.title;
+ this.domain = data.location;
+
+ this.securityLevel = data.securityLevel;
+ if (!data.securityLevel && data.openContents) {
+ this.securityLevel = data.openContents.securityLevel;
+ }
+
+ if (!this.securityLevel) {
+ this.securityLevel = "SL5";
+ }
+
+ this.updatedAtMs = data.updatedAt * 1000;
+
+ folderName = keychain.itemWithUuid(this.folderUuid);
+ if (!folderName) folderName = "None";
+}
+
+KeychainItem.prototype.decrypt = function(keychain) {
+ GibberishAES.size(128);
+ var plainText = null;
+ var key = keychain.keyForItem(this);
+ plainText = GibberishAES.decryptBase64UsingKey(this.encrypted_contents, GibberishAES.s2a(key));
+ if (!plainText) {
+ return ERROR_BAD_DECRYPT;
+ }
+
+ // Decode UTF encoding that OpenSSL uses.
+ plainText = decodeURIComponent(escape(plainText));
+ var pt = '(' + plainText + ');';
+ try { this.decrypted_secure_contents = eval(pt); }
+ catch (e) { return ERROR_INVALID_JSON; }
+ return ERROR_OK;
+};
diff --git a/scripts/OnePassword.js b/scripts/OnePassword.js
new file mode 100644
index 0000000..981c6b7
--- /dev/null
+++ b/scripts/OnePassword.js
@@ -0,0 +1,101 @@
+(function (window) {
+ var keychain = null;
+
+ function OnePassword (url) {
+ this.baseUrl = url;
+ keychain = new Keychain();
+ }
+
+ OnePassword.prototype.load = function () {
+ var deferred = Q.defer();
+
+ Q.all([this.getContents(), this.getEncryptionKeys()]).then(function () {
+ deferred.resolve();
+ });
+
+ return deferred.promise;
+ };
+ OnePassword.prototype.getContents = function () {
+ var deferred = Q.defer();
+
+ getJson(this.baseUrl + "contents.js").then(function (contents) {
+ keychain.setContents(contents);
+ deferred.resolve();
+ }, function () {
+ deferred.reject();
+ });
+
+ return deferred.promise;
+ };
+ OnePassword.prototype.getEncryptionKeys = function () {
+ var deferred = Q.defer();
+
+ getJson(this.baseUrl + "encryptionKeys.js").then(function (keys) {
+ keychain.setEncryptionKeys(keys);
+ deferred.resolve();
+ }, function () {
+ deferred.reject();
+ });
+
+ return deferred.promise;
+ };
+
+ OnePassword.prototype.verifyPassword = function (password) {
+ return keychain.verifyPassword(password);
+ };
+
+ OnePassword.prototype.getKeychainItem = function (entryid) {
+ var deferred = Q.defer();
+
+ getJson(this.baseUrl + entryid + ".1password").then(function (entry) {
+ deferred.resolve(new KeychainItem(entry, keychain));
+ });
+
+ return deferred.promise;
+ };
+
+ OnePassword.prototype.webformsFromDomain = function (domain) {
+ var ret = [];
+ for (var index in keychain.contents[TYPE_WEBFORMS]) {
+ var webform = keychain.contents[TYPE_WEBFORMS][index];
+ var url = new URL(webform.domain);
+ var webformDomain = tld.getDomain(url.hostname);
+
+ if (domain === webformDomain) {
+ ret.push(webform);
+ }
+ }
+
+ return ret;
+ };
+
+ OnePassword.prototype.decryptKeychainItem = function (keychainItem) {
+ keychainItem.decrypt(keychain);
+ };
+
+ var getJson = function (url, cb) {
+ var deferred = Q.defer();
+
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", url, true);
+ xhr.onload = function (e) {
+ if (xhr.readyState === 4) {
+ if (xhr.status === 200) {
+ deferred.resolve(JSON.parse(xhr.responseText));
+ } else {
+ deferred.reject(new Error(xhr.statusText));
+ }
+ }
+ };
+
+ xhr.onerror = function () {
+ cb(xhr.statusText);
+ };
+
+ xhr.send();
+
+ return deferred.promise;
+ };
+
+ window.OnePassword = OnePassword;
+})(this);
diff --git a/scripts/fillForm.js b/scripts/fillForm.js
new file mode 100644
index 0000000..12d1c93
--- /dev/null
+++ b/scripts/fillForm.js
@@ -0,0 +1,85 @@
+(function () {
+ var USERNAME_FIELDS = ["username", "user"];
+ var PASSWORD_FIELDS = ["password", "pass"];
+
+ function fillForm (keychainItem) {
+ var designations = getDesignations(keychainItem.fields);
+
+ if ("username" in designations) {
+ fillField(designations.username, USERNAME_FIELDS);
+ }
+ if ("password" in designations) {
+ fillField(designations.password, PASSWORD_FIELDS);
+ }
+ }
+
+ function getDesignations (fields) {
+ var designations = {};
+
+ for (var index in fields) {
+ var field = fields[index];
+
+ if ("designation" in field) {
+ designations[field.designation] = field;
+ }
+ }
+
+ return designations;
+ }
+
+ function fillField(field, backupNames) {
+ var element = null;
+
+ // see if the element exist on the page
+ if ("id" in field) {
+ element = document.getElementById(field.id);
+ }
+ if ("name" in field) {
+ backupNames.unshift(field.name);
+ }
+
+ if (!element) { // no element with that id
+ for (var index in backupNames) {
+ var name = backupNames[index];
+
+ if (element) {
+ break; // found a match!
+ }
+
+ var selectorElement = "input";
+ var selectorAttributes = [];
+ if (field.type === "T") {
+ selectorAttributes.push(["name", name]);
+ }if (field.type === "P") {
+ selectorAttributes.push(["name", name]);
+ }
+
+ var selector = selectorElement + "[";
+ var divider = "";
+ for (var attIndex in selectorAttributes) {
+ var selectorAttribute = selectorAttributes[attIndex];
+ selector += divider + "" + selectorAttribute[0] + "='" + selectorAttribute[1] + "'";
+ divider = ",";
+ }
+ selector += "]";
+
+ element = document.querySelector(selector);
+ }
+ }
+
+ if (!element) { // could not find any from backup
+
+ }
+
+
+ if (element) {
+ element.value = field.value;
+ }
+ }
+
+ chrome.runtime.onMessage.addListener(
+ function(request, sender, sendResponse) {
+ fillForm(request);
+ }
+ );
+})();
diff --git a/scripts/options.js b/scripts/options.js
new file mode 100644
index 0000000..fc08b50
--- /dev/null
+++ b/scripts/options.js
@@ -0,0 +1,25 @@
+function save () {
+ var baseurl = document.getElementById("baseurl").value;
+
+ chrome.storage.sync.set({
+ "baseurl": baseurl
+ }, function () {
+ var status = document.getElementById("status");
+ status.textContent = "Options saved";
+ setTimeout(function () {
+ status.textContent = "";
+ }, 750);
+ });
+}
+
+function restore () {
+ // default: https://dl-web.dropbox.com/get/1password/1Password.agilekeychain/data/default/
+ chrome.storage.sync.get({
+ "baseurl": "https://dl-web.dropbox.com/get/1password/1Password.agilekeychain/data/default/"
+ }, function (items) {
+ document.getElementById("baseurl").value = items.baseurl;
+ });
+}
+
+document.addEventListener("DOMContentLoaded", restore);
+document.getElementById("save").addEventListener("click", save);
diff --git a/scripts/popup.js b/scripts/popup.js
new file mode 100644
index 0000000..41ee053
--- /dev/null
+++ b/scripts/popup.js
@@ -0,0 +1,88 @@
+(function (window) {
+ var onepassword = null;
+ var tab = null;
+
+ function init () {
+ Q.all([initOnePassword(), getActiveTab()]).spread(function (op, t) {
+ onepassword = op;
+ tab = t;
+ });
+ }
+
+ function initOnePassword () {
+ var deferred = Q.defer();
+
+ chrome.storage.sync.get({
+ "baseurl": "https://dl-web.dropbox.com/get/1password/1Password.agilekeychain/data/default/"
+ }, function (items) {
+ onepassword = new window.OnePassword(items.baseurl);
+ onepassword.load().then(function () {
+ btnVerify.disabled = false;
+ });
+
+ deferred.resolve(onepassword);
+ });
+
+ return deferred.promise;
+ }
+
+ function getCurrentDomain () {
+ var url = new URL(tab.url);
+ return tld.getDomain(url.hostname);
+ }
+
+ function verify (event) {
+ event.preventDefault();
+
+ var password = document.getElementById("masterpassword").value;
+ if (onepassword.verifyPassword(password)) {
+ var domain = getCurrentDomain();
+ var webforms = onepassword.webformsFromDomain(domain);
+ fillForm(webforms[0]);
+ //window.close();
+ } else {
+ alert("wrong password!");
+ }
+ }
+
+ function injectFillFormScript () {
+ var deferred = Q.defer();
+
+ chrome.tabs.executeScript({
+ file: "scripts/fillForm.js",
+ }, function (results) {
+ deferred.resolve();
+ });
+
+ return deferred.promise;
+ }
+
+ function fillForm (webform) {
+ Q.all([injectFillFormScript(), onepassword.getKeychainItem(webform.uuid)]).spread(function (result, item) {
+ onepassword.decryptKeychainItem(item);
+
+ chrome.tabs.sendMessage(tab.id, item.decrypted_secure_contents);
+ });
+ }
+
+ function getActiveTab() {
+ var deferred = Q.defer();
+
+ chrome.tabs.query({
+ currentWindow: true, active: true
+ }, function (tabs) {
+ deferred.resolve(tabs[0]);
+ });
+
+ return deferred.promise;
+ }
+
+
+ btnVerify = document.getElementById("btnVerify");
+ btnVerify.disabled = true;
+ frmVerify = document.getElementById("frmVerify");
+
+ document.addEventListener("DOMContentLoaded", init);
+ frmVerify.addEventListener("submit", verify);
+
+})(this);
diff --git a/scripts/q.js b/scripts/q.js
new file mode 100644
index 0000000..5cbe777
--- /dev/null
+++ b/scripts/q.js
@@ -0,0 +1,1751 @@
+// vim:ts=4:sts=4:sw=4:
+/*!
+ *
+ * Copyright 2009-2012 Kris Kowal under the terms of the MIT
+ * license found at http://github.com/kriskowal/q/raw/master/LICENSE
+ *
+ * With parts by Tyler Close
+ * Copyright 2007-2009 Tyler Close under the terms of the MIT X license found
+ * at http://www.opensource.org/licenses/mit-license.html
+ * Forked at ref_send.js version: 2009-05-11
+ *
+ * With parts by Mark Miller
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+(function (definition) {
+ // Turn off strict mode for this function so we can assign to global.Q
+ /* jshint strict: false */
+
+ // This file will function properly as a