Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

add js library files

  • Loading branch information...
commit 99c719c7922900cb6cc72118781ee720eb32eab2 1 parent e8056e3
Jeff Guo authored
402 lib/AES.js
... ... @@ -0,0 +1,402 @@
  1 +(function(){
  2 +
  3 +var C = (typeof window === 'undefined') ? require('./Crypto').Crypto : window.Crypto;
  4 +
  5 +// Shortcuts
  6 +var util = C.util,
  7 + charenc = C.charenc,
  8 + UTF8 = charenc.UTF8;
  9 +
  10 +// Precomputed SBOX
  11 +var SBOX = [ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
  12 + 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
  13 + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
  14 + 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
  15 + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
  16 + 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
  17 + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
  18 + 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
  19 + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
  20 + 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
  21 + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
  22 + 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
  23 + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
  24 + 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
  25 + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
  26 + 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
  27 + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
  28 + 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
  29 + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
  30 + 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
  31 + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
  32 + 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
  33 + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
  34 + 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
  35 + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
  36 + 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
  37 + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
  38 + 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
  39 + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
  40 + 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
  41 + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
  42 + 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 ];
  43 +
  44 +// Compute inverse SBOX lookup table
  45 +for (var INVSBOX = [], i = 0; i < 256; i++) INVSBOX[SBOX[i]] = i;
  46 +
  47 +// Compute mulitplication in GF(2^8) lookup tables
  48 +var MULT2 = [],
  49 + MULT3 = [],
  50 + MULT9 = [],
  51 + MULTB = [],
  52 + MULTD = [],
  53 + MULTE = [];
  54 +
  55 +function xtime(a, b) {
  56 + for (var result = 0, i = 0; i < 8; i++) {
  57 + if (b & 1) result ^= a;
  58 + var hiBitSet = a & 0x80;
  59 + a = (a << 1) & 0xFF;
  60 + if (hiBitSet) a ^= 0x1b;
  61 + b >>>= 1;
  62 + }
  63 + return result;
  64 +}
  65 +
  66 +for (var i = 0; i < 256; i++) {
  67 + MULT2[i] = xtime(i,2);
  68 + MULT3[i] = xtime(i,3);
  69 + MULT9[i] = xtime(i,9);
  70 + MULTB[i] = xtime(i,0xB);
  71 + MULTD[i] = xtime(i,0xD);
  72 + MULTE[i] = xtime(i,0xE);
  73 +}
  74 +
  75 +// Precomputed RCon lookup
  76 +var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36];
  77 +
  78 +// Inner state
  79 +var state = [[], [], [], []],
  80 + keylength,
  81 + nrounds,
  82 + keyschedule;
  83 +
  84 +var AES = C.AES = {
  85 +
  86 + /**
  87 + * Public API
  88 + */
  89 +
  90 + encrypt: function (message, password, options) {
  91 +
  92 + options = options || {};
  93 +
  94 + // Determine mode
  95 + var mode = options.mode || new C.mode.OFB;
  96 +
  97 + // Allow mode to override options
  98 + if (mode.fixOptions) mode.fixOptions(options);
  99 +
  100 + var
  101 +
  102 + // Convert to bytes if message is a string
  103 + m = (
  104 + message.constructor == String ?
  105 + UTF8.stringToBytes(message) :
  106 + message
  107 + ),
  108 +
  109 + // Generate random IV
  110 + iv = options.iv || util.randomBytes(AES._blocksize * 4),
  111 +
  112 + // Generate key
  113 + k = (
  114 + password.constructor == String ?
  115 + // Derive key from passphrase
  116 + C.PBKDF2(password, iv, 32, { asBytes: true }) :
  117 + // else, assume byte array representing cryptographic key
  118 + password
  119 + );
  120 +
  121 + // Encrypt
  122 + AES._init(k);
  123 + mode.encrypt(AES, m, iv);
  124 +
  125 + // Return ciphertext
  126 + m = options.iv ? m : iv.concat(m);
  127 + return (options && options.asBytes) ? m : util.bytesToBase64(m);
  128 +
  129 + },
  130 +
  131 + decrypt: function (ciphertext, password, options) {
  132 +
  133 + options = options || {};
  134 +
  135 + // Determine mode
  136 + var mode = options.mode || new C.mode.OFB;
  137 +
  138 + // Allow mode to override options
  139 + if (mode.fixOptions) mode.fixOptions(options);
  140 +
  141 + var
  142 +
  143 + // Convert to bytes if ciphertext is a string
  144 + c = (
  145 + ciphertext.constructor == String ?
  146 + util.base64ToBytes(ciphertext):
  147 + ciphertext
  148 + ),
  149 +
  150 + // Separate IV and message
  151 + iv = options.iv || c.splice(0, AES._blocksize * 4),
  152 +
  153 + // Generate key
  154 + k = (
  155 + password.constructor == String ?
  156 + // Derive key from passphrase
  157 + C.PBKDF2(password, iv, 32, { asBytes: true }) :
  158 + // else, assume byte array representing cryptographic key
  159 + password
  160 + );
  161 +
  162 + // Decrypt
  163 + AES._init(k);
  164 + mode.decrypt(AES, c, iv);
  165 +
  166 + // Return plaintext
  167 + return (options && options.asBytes) ? c : UTF8.bytesToString(c);
  168 +
  169 + },
  170 +
  171 +
  172 + /**
  173 + * Package private methods and properties
  174 + */
  175 +
  176 + _blocksize: 4,
  177 +
  178 + _encryptblock: function (m, offset) {
  179 +
  180 + // Set input
  181 + for (var row = 0; row < AES._blocksize; row++) {
  182 + for (var col = 0; col < 4; col++)
  183 + state[row][col] = m[offset + col * 4 + row];
  184 + }
  185 +
  186 + // Add round key
  187 + for (var row = 0; row < 4; row++) {
  188 + for (var col = 0; col < 4; col++)
  189 + state[row][col] ^= keyschedule[col][row];
  190 + }
  191 +
  192 + for (var round = 1; round < nrounds; round++) {
  193 +
  194 + // Sub bytes
  195 + for (var row = 0; row < 4; row++) {
  196 + for (var col = 0; col < 4; col++)
  197 + state[row][col] = SBOX[state[row][col]];
  198 + }
  199 +
  200 + // Shift rows
  201 + state[1].push(state[1].shift());
  202 + state[2].push(state[2].shift());
  203 + state[2].push(state[2].shift());
  204 + state[3].unshift(state[3].pop());
  205 +
  206 + // Mix columns
  207 + for (var col = 0; col < 4; col++) {
  208 +
  209 + var s0 = state[0][col],
  210 + s1 = state[1][col],
  211 + s2 = state[2][col],
  212 + s3 = state[3][col];
  213 +
  214 + state[0][col] = MULT2[s0] ^ MULT3[s1] ^ s2 ^ s3;
  215 + state[1][col] = s0 ^ MULT2[s1] ^ MULT3[s2] ^ s3;
  216 + state[2][col] = s0 ^ s1 ^ MULT2[s2] ^ MULT3[s3];
  217 + state[3][col] = MULT3[s0] ^ s1 ^ s2 ^ MULT2[s3];
  218 +
  219 + }
  220 +
  221 + // Add round key
  222 + for (var row = 0; row < 4; row++) {
  223 + for (var col = 0; col < 4; col++)
  224 + state[row][col] ^= keyschedule[round * 4 + col][row];
  225 + }
  226 +
  227 + }
  228 +
  229 + // Sub bytes
  230 + for (var row = 0; row < 4; row++) {
  231 + for (var col = 0; col < 4; col++)
  232 + state[row][col] = SBOX[state[row][col]];
  233 + }
  234 +
  235 + // Shift rows
  236 + state[1].push(state[1].shift());
  237 + state[2].push(state[2].shift());
  238 + state[2].push(state[2].shift());
  239 + state[3].unshift(state[3].pop());
  240 +
  241 + // Add round key
  242 + for (var row = 0; row < 4; row++) {
  243 + for (var col = 0; col < 4; col++)
  244 + state[row][col] ^= keyschedule[nrounds * 4 + col][row];
  245 + }
  246 +
  247 + // Set output
  248 + for (var row = 0; row < AES._blocksize; row++) {
  249 + for (var col = 0; col < 4; col++)
  250 + m[offset + col * 4 + row] = state[row][col];
  251 + }
  252 +
  253 + },
  254 +
  255 + _decryptblock: function (c, offset) {
  256 +
  257 + // Set input
  258 + for (var row = 0; row < AES._blocksize; row++) {
  259 + for (var col = 0; col < 4; col++)
  260 + state[row][col] = c[offset + col * 4 + row];
  261 + }
  262 +
  263 + // Add round key
  264 + for (var row = 0; row < 4; row++) {
  265 + for (var col = 0; col < 4; col++)
  266 + state[row][col] ^= keyschedule[nrounds * 4 + col][row];
  267 + }
  268 +
  269 + for (var round = 1; round < nrounds; round++) {
  270 +
  271 + // Inv shift rows
  272 + state[1].unshift(state[1].pop());
  273 + state[2].push(state[2].shift());
  274 + state[2].push(state[2].shift());
  275 + state[3].push(state[3].shift());
  276 +
  277 + // Inv sub bytes
  278 + for (var row = 0; row < 4; row++) {
  279 + for (var col = 0; col < 4; col++)
  280 + state[row][col] = INVSBOX[state[row][col]];
  281 + }
  282 +
  283 + // Add round key
  284 + for (var row = 0; row < 4; row++) {
  285 + for (var col = 0; col < 4; col++)
  286 + state[row][col] ^= keyschedule[(nrounds - round) * 4 + col][row];
  287 + }
  288 +
  289 + // Inv mix columns
  290 + for (var col = 0; col < 4; col++) {
  291 +
  292 + var s0 = state[0][col],
  293 + s1 = state[1][col],
  294 + s2 = state[2][col],
  295 + s3 = state[3][col];
  296 +
  297 + state[0][col] = MULTE[s0] ^ MULTB[s1] ^ MULTD[s2] ^ MULT9[s3];
  298 + state[1][col] = MULT9[s0] ^ MULTE[s1] ^ MULTB[s2] ^ MULTD[s3];
  299 + state[2][col] = MULTD[s0] ^ MULT9[s1] ^ MULTE[s2] ^ MULTB[s3];
  300 + state[3][col] = MULTB[s0] ^ MULTD[s1] ^ MULT9[s2] ^ MULTE[s3];
  301 +
  302 + }
  303 +
  304 + }
  305 +
  306 + // Inv shift rows
  307 + state[1].unshift(state[1].pop());
  308 + state[2].push(state[2].shift());
  309 + state[2].push(state[2].shift());
  310 + state[3].push(state[3].shift());
  311 +
  312 + // Inv sub bytes
  313 + for (var row = 0; row < 4; row++) {
  314 + for (var col = 0; col < 4; col++)
  315 + state[row][col] = INVSBOX[state[row][col]];
  316 + }
  317 +
  318 + // Add round key
  319 + for (var row = 0; row < 4; row++) {
  320 + for (var col = 0; col < 4; col++)
  321 + state[row][col] ^= keyschedule[col][row];
  322 + }
  323 +
  324 + // Set output
  325 + for (var row = 0; row < AES._blocksize; row++) {
  326 + for (var col = 0; col < 4; col++)
  327 + c[offset + col * 4 + row] = state[row][col];
  328 + }
  329 +
  330 + },
  331 +
  332 +
  333 + /**
  334 + * Private methods
  335 + */
  336 +
  337 + _init: function (k) {
  338 + keylength = k.length / 4;
  339 + nrounds = keylength + 6;
  340 + AES._keyexpansion(k);
  341 + },
  342 +
  343 + // Generate a key schedule
  344 + _keyexpansion: function (k) {
  345 +
  346 + keyschedule = [];
  347 +
  348 + for (var row = 0; row < keylength; row++) {
  349 + keyschedule[row] = [
  350 + k[row * 4],
  351 + k[row * 4 + 1],
  352 + k[row * 4 + 2],
  353 + k[row * 4 + 3]
  354 + ];
  355 + }
  356 +
  357 + for (var row = keylength; row < AES._blocksize * (nrounds + 1); row++) {
  358 +
  359 + var temp = [
  360 + keyschedule[row - 1][0],
  361 + keyschedule[row - 1][1],
  362 + keyschedule[row - 1][2],
  363 + keyschedule[row - 1][3]
  364 + ];
  365 +
  366 + if (row % keylength == 0) {
  367 +
  368 + // Rot word
  369 + temp.push(temp.shift());
  370 +
  371 + // Sub word
  372 + temp[0] = SBOX[temp[0]];
  373 + temp[1] = SBOX[temp[1]];
  374 + temp[2] = SBOX[temp[2]];
  375 + temp[3] = SBOX[temp[3]];
  376 +
  377 + temp[0] ^= RCON[row / keylength];
  378 +
  379 + } else if (keylength > 6 && row % keylength == 4) {
  380 +
  381 + // Sub word
  382 + temp[0] = SBOX[temp[0]];
  383 + temp[1] = SBOX[temp[1]];
  384 + temp[2] = SBOX[temp[2]];
  385 + temp[3] = SBOX[temp[3]];
  386 +
  387 + }
  388 +
  389 + keyschedule[row] = [
  390 + keyschedule[row - keylength][0] ^ temp[0],
  391 + keyschedule[row - keylength][1] ^ temp[1],
  392 + keyschedule[row - keylength][2] ^ temp[2],
  393 + keyschedule[row - keylength][3] ^ temp[3]
  394 + ];
  395 +
  396 + }
  397 +
  398 + }
  399 +
  400 +};
  401 +
  402 +})();
