aes.js 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /**
  2. * @file aes.js
  3. *
  4. * This file contains an adaptation of the AES decryption algorithm
  5. * from the Standford Javascript Cryptography Library. That work is
  6. * covered by the following copyright and permissions notice:
  7. *
  8. * Copyright 2009-2010 Emily Stark, Mike Hamburg, Dan Boneh.
  9. * All rights reserved.
  10. *
  11. * Redistribution and use in source and binary forms, with or without
  12. * modification, are permitted provided that the following conditions are
  13. * met:
  14. *
  15. * 1. Redistributions of source code must retain the above copyright
  16. * notice, this list of conditions and the following disclaimer.
  17. *
  18. * 2. Redistributions in binary form must reproduce the above
  19. * copyright notice, this list of conditions and the following
  20. * disclaimer in the documentation and/or other materials provided
  21. * with the distribution.
  22. *
  23. * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
  24. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  25. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  26. * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR CONTRIBUTORS BE
  27. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  28. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  29. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  30. * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  31. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  32. * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  33. * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  34. *
  35. * The views and conclusions contained in the software and documentation
  36. * are those of the authors and should not be interpreted as representing
  37. * official policies, either expressed or implied, of the authors.
  38. */
  39. /**
  40. * Expand the S-box tables.
  41. *
  42. * @private
  43. */
  44. 'use strict';
  45. Object.defineProperty(exports, '__esModule', {
  46. value: true
  47. });
  48. var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
  49. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
  50. var precompute = function precompute() {
  51. var tables = [[[], [], [], [], []], [[], [], [], [], []]];
  52. var encTable = tables[0];
  53. var decTable = tables[1];
  54. var sbox = encTable[4];
  55. var sboxInv = decTable[4];
  56. var i = undefined;
  57. var x = undefined;
  58. var xInv = undefined;
  59. var d = [];
  60. var th = [];
  61. var x2 = undefined;
  62. var x4 = undefined;
  63. var x8 = undefined;
  64. var s = undefined;
  65. var tEnc = undefined;
  66. var tDec = undefined;
  67. // Compute double and third tables
  68. for (i = 0; i < 256; i++) {
  69. th[(d[i] = i << 1 ^ (i >> 7) * 283) ^ i] = i;
  70. }
  71. for (x = xInv = 0; !sbox[x]; x ^= x2 || 1, xInv = th[xInv] || 1) {
  72. // Compute sbox
  73. s = xInv ^ xInv << 1 ^ xInv << 2 ^ xInv << 3 ^ xInv << 4;
  74. s = s >> 8 ^ s & 255 ^ 99;
  75. sbox[x] = s;
  76. sboxInv[s] = x;
  77. // Compute MixColumns
  78. x8 = d[x4 = d[x2 = d[x]]];
  79. tDec = x8 * 0x1010101 ^ x4 * 0x10001 ^ x2 * 0x101 ^ x * 0x1010100;
  80. tEnc = d[s] * 0x101 ^ s * 0x1010100;
  81. for (i = 0; i < 4; i++) {
  82. encTable[i][x] = tEnc = tEnc << 24 ^ tEnc >>> 8;
  83. decTable[i][s] = tDec = tDec << 24 ^ tDec >>> 8;
  84. }
  85. }
  86. // Compactify. Considerable speedup on Firefox.
  87. for (i = 0; i < 5; i++) {
  88. encTable[i] = encTable[i].slice(0);
  89. decTable[i] = decTable[i].slice(0);
  90. }
  91. return tables;
  92. };
  93. var aesTables = null;
  94. /**
  95. * Schedule out an AES key for both encryption and decryption. This
  96. * is a low-level class. Use a cipher mode to do bulk encryption.
  97. *
  98. * @class AES
  99. * @param key {Array} The key as an array of 4, 6 or 8 words.
  100. */
  101. var AES = (function () {
  102. function AES(key) {
  103. _classCallCheck(this, AES);
  104. /**
  105. * The expanded S-box and inverse S-box tables. These will be computed
  106. * on the client so that we don't have to send them down the wire.
  107. *
  108. * There are two tables, _tables[0] is for encryption and
  109. * _tables[1] is for decryption.
  110. *
  111. * The first 4 sub-tables are the expanded S-box with MixColumns. The
  112. * last (_tables[01][4]) is the S-box itself.
  113. *
  114. * @private
  115. */
  116. // if we have yet to precompute the S-box tables
  117. // do so now
  118. if (!aesTables) {
  119. aesTables = precompute();
  120. }
  121. // then make a copy of that object for use
  122. this._tables = [[aesTables[0][0].slice(), aesTables[0][1].slice(), aesTables[0][2].slice(), aesTables[0][3].slice(), aesTables[0][4].slice()], [aesTables[1][0].slice(), aesTables[1][1].slice(), aesTables[1][2].slice(), aesTables[1][3].slice(), aesTables[1][4].slice()]];
  123. var i = undefined;
  124. var j = undefined;
  125. var tmp = undefined;
  126. var encKey = undefined;
  127. var decKey = undefined;
  128. var sbox = this._tables[0][4];
  129. var decTable = this._tables[1];
  130. var keyLen = key.length;
  131. var rcon = 1;
  132. if (keyLen !== 4 && keyLen !== 6 && keyLen !== 8) {
  133. throw new Error('Invalid aes key size');
  134. }
  135. encKey = key.slice(0);
  136. decKey = [];
  137. this._key = [encKey, decKey];
  138. // schedule encryption keys
  139. for (i = keyLen; i < 4 * keyLen + 28; i++) {
  140. tmp = encKey[i - 1];
  141. // apply sbox
  142. if (i % keyLen === 0 || keyLen === 8 && i % keyLen === 4) {
  143. tmp = sbox[tmp >>> 24] << 24 ^ sbox[tmp >> 16 & 255] << 16 ^ sbox[tmp >> 8 & 255] << 8 ^ sbox[tmp & 255];
  144. // shift rows and add rcon
  145. if (i % keyLen === 0) {
  146. tmp = tmp << 8 ^ tmp >>> 24 ^ rcon << 24;
  147. rcon = rcon << 1 ^ (rcon >> 7) * 283;
  148. }
  149. }
  150. encKey[i] = encKey[i - keyLen] ^ tmp;
  151. }
  152. // schedule decryption keys
  153. for (j = 0; i; j++, i--) {
  154. tmp = encKey[j & 3 ? i : i - 4];
  155. if (i <= 4 || j < 4) {
  156. decKey[j] = tmp;
  157. } else {
  158. decKey[j] = decTable[0][sbox[tmp >>> 24]] ^ decTable[1][sbox[tmp >> 16 & 255]] ^ decTable[2][sbox[tmp >> 8 & 255]] ^ decTable[3][sbox[tmp & 255]];
  159. }
  160. }
  161. }
  162. /**
  163. * Decrypt 16 bytes, specified as four 32-bit words.
  164. *
  165. * @param {Number} encrypted0 the first word to decrypt
  166. * @param {Number} encrypted1 the second word to decrypt
  167. * @param {Number} encrypted2 the third word to decrypt
  168. * @param {Number} encrypted3 the fourth word to decrypt
  169. * @param {Int32Array} out the array to write the decrypted words
  170. * into
  171. * @param {Number} offset the offset into the output array to start
  172. * writing results
  173. * @return {Array} The plaintext.
  174. */
  175. _createClass(AES, [{
  176. key: 'decrypt',
  177. value: function decrypt(encrypted0, encrypted1, encrypted2, encrypted3, out, offset) {
  178. var key = this._key[1];
  179. // state variables a,b,c,d are loaded with pre-whitened data
  180. var a = encrypted0 ^ key[0];
  181. var b = encrypted3 ^ key[1];
  182. var c = encrypted2 ^ key[2];
  183. var d = encrypted1 ^ key[3];
  184. var a2 = undefined;
  185. var b2 = undefined;
  186. var c2 = undefined;
  187. // key.length === 2 ?
  188. var nInnerRounds = key.length / 4 - 2;
  189. var i = undefined;
  190. var kIndex = 4;
  191. var table = this._tables[1];
  192. // load up the tables
  193. var table0 = table[0];
  194. var table1 = table[1];
  195. var table2 = table[2];
  196. var table3 = table[3];
  197. var sbox = table[4];
  198. // Inner rounds. Cribbed from OpenSSL.
  199. for (i = 0; i < nInnerRounds; i++) {
  200. a2 = table0[a >>> 24] ^ table1[b >> 16 & 255] ^ table2[c >> 8 & 255] ^ table3[d & 255] ^ key[kIndex];
  201. b2 = table0[b >>> 24] ^ table1[c >> 16 & 255] ^ table2[d >> 8 & 255] ^ table3[a & 255] ^ key[kIndex + 1];
  202. c2 = table0[c >>> 24] ^ table1[d >> 16 & 255] ^ table2[a >> 8 & 255] ^ table3[b & 255] ^ key[kIndex + 2];
  203. d = table0[d >>> 24] ^ table1[a >> 16 & 255] ^ table2[b >> 8 & 255] ^ table3[c & 255] ^ key[kIndex + 3];
  204. kIndex += 4;
  205. a = a2;b = b2;c = c2;
  206. }
  207. // Last round.
  208. for (i = 0; i < 4; i++) {
  209. out[(3 & -i) + offset] = sbox[a >>> 24] << 24 ^ sbox[b >> 16 & 255] << 16 ^ sbox[c >> 8 & 255] << 8 ^ sbox[d & 255] ^ key[kIndex++];
  210. a2 = a;a = b;b = c;c = d;d = a2;
  211. }
  212. }
  213. }]);
  214. return AES;
  215. })();
  216. exports['default'] = AES;
  217. module.exports = exports['default'];