;(function() { var util = {}; util.low = function(byte) { return byte & 0xf; }; util.high = function(byte) { return byte >>> 4 & 0xf; }; util.madd = function(a, b) { // TODO: rename to madd256 return (a + b) % N; // return (a + b) & 0xff; // when N = 256, 0xff = N - 1 }; util.msub = function(a, b) {// TODO: rename to msub256 return util.madd(N, a - b); }; util.swap = function(lst, p1, p2) { var tmp = lst[p1]; lst[p1] = lst[p2]; lst[p2] = tmp; }; util.gcd = function(a, b){ var t; while (b !== 0) { t = b; b = a % b; a = t; } return a; }; var N = 256; var N_OVER_TWO_FLOOR = Math.floor(N / 2); var TWO_N = 2 * N; var spritz = {}; spritz._util = util; spritz._initializeState = function _initializeState() { var state = {}; state.i = 0; state.j = 0; state.k = 0; state.z = 0; state.a = 0; state.w = 1; state.S = []; for (var i = 0; i < N; i++) { state.S[i] = i; } return state; }; spritz._absorb = function _absorb(I, state){ var v; /* basic validation of I consider bounds-checking and deep-checking of each N-value such that they are in the valid range (0 <= x < N) */ if(!(Array.isArray(I) && I.length > 0)){ return false; } for(v = 0; v < I.length; v++){ spritz._absorbByte(I[v], state); } return true; }; spritz._absorbByte = function _absorbByte(b, state) { spritz._absorbNibble(util.low(b), state); spritz._absorbNibble(util.high(b), state); }; spritz._absorbNibble = function _absorbNibble(x, state) { if (state.a === N_OVER_TWO_FLOOR){ spritz.shuffle(state); } util.swap(state.S, state.a, util.madd(N_OVER_TWO_FLOOR, x)); state.a = util.madd(state.a, 1); }; spritz._absorbStop = function _absorbStop(state){ if(state.a === N_OVER_TWO_FLOOR){ spritz._shuffle(state); } state.a = util.madd(state.a, 1); }; spritz._shuffle = function _shuffle(state){ spritz._whip(TWO_N, state); spritz._crush(state); spritz._whip(TWO_N, state); spritz._crush(state); spritz._whip(TWO_N, state); state.a = 0; }; spritz._whip = function _whip(r, state) { for (var i = 0; i < r; i++) { spritz._update(state); } do { state.w = util.madd(state.w, 1); } while (util.gcd(state.w, N) !== 1); // NB. a simple-case assumption is that if N is a power of 2 then one could instead use: // w = madd(w, 2); }; spritz._crush = function _crush(state) { var index; for (var i = 0; i < N_OVER_TWO_FLOOR; i++) { index = N - i - 1; if (state.S[i] > state.S[index]) { util.swap(state.S, i, index); } } }; spritz._update = function _update(state) { //done state.i = util.madd(state.i, state.w); state.j = util.madd(state.k, state.S[util.madd(state.j, state.S[state.i])]); state.k = util.madd(state.i + state.k, state.S[state.j]); util.swap(state.S, state.i, state.j); }; spritz._squeeze = function _squeeze(r, state) { if (state.a > 0) { spritz._shuffle(state); } var P = []; for (var i = 0; i < r; i++) { P[i] = spritz._drip(state); } return P; }; spritz._drip = function _drip(state){ if (state.a > 0) { spritz._shuffle(state); } spritz._update(state); return spritz._output(state); }; spritz._output = function _output(state) { var idx = util.madd(state.z, state.k); idx = util.madd(state.i, state.S[idx]); idx = util.madd(state.j, state.S[idx]); state.z = state.S[idx]; return state.z; }; spritz._keySetup = function _keySetup(K) { var state = spritz._initializeState(); spritz._absorb(K, state); return state; }; spritz.stringToUtf8ByteArray = function stringToUtf8ByteArray(utf8Array){ var utf8 = unescape(encodeURIComponent(utf8Array)); var arr = []; for (var i = 0; i < utf8.length; i++) { arr.push(utf8.charCodeAt(i)); } return arr; }; spritz.utf8ByteArrayToString = function utf8ByteArrayToString(utf8Array){ var ret = ""; for(var i = 0; i < utf8Array.length; i++){ ret += String.fromCharCode(utf8Array[i]); } return decodeURIComponent(escape(ret)); }; spritz.hash = function hash(M, r){ if(typeof M == 'string'){ return spritz.hash(spritz.stringToUtf8ByteArray(M), r); } var state = spritz._initializeState(); spritz._absorb(M, state); spritz._absorbStop(state); spritz._absorb([r & 0xff], state); // NB. restricted(!) to 255-byte hashes return spritz._squeeze(r, state); }; spritz.encrypt = function encrypt(K, M) { var C = [], stream , i; var state = spritz._keySetup(K); stream = spritz._squeeze(M.length, state); for (i = 0; i < M.length; i++) { C[i] = util.madd(M[i], stream[i]); } return C; }; spritz.decrypt = function decrypt(K, C) { var M = [] , stream , i; var state = spritz._keySetup(K); stream = spritz._squeeze(C.length, state); for (i = 0; i < C.length; i++) { M[i] = util.msub(C[i], stream[i]); } return M; }; // Export spritz as lodash 4.5.0. var objectTypes = { 'function': true, 'object': true }; function checkGlobal(value) { return (value && value.Object === Object) ? value : null; } var freeWindow = checkGlobal(objectTypes[typeof window] && window); var freeSelf = checkGlobal(objectTypes[typeof self] && self); var freeGlobal = checkGlobal(freeExports && freeModule && typeof global == 'object' && global); var freeModule = (objectTypes[typeof module] && module && !module.nodeType) ? module : undefined; var freeExports = (objectTypes[typeof exports] && exports && !exports.nodeType) ? exports : undefined; var moduleExports = (freeModule && freeModule.exports === freeExports) ? freeExports: undefined; var thisGlobal = checkGlobal(objectTypes[typeof this] && this); var root = freeGlobal || ((freeWindow !== (thisGlobal && thisGlobal.window)) && freeWindow) || freeSelf || thisGlobal || Function('return this')(); // Expose lodash on the free variable `window` or `self` when available. This // prevents errors in cases where lodash is loaded by a script tag in the presence // of an AMD loader. See http://requirejs.org/docs/errors.html#mismatch for more details. (freeWindow || freeSelf || {}).spritz = spritz; // Some AMD build optimizers like r.js check for condition patterns like the following: if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) { // Define as an anonymous module so, through path mapping, it can be // referenced as the "underscore" module. define(function() { return spritz; }); } // Check for `exports` after `define` in case a build optimizer adds an `exports` object. else if (freeExports && freeModule) { // Export for Node.js. if (moduleExports) { freeModule.exports = spritz; } // Export for CommonJS support. freeExports.spritz = spritz; } else { // Export to the global object. root.spritz = spritz; } }.call(this)); // close the prefix