378 lib/BlockModes.js
... ... @@ -0,0 +1,378 @@
  1 +/*!
  2 + * Crypto-JS contribution from Simon Greatrix
  3 + */
  4 +
  5 +(function(){
  6 +
  7 +var C = (typeof window === 'undefined') ? require('./Crypto').Crypto : window.Crypto;
  8 +
  9 +// Create pad namespace
  10 +var C_pad = C.pad = {};
  11 +
  12 +// Calculate the number of padding bytes required.
  13 +function _requiredPadding(cipher, message) {
  14 + var blockSizeInBytes = cipher._blocksize * 4;
  15 + var reqd = blockSizeInBytes - message.length % blockSizeInBytes;
  16 + return reqd;
  17 +};
  18 +
  19 +// Remove padding when the final byte gives the number of padding bytes.
  20 +var _unpadLength = function (message) {
  21 + var pad = message.pop();
  22 + for (var i = 1; i < pad; i++) {
  23 + message.pop();
  24 + }
  25 + };
  26 +
  27 +// No-operation padding, used for stream ciphers
  28 +C_pad.NoPadding = {
  29 + pad : function (cipher,message) {},
  30 + unpad : function (message) {}
  31 + };
  32 +
  33 +// Zero Padding.
  34 +//
  35 +// If the message is not an exact number of blocks, the final block is
  36 +// completed with 0x00 bytes. There is no unpadding.
  37 +C_pad.ZeroPadding = {
  38 + pad : function (cipher, message) {
  39 + var blockSizeInBytes = cipher._blocksize * 4;
  40 + var reqd = message.length % blockSizeInBytes;
  41 + if( reqd!=0 ) {
  42 + for(reqd = blockSizeInBytes - reqd; reqd>0; reqd--) {
  43 + message.push(0x00);
  44 + }
  45 + }
  46 + },
  47 +
  48 + unpad : function (message) {}
  49 +};
  50 +
  51 +// ISO/IEC 7816-4 padding.
  52 +//
  53 +// Pads the plain text with an 0x80 byte followed by as many 0x00
  54 +// bytes are required to complete the block.
  55 +C_pad.iso7816 = {
  56 + pad : function (cipher, message) {
  57 + var reqd = _requiredPadding(cipher, message);
  58 + message.push(0x80);
  59 + for (; reqd > 1; reqd--) {
  60 + message.push(0x00);
  61 + }
  62 + },
  63 +
  64 + unpad : function (message) {
  65 + while (message.pop() != 0x80) {}
  66 + }
  67 +};
  68 +
  69 +// ANSI X.923 padding
  70 +//
  71 +// The final block is padded with zeros except for the last byte of the
  72 +// last block which contains the number of padding bytes.
  73 +C_pad.ansix923 = {
  74 + pad : function (cipher, message) {
  75 + var reqd = _requiredPadding(cipher, message);
  76 + for (var i = 1; i < reqd; i++) {
  77 + message.push(0x00);
  78 + }
  79 + message.push(reqd);
  80 + },
  81 +
  82 + unpad : _unpadLength
  83 +};
  84 +
  85 +// ISO 10126
  86 +//
  87 +// The final block is padded with random bytes except for the last
  88 +// byte of the last block which contains the number of padding bytes.
  89 +C_pad.iso10126 = {
  90 + pad : function (cipher, message) {
  91 + var reqd = _requiredPadding(cipher, message);
  92 + for (var i = 1; i < reqd; i++) {
  93 + message.push(Math.floor(Math.random() * 256));
  94 + }
  95 + message.push(reqd);
  96 + },
  97 +
  98 + unpad : _unpadLength
  99 +};
  100 +
  101 +// PKCS7 padding
  102 +//
  103 +// PKCS7 is described in RFC 5652. Padding is in whole bytes. The
  104 +// value of each added byte is the number of bytes that are added,
  105 +// i.e. N bytes, each of value N are added.
  106 +C_pad.pkcs7 = {
  107 + pad : function (cipher, message) {
  108 + var reqd = _requiredPadding(cipher, message);
  109 + for (var i = 0; i < reqd; i++) {
  110 + message.push(reqd);
  111 + }
  112 + },
  113 +
  114 + unpad : _unpadLength
  115 +};
  116 +
  117 +// Create mode namespace
  118 +var C_mode = C.mode = {};
  119 +
  120 +/**
  121 + * Mode base "class".
  122 + */
  123 +var Mode = C_mode.Mode = function (padding) {
  124 + if (padding) {
  125 + this._padding = padding;
  126 + }
  127 +};
  128 +
  129 +Mode.prototype = {
  130 + encrypt: function (cipher, m, iv) {
  131 + this._padding.pad(cipher, m);
  132 + this._doEncrypt(cipher, m, iv);
  133 + },
  134 +
  135 + decrypt: function (cipher, m, iv) {
  136 + this._doDecrypt(cipher, m, iv);
  137 + this._padding.unpad(m);
  138 + },
  139 +
  140 + // Default padding
  141 + _padding: C_pad.iso7816
  142 +};
  143 +
  144 +
  145 +/**
  146 + * Electronic Code Book mode.
  147 + *
  148 + * ECB applies the cipher directly against each block of the input.
  149 + *
  150 + * ECB does not require an initialization vector.
  151 + */
  152 +var ECB = C_mode.ECB = function () {
  153 + // Call parent constructor
  154 + Mode.apply(this, arguments);
  155 +};
  156 +
  157 +// Inherit from Mode
  158 +var ECB_prototype = ECB.prototype = new Mode;
  159 +
  160 +// Concrete steps for Mode template
  161 +ECB_prototype._doEncrypt = function (cipher, m, iv) {
  162 + var blockSizeInBytes = cipher._blocksize * 4;
  163 + // Encrypt each block
  164 + for (var offset = 0; offset < m.length; offset += blockSizeInBytes) {
  165 + cipher._encryptblock(m, offset);
  166 + }
  167 +};
  168 +ECB_prototype._doDecrypt = function (cipher, c, iv) {
  169 + var blockSizeInBytes = cipher._blocksize * 4;
  170 + // Decrypt each block
  171 + for (var offset = 0; offset < c.length; offset += blockSizeInBytes) {
  172 + cipher._decryptblock(c, offset);
  173 + }
  174 +};
  175 +
  176 +// ECB never uses an IV
  177 +ECB_prototype.fixOptions = function (options) {
  178 + options.iv = [];
  179 +};
  180 +
  181 +
  182 +/**
  183 + * Cipher block chaining
  184 + *
  185 + * The first block is XORed with the IV. Subsequent blocks are XOR with the
  186 + * previous cipher output.
  187 + */
  188 +var CBC = C_mode.CBC = function () {
  189 + // Call parent constructor
  190 + Mode.apply(this, arguments);
  191 +};
  192 +
  193 +// Inherit from Mode
  194 +var CBC_prototype = CBC.prototype = new Mode;
  195 +
  196 +// Concrete steps for Mode template
  197 +CBC_prototype._doEncrypt = function (cipher, m, iv) {
  198 + var blockSizeInBytes = cipher._blocksize * 4;
  199 +
  200 + // Encrypt each block
  201 + for (var offset = 0; offset < m.length; offset += blockSizeInBytes) {
  202 + if (offset == 0) {
  203 + // XOR first block using IV
  204 + for (var i = 0; i < blockSizeInBytes; i++)
  205 + m[i] ^= iv[i];
  206 + } else {
  207 + // XOR this block using previous crypted block
  208 + for (var i = 0; i < blockSizeInBytes; i++)
  209 + m[offset + i] ^= m[offset + i - blockSizeInBytes];
  210 + }
  211 + // Encrypt block
  212 + cipher._encryptblock(m, offset);
  213 + }
  214 +};
  215 +CBC_prototype._doDecrypt = function (cipher, c, iv) {
  216 + var blockSizeInBytes = cipher._blocksize * 4;
  217 +
  218 + // At the start, the previously crypted block is the IV
  219 + var prevCryptedBlock = iv;
  220 +
  221 + // Decrypt each block
  222 + for (var offset = 0; offset < c.length; offset += blockSizeInBytes) {
  223 + // Save this crypted block
  224 + var thisCryptedBlock = c.slice(offset, offset + blockSizeInBytes);
  225 + // Decrypt block
  226 + cipher._decryptblock(c, offset);
  227 + // XOR decrypted block using previous crypted block
  228 + for (var i = 0; i < blockSizeInBytes; i++) {
  229 + c[offset + i] ^= prevCryptedBlock[i];
  230 + }
  231 + prevCryptedBlock = thisCryptedBlock;
  232 + }
  233 +};
  234 +
  235 +
  236 +/**
  237 + * Cipher feed back
  238 + *
  239 + * The cipher output is XORed with the plain text to produce the cipher output,
  240 + * which is then fed back into the cipher to produce a bit pattern to XOR the
  241 + * next block with.
  242 + *
  243 + * This is a stream cipher mode and does not require padding.
  244 + */
  245 +var CFB = C_mode.CFB = function () {
  246 + // Call parent constructor
  247 + Mode.apply(this, arguments);
  248 +};
  249 +
  250 +// Inherit from Mode
  251 +var CFB_prototype = CFB.prototype = new Mode;
  252 +
  253 +// Override padding
  254 +CFB_prototype._padding = C_pad.NoPadding;
  255 +
  256 +// Concrete steps for Mode template
  257 +CFB_prototype._doEncrypt = function (cipher, m, iv) {
  258 + var blockSizeInBytes = cipher._blocksize * 4,
  259 + keystream = iv.slice(0);
  260 +
  261 + // Encrypt each byte
  262 + for (var i = 0; i < m.length; i++) {
  263 +
  264 + var j = i % blockSizeInBytes;
  265 + if (j == 0) cipher._encryptblock(keystream, 0);
  266 +
  267 + m[i] ^= keystream[j];
  268 + keystream[j] = m[i];
  269 + }
  270 +};
  271 +CFB_prototype._doDecrypt = function (cipher, c, iv) {
  272 + var blockSizeInBytes = cipher._blocksize * 4,
  273 + keystream = iv.slice(0);
  274 +
  275 + // Encrypt each byte
  276 + for (var i = 0; i < c.length; i++) {
  277 +
  278 + var j = i % blockSizeInBytes;
  279 + if (j == 0) cipher._encryptblock(keystream, 0);
  280 +
  281 + var b = c[i];
  282 + c[i] ^= keystream[j];
  283 + keystream[j] = b;
  284 + }
  285 +};
  286 +
  287 +
  288 +/**
  289 + * Output feed back
  290 + *
  291 + * The cipher repeatedly encrypts its own output. The output is XORed with the
  292 + * plain text to produce the cipher text.
  293 + *
  294 + * This is a stream cipher mode and does not require padding.
  295 + */
  296 +var OFB = C_mode.OFB = function () {
  297 + // Call parent constructor
  298 + Mode.apply(this, arguments);
  299 +};
  300 +
  301 +// Inherit from Mode
  302 +var OFB_prototype = OFB.prototype = new Mode;
  303 +
  304 +// Override padding
  305 +OFB_prototype._padding = C_pad.NoPadding;
  306 +
  307 +// Concrete steps for Mode template
  308 +OFB_prototype._doEncrypt = function (cipher, m, iv) {
  309 +
  310 + var blockSizeInBytes = cipher._blocksize * 4,
  311 + keystream = iv.slice(0);
  312 +
  313 + // Encrypt each byte
  314 + for (var i = 0; i < m.length; i++) {
  315 +
  316 + // Generate keystream
  317 + if (i % blockSizeInBytes == 0)
  318 + cipher._encryptblock(keystream, 0);
  319 +
  320 + // Encrypt byte
  321 + m[i] ^= keystream[i % blockSizeInBytes];
  322 +
  323 + }
  324 +};
  325 +OFB_prototype._doDecrypt = OFB_prototype._doEncrypt;
  326 +
  327 +/**
  328 + * Counter
  329 + * @author Gergely Risko
  330 + *
  331 + * After every block the last 4 bytes of the IV is increased by one
  332 + * with carry and that IV is used for the next block.
  333 + *
  334 + * This is a stream cipher mode and does not require padding.
  335 + */
  336 +var CTR = C_mode.CTR = function () {
  337 + // Call parent constructor
  338 + Mode.apply(this, arguments);
  339 +};
  340 +
  341 +// Inherit from Mode
  342 +var CTR_prototype = CTR.prototype = new Mode;
  343 +
  344 +// Override padding
  345 +CTR_prototype._padding = C_pad.NoPadding;
  346 +
  347 +CTR_prototype._doEncrypt = function (cipher, m, iv) {
  348 + var blockSizeInBytes = cipher._blocksize * 4;
  349 + var counter = iv.slice(0);
  350 +
  351 + for (var i = 0; i < m.length;) {
  352 + // do not lose iv
  353 + var keystream = counter.slice(0);
  354 +
  355 + // Generate keystream for next block
  356 + cipher._encryptblock(keystream, 0);
  357 +
  358 + // XOR keystream with block
  359 + for (var j = 0; i < m.length && j < blockSizeInBytes; j++, i++) {
  360 + m[i] ^= keystream[j];
  361 + }
  362 +
  363 + // Increase counter
  364 + if(++(counter[blockSizeInBytes-1]) == 256) {
  365 + counter[blockSizeInBytes-1] = 0;
  366 + if(++(counter[blockSizeInBytes-2]) == 256) {
  367 + counter[blockSizeInBytes-2] = 0;
  368 + if(++(counter[blockSizeInBytes-3]) == 256) {
  369 + counter[blockSizeInBytes-3] = 0;
  370 + ++(counter[blockSizeInBytes-4]);
  371 + }
  372 + }
  373 + }
  374 + }
  375 +};
  376 +CTR_prototype._doDecrypt = CTR_prototype._doEncrypt;
  377 +
  378 +})();
