aes.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /** @fileOverview Low-level AES implementation.
  2. *
  3. * This file contains a low-level implementation of AES, optimized for
  4. * size and for efficiency on several browsers. It is based on
  5. * OpenSSL's aes_core.c, a public-domain implementation by Vincent
  6. * Rijmen, Antoon Bosselaers and Paulo Barreto.
  7. *
  8. * An older version of this implementation is available in the public
  9. * domain, but this one is (c) Emily Stark, Mike Hamburg, Dan Boneh,
  10. * Stanford University 2008-2010 and BSD-licensed for liability
  11. * reasons.
  12. *
  13. * @author Emily Stark
  14. * @author Mike Hamburg
  15. * @author Dan Boneh
  16. */
  17. /**
  18. * Schedule out an AES key for both encryption and decryption. This
  19. * is a low-level class. Use a cipher mode to do bulk encryption.
  20. *
  21. * @constructor
  22. * @param {Array} key The key as an array of 4, 6 or 8 words.
  23. *
  24. * @class Advanced Encryption Standard (low-level interface)
  25. */
  26. sjcl.cipher.aes = function (key) {
  27. if (!this._tables[0][0][0]) {
  28. this._precompute();
  29. }
  30. var i, j, tmp,
  31. encKey, decKey,
  32. sbox = this._tables[0][4], decTable = this._tables[1],
  33. keyLen = key.length, rcon = 1;
  34. if (keyLen !== 4 && keyLen !== 6 && keyLen !== 8) {
  35. throw new sjcl.exception.invalid("invalid aes key size");
  36. }
  37. this._key = [encKey = key.slice(0), decKey = []];
  38. // schedule encryption keys
  39. for (i = keyLen; i < 4 * keyLen + 28; i++) {
  40. tmp = encKey[i-1];
  41. // apply sbox
  42. if (i%keyLen === 0 || (keyLen === 8 && i%keyLen === 4)) {
  43. tmp = sbox[tmp>>>24]<<24 ^ sbox[tmp>>16&255]<<16 ^ sbox[tmp>>8&255]<<8 ^ sbox[tmp&255];
  44. // shift rows and add rcon
  45. if (i%keyLen === 0) {
  46. tmp = tmp<<8 ^ tmp>>>24 ^ rcon<<24;
  47. rcon = rcon<<1 ^ (rcon>>7)*283;
  48. }
  49. }
  50. encKey[i] = encKey[i-keyLen] ^ tmp;
  51. }
  52. // schedule decryption keys
  53. for (j = 0; i; j++, i--) {
  54. tmp = encKey[j&3 ? i : i - 4];
  55. if (i<=4 || j<4) {
  56. decKey[j] = tmp;
  57. } else {
  58. decKey[j] = decTable[0][sbox[tmp>>>24 ]] ^
  59. decTable[1][sbox[tmp>>16 & 255]] ^
  60. decTable[2][sbox[tmp>>8 & 255]] ^
  61. decTable[3][sbox[tmp & 255]];
  62. }
  63. }
  64. };
  65. sjcl.cipher.aes.prototype = {
  66. // public
  67. /* Something like this might appear here eventually
  68. name: "AES",
  69. blockSize: 4,
  70. keySizes: [4,6,8],
  71. */
  72. /**
  73. * Encrypt an array of 4 big-endian words.
  74. * @param {Array} data The plaintext.
  75. * @return {Array} The ciphertext.
  76. */
  77. encrypt:function (data) { return this._crypt(data,0); },
  78. /**
  79. * Decrypt an array of 4 big-endian words.
  80. * @param {Array} data The ciphertext.
  81. * @return {Array} The plaintext.
  82. */
  83. decrypt:function (data) { return this._crypt(data,1); },
  84. /**
  85. * The expanded S-box and inverse S-box tables. These will be computed
  86. * on the client so that we don't have to send them down the wire.
  87. *
  88. * There are two tables, _tables[0] is for encryption and
  89. * _tables[1] is for decryption.
  90. *
  91. * The first 4 sub-tables are the expanded S-box with MixColumns. The
  92. * last (_tables[01][4]) is the S-box itself.
  93. *
  94. * @private
  95. */
  96. _tables: [[[],[],[],[],[]],[[],[],[],[],[]]],
  97. /**
  98. * Expand the S-box tables.
  99. *
  100. * @private
  101. */
  102. _precompute: function () {
  103. var encTable = this._tables[0], decTable = this._tables[1],
  104. sbox = encTable[4], sboxInv = decTable[4],
  105. i, x, xInv, d=[], th=[], x2, x4, x8, s, tEnc, tDec;
  106. // Compute double and third tables
  107. for (i = 0; i < 256; i++) {
  108. th[( d[i] = i<<1 ^ (i>>7)*283 )^i]=i;
  109. }
  110. for (x = xInv = 0; !sbox[x]; x ^= x2 || 1, xInv = th[xInv] || 1) {
  111. // Compute sbox
  112. s = xInv ^ xInv<<1 ^ xInv<<2 ^ xInv<<3 ^ xInv<<4;
  113. s = s>>8 ^ s&255 ^ 99;
  114. sbox[x] = s;
  115. sboxInv[s] = x;
  116. // Compute MixColumns
  117. x8 = d[x4 = d[x2 = d[x]]];
  118. tDec = x8*0x1010101 ^ x4*0x10001 ^ x2*0x101 ^ x*0x1010100;
  119. tEnc = d[s]*0x101 ^ s*0x1010100;
  120. for (i = 0; i < 4; i++) {
  121. encTable[i][x] = tEnc = tEnc<<24 ^ tEnc>>>8;
  122. decTable[i][s] = tDec = tDec<<24 ^ tDec>>>8;
  123. }
  124. }
  125. // Compactify. Considerable speedup on Firefox.
  126. for (i = 0; i < 5; i++) {
  127. encTable[i] = encTable[i].slice(0);
  128. decTable[i] = decTable[i].slice(0);
  129. }
  130. },
  131. /**
  132. * Encryption and decryption core.
  133. * @param {Array} input Four words to be encrypted or decrypted.
  134. * @param dir The direction, 0 for encrypt and 1 for decrypt.
  135. * @return {Array} The four encrypted or decrypted words.
  136. * @private
  137. */
  138. _crypt:function (input, dir) {
  139. if (input.length !== 4) {
  140. throw new sjcl.exception.invalid("invalid aes block size");
  141. }
  142. var key = this._key[dir],
  143. // state variables a,b,c,d are loaded with pre-whitened data
  144. a = input[0] ^ key[0],
  145. b = input[dir ? 3 : 1] ^ key[1],
  146. c = input[2] ^ key[2],
  147. d = input[dir ? 1 : 3] ^ key[3],
  148. a2, b2, c2,
  149. nInnerRounds = key.length/4 - 2,
  150. i,
  151. kIndex = 4,
  152. out = [0,0,0,0],
  153. table = this._tables[dir],
  154. // load up the tables
  155. t0 = table[0],
  156. t1 = table[1],
  157. t2 = table[2],
  158. t3 = table[3],
  159. sbox = table[4];
  160. // Inner rounds. Cribbed from OpenSSL.
  161. for (i = 0; i < nInnerRounds; i++) {
  162. a2 = t0[a>>>24] ^ t1[b>>16 & 255] ^ t2[c>>8 & 255] ^ t3[d & 255] ^ key[kIndex];
  163. b2 = t0[b>>>24] ^ t1[c>>16 & 255] ^ t2[d>>8 & 255] ^ t3[a & 255] ^ key[kIndex + 1];
  164. c2 = t0[c>>>24] ^ t1[d>>16 & 255] ^ t2[a>>8 & 255] ^ t3[b & 255] ^ key[kIndex + 2];
  165. d = t0[d>>>24] ^ t1[a>>16 & 255] ^ t2[b>>8 & 255] ^ t3[c & 255] ^ key[kIndex + 3];
  166. kIndex += 4;
  167. a=a2; b=b2; c=c2;
  168. }
  169. // Last round.
  170. for (i = 0; i < 4; i++) {
  171. out[dir ? 3&-i : i] =
  172. sbox[a>>>24 ]<<24 ^
  173. sbox[b>>16 & 255]<<16 ^
  174. sbox[c>>8 & 255]<<8 ^
  175. sbox[d & 255] ^
  176. key[kIndex++];
  177. a2=a; a=b; b=c; c=d; d=a2;
  178. }
  179. return out;
  180. }
  181. };