Subversion Repositories cryptochat

Rev

View as "text/javascript" | Blame | Last modification | View Log | RSS feed

  1. /*
  2. CryptoJS v3.1.2
  3. code.google.com/p/crypto-js
  4. (c) 2009-2013 by Jeff Mott. All rights reserved.
  5. code.google.com/p/crypto-js/wiki/License
  6. */
  7. (function () {
  8.     // Shortcuts
  9.     var C = CryptoJS;
  10.     var C_lib = C.lib;
  11.     var BlockCipher = C_lib.BlockCipher;
  12.     var C_algo = C.algo;
  13.  
  14.     // Lookup tables
  15.     var SBOX = [];
  16.     var INV_SBOX = [];
  17.     var SUB_MIX_0 = [];
  18.     var SUB_MIX_1 = [];
  19.     var SUB_MIX_2 = [];
  20.     var SUB_MIX_3 = [];
  21.     var INV_SUB_MIX_0 = [];
  22.     var INV_SUB_MIX_1 = [];
  23.     var INV_SUB_MIX_2 = [];
  24.     var INV_SUB_MIX_3 = [];
  25.  
  26.     // Compute lookup tables
  27.     (function () {
  28.         // Compute double table
  29.         var d = [];
  30.         for (var i = 0; i < 256; i++) {
  31.             if (i < 128) {
  32.                 d[i] = i << 1;
  33.             } else {
  34.                 d[i] = (i << 1) ^ 0x11b;
  35.             }
  36.         }
  37.  
  38.         // Walk GF(2^8)
  39.         var x = 0;
  40.         var xi = 0;
  41.         for (var i = 0; i < 256; i++) {
  42.             // Compute sbox
  43.             var sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4);
  44.             sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63;
  45.             SBOX[x] = sx;
  46.             INV_SBOX[sx] = x;
  47.  
  48.             // Compute multiplication
  49.             var x2 = d[x];
  50.             var x4 = d[x2];
  51.             var x8 = d[x4];
  52.  
  53.             // Compute sub bytes, mix columns tables
  54.             var t = (d[sx] * 0x101) ^ (sx * 0x1010100);
  55.             SUB_MIX_0[x] = (t << 24) | (t >>> 8);
  56.             SUB_MIX_1[x] = (t << 16) | (t >>> 16);
  57.             SUB_MIX_2[x] = (t << 8)  | (t >>> 24);
  58.             SUB_MIX_3[x] = t;
  59.  
  60.             // Compute inv sub bytes, inv mix columns tables
  61.             var t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100);
  62.             INV_SUB_MIX_0[sx] = (t << 24) | (t >>> 8);
  63.             INV_SUB_MIX_1[sx] = (t << 16) | (t >>> 16);
  64.             INV_SUB_MIX_2[sx] = (t << 8)  | (t >>> 24);
  65.             INV_SUB_MIX_3[sx] = t;
  66.  
  67.             // Compute next counter
  68.             if (!x) {
  69.                 x = xi = 1;
  70.             } else {
  71.                 x = x2 ^ d[d[d[x8 ^ x2]]];
  72.                 xi ^= d[d[xi]];
  73.             }
  74.         }
  75.     }());
  76.  
  77.     // Precomputed Rcon lookup
  78.     var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36];
  79.  
  80.     /**
  81.      * AES block cipher algorithm.
  82.      */
  83.     var AES = C_algo.AES = BlockCipher.extend({
  84.         _doReset: function () {
  85.             // Shortcuts
  86.             var key = this._key;
  87.             var keyWords = key.words;
  88.             var keySize = key.sigBytes / 4;
  89.  
  90.             // Compute number of rounds
  91.             var nRounds = this._nRounds = keySize + 6
  92.  
  93.             // Compute number of key schedule rows
  94.             var ksRows = (nRounds + 1) * 4;
  95.  
  96.             // Compute key schedule
  97.             var keySchedule = this._keySchedule = [];
  98.             for (var ksRow = 0; ksRow < ksRows; ksRow++) {
  99.                 if (ksRow < keySize) {
  100.                     keySchedule[ksRow] = keyWords[ksRow];
  101.                 } else {
  102.                     var t = keySchedule[ksRow - 1];
  103.  
  104.                     if (!(ksRow % keySize)) {
  105.                         // Rot word
  106.                         t = (t << 8) | (t >>> 24);
  107.  
  108.                         // Sub word
  109.                         t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff];
  110.  
  111.                         // Mix Rcon
  112.                         t ^= RCON[(ksRow / keySize) | 0] << 24;
  113.                     } else if (keySize > 6 && ksRow % keySize == 4) {
  114.                         // Sub word
  115.                         t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff];
  116.                     }
  117.  
  118.                     keySchedule[ksRow] = keySchedule[ksRow - keySize] ^ t;
  119.                 }
  120.             }
  121.  
  122.             // Compute inv key schedule
  123.             var invKeySchedule = this._invKeySchedule = [];
  124.             for (var invKsRow = 0; invKsRow < ksRows; invKsRow++) {
  125.                 var ksRow = ksRows - invKsRow;
  126.  
  127.                 if (invKsRow % 4) {
  128.                     var t = keySchedule[ksRow];
  129.                 } else {
  130.                     var t = keySchedule[ksRow - 4];
  131.                 }
  132.  
  133.                 if (invKsRow < 4 || ksRow <= 4) {
  134.                     invKeySchedule[invKsRow] = t;
  135.                 } else {
  136.                     invKeySchedule[invKsRow] = INV_SUB_MIX_0[SBOX[t >>> 24]] ^ INV_SUB_MIX_1[SBOX[(t >>> 16) & 0xff]] ^
  137.                                                INV_SUB_MIX_2[SBOX[(t >>> 8) & 0xff]] ^ INV_SUB_MIX_3[SBOX[t & 0xff]];
  138.                 }
  139.             }
  140.         },
  141.  
  142.         encryptBlock: function (M, offset) {
  143.             this._doCryptBlock(M, offset, this._keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX);
  144.         },
  145.  
  146.         decryptBlock: function (M, offset) {
  147.             // Swap 2nd and 4th rows
  148.             var t = M[offset + 1];
  149.             M[offset + 1] = M[offset + 3];
  150.             M[offset + 3] = t;
  151.  
  152.             this._doCryptBlock(M, offset, this._invKeySchedule, INV_SUB_MIX_0, INV_SUB_MIX_1, INV_SUB_MIX_2, INV_SUB_MIX_3, INV_SBOX);
  153.  
  154.             // Inv swap 2nd and 4th rows
  155.             var t = M[offset + 1];
  156.             M[offset + 1] = M[offset + 3];
  157.             M[offset + 3] = t;
  158.         },
  159.  
  160.         _doCryptBlock: function (M, offset, keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX) {
  161.             // Shortcut
  162.             var nRounds = this._nRounds;
  163.  
  164.             // Get input, add round key
  165.             var s0 = M[offset]     ^ keySchedule[0];
  166.             var s1 = M[offset + 1] ^ keySchedule[1];
  167.             var s2 = M[offset + 2] ^ keySchedule[2];
  168.             var s3 = M[offset + 3] ^ keySchedule[3];
  169.  
  170.             // Key schedule row counter
  171.             var ksRow = 4;
  172.  
  173.             // Rounds
  174.             for (var round = 1; round < nRounds; round++) {
  175.                 // Shift rows, sub bytes, mix columns, add round key
  176.                 var t0 = SUB_MIX_0[s0 >>> 24] ^ SUB_MIX_1[(s1 >>> 16) & 0xff] ^ SUB_MIX_2[(s2 >>> 8) & 0xff] ^ SUB_MIX_3[s3 & 0xff] ^ keySchedule[ksRow++];
  177.                 var t1 = SUB_MIX_0[s1 >>> 24] ^ SUB_MIX_1[(s2 >>> 16) & 0xff] ^ SUB_MIX_2[(s3 >>> 8) & 0xff] ^ SUB_MIX_3[s0 & 0xff] ^ keySchedule[ksRow++];
  178.                 var t2 = SUB_MIX_0[s2 >>> 24] ^ SUB_MIX_1[(s3 >>> 16) & 0xff] ^ SUB_MIX_2[(s0 >>> 8) & 0xff] ^ SUB_MIX_3[s1 & 0xff] ^ keySchedule[ksRow++];
  179.                 var t3 = SUB_MIX_0[s3 >>> 24] ^ SUB_MIX_1[(s0 >>> 16) & 0xff] ^ SUB_MIX_2[(s1 >>> 8) & 0xff] ^ SUB_MIX_3[s2 & 0xff] ^ keySchedule[ksRow++];
  180.  
  181.                 // Update state
  182.                 s0 = t0;
  183.                 s1 = t1;
  184.                 s2 = t2;
  185.                 s3 = t3;
  186.             }
  187.  
  188.             // Shift rows, sub bytes, add round key
  189.             var t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++];
  190.             var t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++];
  191.             var t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++];
  192.             var t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++];
  193.  
  194.             // Set output
  195.             M[offset]     = t0;
  196.             M[offset + 1] = t1;
  197.             M[offset + 2] = t2;
  198.             M[offset + 3] = t3;
  199.         },
  200.  
  201.         keySize: 256/32
  202.     });
  203.  
  204.     /**
  205.      * Shortcut functions to the cipher's object interface.
  206.      *
  207.      * @example
  208.      *
  209.      *     var ciphertext = CryptoJS.AES.encrypt(message, key, cfg);
  210.      *     var plaintext  = CryptoJS.AES.decrypt(ciphertext, key, cfg);
  211.      */
  212.     C.AES = BlockCipher._createHelper(AES);
  213. }());
  214.