155 lib/Crypto.js
... ... @@ -0,0 +1,155 @@
  1 +if (typeof Crypto == "undefined" || ! Crypto.util)
  2 +{
  3 +(function(){
  4 +
  5 +var base64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  6 +
  7 +// Global Crypto object
  8 +// with browser window or with node module
  9 +var Crypto = (typeof window === 'undefined') ? exports.Crypto = {} : window.Crypto = {};
  10 +
  11 +// Crypto utilities
  12 +var util = Crypto.util = {
  13 +
  14 + // Bit-wise rotate left
  15 + rotl: function (n, b) {
  16 + return (n << b) | (n >>> (32 - b));
  17 + },
  18 +
  19 + // Bit-wise rotate right
  20 + rotr: function (n, b) {
  21 + return (n << (32 - b)) | (n >>> b);
  22 + },
  23 +
  24 + // Swap big-endian to little-endian and vice versa
  25 + endian: function (n) {
  26 +
  27 + // If number given, swap endian
  28 + if (n.constructor == Number) {
  29 + return util.rotl(n, 8) & 0x00FF00FF |
  30 + util.rotl(n, 24) & 0xFF00FF00;
  31 + }
  32 +
  33 + // Else, assume array and swap all items
  34 + for (var i = 0; i < n.length; i++)
  35 + n[i] = util.endian(n[i]);
  36 + return n;
  37 +
  38 + },
  39 +
  40 + // Generate an array of any length of random bytes
  41 + randomBytes: function (n) {
  42 + for (var bytes = []; n > 0; n--)
  43 + bytes.push(Math.floor(Math.random() * 256));
  44 + return bytes;
  45 + },
  46 +
  47 + // Convert a byte array to big-endian 32-bit words
  48 + bytesToWords: function (bytes) {
  49 + for (var words = [], i = 0, b = 0; i < bytes.length; i++, b += 8)
  50 + words[b >>> 5] |= (bytes[i] & 0xFF) << (24 - b % 32);
  51 + return words;
  52 + },
  53 +
  54 + // Convert big-endian 32-bit words to a byte array
  55 + wordsToBytes: function (words) {
  56 + for (var bytes = [], b = 0; b < words.length * 32; b += 8)
  57 + bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF);
  58 + return bytes;
  59 + },
  60 +
  61 + // Convert a byte array to a hex string
  62 + bytesToHex: function (bytes) {
  63 + for (var hex = [], i = 0; i < bytes.length; i++) {
  64 + hex.push((bytes[i] >>> 4).toString(16));
  65 + hex.push((bytes[i] & 0xF).toString(16));
  66 + }
  67 + return hex.join("");
  68 + },
  69 +
  70 + // Convert a hex string to a byte array
  71 + hexToBytes: function (hex) {
  72 + for (var bytes = [], c = 0; c < hex.length; c += 2)
  73 + bytes.push(parseInt(hex.substr(c, 2), 16));
  74 + return bytes;
  75 + },
  76 +
  77 + // Convert a byte array to a base-64 string
  78 + bytesToBase64: function (bytes) {
  79 +
  80 + // Use browser-native function if it exists
  81 + if (typeof btoa == "function") return btoa(Binary.bytesToString(bytes));
  82 +
  83 + for(var base64 = [], i = 0; i < bytes.length; i += 3) {
  84 + var triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
  85 + for (var j = 0; j < 4; j++) {
  86 + if (i * 8 + j * 6 <= bytes.length * 8)
  87 + base64.push(base64map.charAt((triplet >>> 6 * (3 - j)) & 0x3F));
  88 + else base64.push("=");
  89 + }
  90 + }
  91 +
  92 + return base64.join("");
  93 +
  94 + },
  95 +
  96 + // Convert a base-64 string to a byte array
  97 + base64ToBytes: function (base64) {
  98 +
  99 + // Use browser-native function if it exists
  100 + if (typeof atob == "function") return Binary.stringToBytes(atob(base64));
  101 +
  102 + // Remove non-base-64 characters
  103 + base64 = base64.replace(/[^A-Z0-9+\/]/ig, "");
  104 +
  105 + for (var bytes = [], i = 0, imod4 = 0; i < base64.length; imod4 = ++i % 4) {
  106 + if (imod4 == 0) continue;
  107 + bytes.push(((base64map.indexOf(base64.charAt(i - 1)) & (Math.pow(2, -2 * imod4 + 8) - 1)) << (imod4 * 2)) |
  108 + (base64map.indexOf(base64.charAt(i)) >>> (6 - imod4 * 2)));
  109 + }
  110 +
  111 + return bytes;
  112 +
  113 + }
  114 +
  115 +};
  116 +
  117 +// Crypto character encodings
  118 +var charenc = Crypto.charenc = {};
  119 +
  120 +// UTF-8 encoding
  121 +var UTF8 = charenc.UTF8 = {
  122 +
  123 + // Convert a string to a byte array
  124 + stringToBytes: function (str) {
  125 + return Binary.stringToBytes(unescape(encodeURIComponent(str)));
  126 + },
  127 +
  128 + // Convert a byte array to a string
  129 + bytesToString: function (bytes) {
  130 + return decodeURIComponent(escape(Binary.bytesToString(bytes)));
  131 + }
  132 +
  133 +};
  134 +
  135 +// Binary encoding
  136 +var Binary = charenc.Binary = {
  137 +
  138 + // Convert a string to a byte array
  139 + stringToBytes: function (str) {
  140 + for (var bytes = [], i = 0; i < str.length; i++)
  141 + bytes.push(str.charCodeAt(i) & 0xFF);
  142 + return bytes;
  143 + },
  144 +
  145 + // Convert a byte array to a string
  146 + bytesToString: function (bytes) {
  147 + for (var str = [], i = 0; i < bytes.length; i++)
  148 + str.push(String.fromCharCode(bytes[i]));
  149 + return str.join("");
  150 + }
  151 +
  152 +};
  153 +
  154 +})();
  155 +}
37 lib/CryptoMath.js
... ... @@ -0,0 +1,37 @@
  1 +(function(){
  2 +
  3 +var C = (typeof window === 'undefined') ? require('./Crypto').Crypto : window.Crypto;
  4 +
  5 +// Shortcut
  6 +var util = C.util;
  7 +
  8 +// Convert n to unsigned 32-bit integer
  9 +util.u32 = function (n) {
  10 + return n >>> 0;
  11 +};
  12 +
  13 +// Unsigned 32-bit addition
  14 +util.add = function () {
  15 + var result = this.u32(arguments[0]);
  16 + for (var i = 1; i < arguments.length; i++)
  17 + result = this.u32(result + this.u32(arguments[i]));
  18 + return result;
  19 +};
  20 +
  21 +// Unsigned 32-bit multiplication
  22 +util.mult = function (m, n) {
  23 + return this.add((n & 0xFFFF0000) * m,
  24 + (n & 0x0000FFFF) * m);
  25 +};
  26 +
  27 +// Unsigned 32-bit greater than (>) comparison
  28 +util.gt = function (m, n) {
  29 + return this.u32(m) > this.u32(n);
  30 +};
  31 +
  32 +// Unsigned 32-bit less than (<) comparison
  33 +util.lt = function (m, n) {
  34 + return this.u32(m) < this.u32(n);
  35 +};
  36 +
  37 +})();
1,003 lib/DES.js
... ... @@ -0,0 +1,1003 @@
  1 +/**
  2 + * Definition of Data Encryption Standard (DES) taken from:
  3 + * http://www.itl.nist.gov/fipspubs/fip46-2.htm
  4 + */
  5 +
  6 +(function() {
  7 +
  8 +var C = (typeof window === 'undefined') ? require('./Crypto').Crypto : window.Crypto;
  9 +
  10 + // Shortcuts
  11 + var util = C.util, charenc = C.charenc, UTF8 = charenc.UTF8;
  12 +
  13 + /***************************************************************************
  14 + *
  15 + * DES Key Schedule.
  16 + *
  17 + * The Key consists of 16 sub-keys of 48 bits each. As each sub-key is
  18 + * applied to an expanded 32-bit value where each 4 bits of input is
  19 + * expanded into 6 bits of output the sub-key can be broken down into 8
  20 + * 32-bit values which allows the key to be used without expansion.
  21 + *
  22 + * To create the 16 sub-keys, 56 bits are selected from the input 64 bit key
  23 + * according to <i>PC1</i>. Each sub-key is generated by left rotating the
  24 + * bits a different amount and then selecting 48 bits according to <i>PC2</i>.
  25 + *
  26 + **************************************************************************/
  27 +
  28 + var KeySchedule;
  29 +
  30 + /**
  31 + * Representation of a DES key schedule.
  32 + *
  33 + * @param {Array
  34 + * of 8 bytes} key The cipher key
  35 + *
  36 + * @constructor
  37 + */
  38 + KeySchedule = function(key) {
  39 + /**
  40 + * The schedule of 16 keys
  41 + */
  42 + this.keys = new Array(16);
  43 + this._initialiseKeys(key);
  44 + };
  45 +
  46 + /**
  47 + * Permuted Choice 1 (PC1) byte offsets into the key. Each of the 56 entries
  48 + * selects one bit of DES's 56 bit key.
  49 + * <p>
  50 + *
  51 + * <pre>
  52 + * The PC1 is defined as:
  53 + *
  54 + * 57, 49, 41, 33, 25, 17, 9,
  55 + * 1, 58, 50, 42, 34, 26, 18,
  56 + * 10, 2, 59, 51, 43, 35, 27,
  57 + * 19, 11, 3, 60, 52, 44, 36,
  58 + * 63, 55, 47, 39, 31, 23, 15,
  59 + * 7, 62, 54, 46, 38, 30, 22,
  60 + * 14, 6, 61, 53, 45, 37, 29,
  61 + * 21, 13, 5, 28, 20, 12, 4
  62 + * </pre>
  63 + *
  64 + * We represent this as an offset into an 8-byte array and a bit mask upon
  65 + * that byte. For example 57=(7*8)+1 so is the first (MSB) of the 7th byte.
  66 + *
  67 + * @constant
  68 + */
  69 + KeySchedule.PC1_offsets = [ 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0,
  70 + 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6,
  71 + 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0, 3, 2, 1, 0 ];
  72 +
  73 + /**
  74 + * Permuted Choice 1 (PC1) bit masks. Each of the 56 entries selects one bit
  75 + * of DES's 56 bit key.
  76 + *
  77 + * @constant
  78 + */
  79 + KeySchedule.PC1_masks = [ 128, 128, 128, 128, 128, 128, 128, 128, 64, 64,
  80 + 64, 64, 64, 64, 64, 64, 32, 32, 32, 32, 32, 32, 32, 32, 16, 16, 16,
  81 + 16, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8,
  82 + 8, 8, 8, 16, 16, 16, 16 ];
  83 +
  84 + /**
  85 + * Permuted Choice 2 (PC2) selects the active 48 bits from the 56 bits of
  86 + * the key.
  87 + * <p>
  88 + *
  89 + * <pre>
  90 + * The PC2 is defined as:
  91 + *
  92 + * 14, 17, 11, 24, 1, 5,
  93 + * 3, 28, 15, 6, 21, 10,
  94 + * 23, 19, 12, 4, 26, 8,
  95 + * 16, 7, 27, 20, 13, 2,
  96 + * 41, 52, 31, 37, 47, 55,
  97 + * 30, 40, 51, 45, 33, 48,
  98 + * 44, 49, 39, 56, 34, 53,
  99 + * 46, 42, 50, 36, 29, 32
  100 + * </pre>
  101 + *
  102 + * We invert the choice to specify what each bit adds to each 6-bit value of
  103 + * the key. For example, bit 1 is the 5th bit selected so this add 2 to the
  104 + * first 6-bit value.
  105 + *
  106 + * @constant
  107 + */
  108 + KeySchedule.PC2_offsets1 = [ 0, 3, 1, 2, 0, 1, 3, 2, 0, 1, 0, 2, 3, 0, 1,
  109 + 3, 0, 0, 2, 3, 1, 0, 2, 0, 0, 2, 3, 1 ];
  110 +
  111 + /**
  112 + * PC2 offsets for 2nd block.
  113 + *
  114 + * @constant
  115 + */
  116 + KeySchedule.PC2_offsets2 = [ 7, 5, 4, 7, 5, 6, 0, 7, 4, 0, 6, 5, 4, 7, 0,
  117 + 6, 5, 7, 4, 5, 6, 7, 5, 4, 6, 0, 4, 6 ];
  118 +
  119 + /**
  120 + * Permuted Choice 2 (PC2) masks for 1st block.
  121 + *
  122 + * @constant
  123 + */
  124 + KeySchedule.PC2_masks1 = [ 2, 1, 32, 4, 1, 4, 16, 1, 0, 1, 8, 8, 2, 32, 8,
  125 + 32, 16, 0, 16, 4, 2, 0, 32, 4, 0, 2, 8, 16 ];
  126 +
  127 + /**
  128 + * PC2 masks for 2nd block.
  129 + *
  130 + * @constant
  131 + */
  132 + KeySchedule.PC2_masks2 = [ 2, 32, 8, 1, 2, 2, 0, 4, 4, 0, 8, 16, 32, 16, 0,
  133 + 32, 4, 32, 2, 1, 16, 8, 8, 16, 1, 0, 1, 4 ];
  134 +
  135 + /**
  136 + * Cumulative key shifts.
  137 + *
  138 + * @constant
  139 + */
  140 + KeySchedule.keyShifts = [ 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23,
  141 + 25, 27, 28 ];
  142 +
  143 + KeySchedule.prototype._initialiseKeys = function(key) {
  144 + var i;
  145 +
  146 + // extract 56 key bits in order determined by PC1
  147 + var bits = new Array(56);
  148 + for (i = 0; i < 56; i++) {
  149 + bits[i] = (key[KeySchedule.PC1_offsets[i]] & KeySchedule.PC1_masks[i]) != 0;
  150 + }
  151 +
  152 + // split 56 bits into two 28-bit chunks
  153 + var bits1 = bits.slice(0, 28);
  154 + var bits2 = bits.slice(28, 56);
  155 +
  156 + // duplicate each half to allow for easy bit shifts
  157 + bits1 = bits1.concat(bits1);
  158 + bits2 = bits2.concat(bits2);
  159 +
  160 + // assemble the 16 keys
  161 + for (i = 0; i < 16; i++) {
  162 + var k = [ 0, 0, 0, 0, 0, 0, 0, 0 ];
  163 +
  164 + // select the bits of the key according to PC2
  165 + var s = KeySchedule.keyShifts[i];
  166 + for ( var j = 0; j < 28; j++) {
  167 + if (bits1[j + s]) {
  168 + k[KeySchedule.PC2_offsets1[j]] += KeySchedule.PC2_masks1[j];
  169 + }
  170 + if (bits2[j + s]) {
  171 + k[KeySchedule.PC2_offsets2[j]] += KeySchedule.PC2_masks2[j];
  172 + }
  173 + }
  174 +
  175 + // Scale each of the 8 blocks to a 32-bit mask.
  176 + k[0] = ((k[0] & 0x1f) << 27) + ((k[0] & 0x20) >> 5);
  177 + for ( var j = 1; j <= 6; j++) {
  178 + k[j] = k[j] << (27 - 4 * j);
  179 + }
  180 + k[7] = ((k[7] & 0x3e) >> 1) + ((k[7] & 0x1) << 31);
  181 + this.keys[i] = k;
  182 + }
  183 + };
  184 +
  185 + /**
  186 + * Retrieve the key for a specified round
  187 + *
  188 + * @param i
  189 + * the round
  190 + * @returns the key
  191 + */
  192 + KeySchedule.prototype.getKey = function(i) {
  193 + return this.keys[i];
  194 + };
  195 +
  196 + /***************************************************************************
  197 + *
  198 + * DES Engine State
  199 + *
  200 + **************************************************************************/
  201 +
  202 + var State;
  203 +
  204 + /**
  205 + * The algorithm's state. DES operates on two sets of 32-bits, with each
  206 + * block of 32-bits treated as a single number.
  207 + *
  208 + * @class
  209 + */
  210 + State = function() {
  211 + /** The LHS of the Feistel scheme */
  212 + this.lhs = 0;
  213 + /** The RHS of the Feistel scheme */
  214 + this.rhs = 0;
  215 + };
  216 +
  217 + /**
  218 + * The masks that select the SBOX input. Each SBOX accepts 6 bits from the
  219 + * input.
  220 + *
  221 + * @constant
  222 + */
  223 + State.SBOX_MASK = [ 0xf8000001, 0x1f800000, 0x01f80000, 0x001f8000,
  224 + 0x0001f800, 0x00001f80, 0x000001f8, 0x8000001f ];
  225 +
  226 + /**
  227 + * The SBOXes. The 8 SBOXes each map 6 bit masked bit of the input to 4 bits
  228 + * of output. These SBOXes include the post SBOX permutation and benefit
  229 + * from JavaScript's sparse arrays to make specifying the input match
  230 + * simple.
  231 + *
  232 + * @constant
  233 + */
  234 + State.SBOX = new Array(8);
  235 +
  236 + var SBOX = State.SBOX;
  237 +
  238 + SBOX[0] = new Array();
  239 + SBOX[0][0] = 0x808200; // 0 (0, 0) = 14
  240 + SBOX[0][268435456] = 0x8000; // 10000000 (0, 1) = 4
  241 + SBOX[0][536870912] = 0x808002; // 20000000 (0, 2) = 13
  242 + SBOX[0][805306368] = 0x2; // 30000000 (0, 3) = 1
  243 + SBOX[0][1073741824] = 0x200; // 40000000 (0, 4) = 2
  244 + SBOX[0][1342177280] = 0x808202; // 50000000 (0, 5) = 15
  245 + SBOX[0][1610612736] = 0x800202; // 60000000 (0, 6) = 11
  246 + SBOX[0][1879048192] = 0x800000; // 70000000 (0, 7) = 8
  247 + SBOX[0][-2147483648] = 0x202; // 80000000 (0, 8) = 3
  248 + SBOX[0][-1879048192] = 0x800200; // 90000000 (0, 9) = 10
  249 + SBOX[0][-1610612736] = 0x8200; // a0000000 (0, 10) = 6
  250 + SBOX[0][-1342177280] = 0x808000; // b0000000 (0, 11) = 12
  251 + SBOX[0][-1073741824] = 0x8002; // c0000000 (0, 12) = 5
  252 + SBOX[0][-805306368] = 0x800002; // d0000000 (0, 13) = 9
  253 + SBOX[0][-536870912] = 0x0; // e0000000 (0, 14) = 0
  254 + SBOX[0][-268435456] = 0x8202; // f0000000 (0, 15) = 7
  255 + SBOX[0][134217728] = 0x0; // 8000000 (1, 0) = 0
  256 + SBOX[0][402653184] = 0x808202; // 18000000 (1, 1) = 15
  257 + SBOX[0][671088640] = 0x8202; // 28000000 (1, 2) = 7
  258 + SBOX[0][939524096] = 0x8000; // 38000000 (1, 3) = 4
  259 + SBOX[0][1207959552] = 0x808200; // 48000000 (1, 4) = 14
  260 + SBOX[0][1476395008] = 0x200; // 58000000 (1, 5) = 2
  261 + SBOX[0][1744830464] = 0x808002; // 68000000 (1, 6) = 13
  262 + SBOX[0][2013265920] = 0x2; // 78000000 (1, 7) = 1
  263 + SBOX[0][-2013265920] = 0x800200; // 88000000 (1, 8) = 10
  264 + SBOX[0][-1744830464] = 0x8200; // 98000000 (1, 9) = 6
  265 + SBOX[0][-1476395008] = 0x808000; // a8000000 (1, 10) = 12
  266 + SBOX[0][-1207959552] = 0x800202; // b8000000 (1, 11) = 11
  267 + SBOX[0][-939524096] = 0x800002; // c8000000 (1, 12) = 9
  268 + SBOX[0][-671088640] = 0x8002; // d8000000 (1, 13) = 5
  269 + SBOX[0][-402653184] = 0x202; // e8000000 (1, 14) = 3
  270 + SBOX[0][-134217728] = 0x800000; // f8000000 (1, 15) = 8
  271 + SBOX[0][1] = 0x8000; // 1 (2, 0) = 4
  272 + SBOX[0][268435457] = 0x2; // 10000001 (2, 1) = 1
  273 + SBOX[0][536870913] = 0x808200; // 20000001 (2, 2) = 14
  274 + SBOX[0][805306369] = 0x800000; // 30000001 (2, 3) = 8
  275 + SBOX[0][1073741825] = 0x808002; // 40000001 (2, 4) = 13
  276 + SBOX[0][1342177281] = 0x8200; // 50000001 (2, 5) = 6
  277 + SBOX[0][1610612737] = 0x200; // 60000001 (2, 6) = 2
  278 + SBOX[0][1879048193] = 0x800202; // 70000001 (2, 7) = 11
  279 + SBOX[0][-2147483647] = 0x808202; // 80000001 (2, 8) = 15
  280