AES.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621
  1. (function() {
  2. var Nr = 10;
  3. // convert two-dimensional indicies to one-dim array indices
  4. var I00 = 0;
  5. var I01 = 1;
  6. var I02 = 2;
  7. var I03 = 3;
  8. var I10 = 4;
  9. var I11 = 5;
  10. var I12 = 6;
  11. var I13 = 7;
  12. var I20 = 8;
  13. var I21 = 9;
  14. var I22 = 10;
  15. var I23 = 11;
  16. var I30 = 12;
  17. var I31 = 13;
  18. var I32 = 14;
  19. var I33 = 15;
  20. // S-Box substitution table
  21. var S_enc = new Array(
  22. 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
  23. 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
  24. 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
  25. 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
  26. 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
  27. 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
  28. 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
  29. 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
  30. 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
  31. 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
  32. 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
  33. 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
  34. 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
  35. 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
  36. 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
  37. 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
  38. 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
  39. 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
  40. 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
  41. 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
  42. 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
  43. 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
  44. 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
  45. 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
  46. 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
  47. 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
  48. 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
  49. 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
  50. 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
  51. 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
  52. 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
  53. 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16);
  54. // inverse S-Box for decryptions
  55. var S_dec = new Array(
  56. 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
  57. 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
  58. 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
  59. 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
  60. 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
  61. 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
  62. 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
  63. 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
  64. 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
  65. 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
  66. 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
  67. 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
  68. 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
  69. 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
  70. 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
  71. 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
  72. 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
  73. 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
  74. 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
  75. 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
  76. 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
  77. 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
  78. 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
  79. 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
  80. 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
  81. 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
  82. 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
  83. 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
  84. 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
  85. 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
  86. 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
  87. 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d);
  88. function cvt_hex8 (val) {
  89. var vh = (val>>>4)&0x0f;
  90. return vh.toString(16) + (val&0x0f).toString(16);
  91. }
  92. function cvt_byte (str) {
  93. // get the first hex digit
  94. var val1 = str.charCodeAt(0);
  95. // do some error checking
  96. if (val1 >= 48 && val1 <= 57) {
  97. // have a valid digit 0-9
  98. val1 -= 48;
  99. } else if (val1 >= 65 && val1 <= 70) {
  100. // have a valid digit A-F
  101. val1 -= 55;
  102. } else if (val1 >= 97 && val1 <= 102) {
  103. // have a valid digit A-F
  104. val1 -= 87;
  105. } else {
  106. // not 0-9 or A-F, complain
  107. console.log( str.charAt(1)+" is not a valid hex digit" );
  108. return -1;
  109. }
  110. // get the second hex digit
  111. var val2 = str.charCodeAt(1);
  112. // do some error checking
  113. if ( val2 >= 48 && val2 <= 57 ) {
  114. // have a valid digit 0-9
  115. val2 -= 48;
  116. } else if ( val2 >= 65 && val2 <= 70 ) {
  117. // have a valid digit A-F
  118. val2 -= 55;
  119. } else if ( val2 >= 97 && val2 <= 102 ) {
  120. // have a valid digit A-F
  121. val2 -= 87;
  122. } else {
  123. // not 0-9 or A-F, complain
  124. console.log( str.charAt(2)+" is not a valid hex digit" );
  125. return -1;
  126. }
  127. // all is ok, return the value
  128. return val1*16 + val2;
  129. }
  130. // conversion function for non-constant subscripts
  131. // assume subscript range 0..3
  132. function I(x,y) {
  133. return (x*4) + y;
  134. }
  135. // remove spaces from input
  136. function remove_spaces(instr) {
  137. var i;
  138. var outstr = "";
  139. for(i=0; i<instr.length; i++) {
  140. if ( instr.charAt(i) != " " )
  141. // not a space, include it
  142. outstr += instr.charAt(i);
  143. }
  144. return outstr;
  145. }
  146. // get the message to encrypt/decrypt or the key
  147. // return as a 16-byte array
  148. function get_value(str, isASCII) {
  149. var dbyte = new Array(16);
  150. var i;
  151. var val; // one hex digit
  152. if (isASCII) {
  153. // check length of data
  154. if (str.length > 16) {
  155. console.log("is too long, using the first 16 ASCII characters" );
  156. }
  157. // have ASCII data
  158. // 16 characters?
  159. if (str.length >= 16) {
  160. // 16 or more characters
  161. for(i=0; i<16; i++) {
  162. dbyte[i] = str.charCodeAt(i);
  163. }
  164. } else {
  165. // less than 16 characters - fill with NULLs
  166. for(i=0; i<str.length; i++) {
  167. dbyte[i] = str.charCodeAt(i);
  168. }
  169. for( i=str.length; i<16; i++) {
  170. dbyte[i] = 0;
  171. }
  172. }
  173. } else {
  174. // have hex data - remove any spaces they used, then convert
  175. //str = remove_spaces(str);
  176. // check length of data
  177. if ( str.length != 32 ) {
  178. //console.log("\tget_value:\tstr = " + str + "\tisASCII = " + isASCII); //isASCII = false
  179. console.log("length wrong: Is " + str.length + " hex digits, but must be 128 bits (32 hex digits)");
  180. dbyte[0] = -1;
  181. return dbyte;
  182. }
  183. for( i=0; i<16; i++ ) {
  184. // isolate and convert this substring
  185. dbyte[i] = cvt_byte( str.substr(i*2,2) );
  186. if( dbyte[i] < 0 ) {
  187. // have an error
  188. dbyte[0] = -1;
  189. return dbyte;
  190. }
  191. }
  192. }
  193. // return successful conversion
  194. return dbyte;
  195. }
  196. //do the AES GF(2**8) multiplication
  197. // do this by the shift-and-"add" approach
  198. function aes_mul(a, b) {
  199. var res = 0;
  200. while(a > 0) {
  201. if((a&1) != 0)
  202. res = res ^ b; // "add" to the result
  203. a >>>= 1; // shift a to get next higher-order bit
  204. b <<= 1; // shift multiplier also
  205. }
  206. // now reduce it modulo x**8 + x**4 + x**3 + x + 1
  207. var hbit = 0x10000; // bit to test if we need to take action
  208. var modulus = 0x11b00; // modulus - XOR by this to change value
  209. while(hbit >= 0x100) {
  210. if ((res & hbit) != 0) {
  211. res ^= modulus; // XOR with the modulus
  212. }
  213. // prepare for the next loop
  214. hbit >>= 1;
  215. modulus >>= 1;
  216. }
  217. return res;
  218. }
  219. // apply the S-box substitution to the key expansion
  220. function SubWord(word_ary) {
  221. var i;
  222. for(i=0; i<16; i++) {
  223. word_ary[i] = S_enc[word_ary[i]];
  224. }
  225. return word_ary;
  226. }
  227. // rotate the bytes in a word
  228. function RotWord(word_ary) {
  229. return new Array(word_ary[1], word_ary[2], word_ary[3], word_ary[0]);
  230. }
  231. // calculate the first item Rcon[i] = { x^(i-1), 0, 0, 0 }
  232. // note we only return the first item
  233. function Rcon(exp) {
  234. var val = 2;
  235. var result = 1;
  236. // remember to calculate x^(exp-1)
  237. exp--;
  238. // process the exponent using normal shift and multiply
  239. while ( exp > 0 )
  240. {
  241. if ( (exp & 1) != 0 )
  242. result = aes_mul( result, val );
  243. // square the value
  244. val = aes_mul( val, val );
  245. // move to the next bit
  246. exp >>= 1;
  247. }
  248. return result;
  249. }
  250. // round key generation
  251. // return a byte array with the expanded key information
  252. function key_expand( key )
  253. {
  254. var temp = new Array(4);
  255. var i, j;
  256. var w = new Array(4*(Nr+1));
  257. // copy initial key stuff
  258. for( i=0; i<16; i++ )
  259. {
  260. w[i] = key[i];
  261. }
  262. // generate rest of key schedule using 32-bit words
  263. i = 4;
  264. while ( i < 4*(Nr+1)) // blocksize * ( rounds + 1 )
  265. {
  266. // copy word W[i-1] to temp
  267. for( j=0; j<4; j++ )
  268. temp[j] = w[(i-1)*4+j];
  269. if ( i % 4 == 0)
  270. {
  271. // temp = SubWord(RotWord(temp)) ^ Rcon[i/4];
  272. temp = RotWord( temp );
  273. temp = SubWord( temp );
  274. temp[0] ^= Rcon( i>>>2 );
  275. }
  276. // word = word ^ temp
  277. for( j=0; j<4; j++ )
  278. w[i*4+j] = w[(i-4)*4+j] ^ temp[j];
  279. i++;
  280. }
  281. return w;
  282. }
  283. // do S-Box substitution
  284. function SubBytes(state, Sbox)
  285. {
  286. var i;
  287. for( i=0; i<16; i++ )
  288. state[i] = Sbox[ state[i] ];
  289. return state;
  290. }
  291. // shift each row as appropriate
  292. function ShiftRows(state)
  293. {
  294. var t0, t1, t2, t3;
  295. // top row (row 0) isn't shifted
  296. // next row (row 1) rotated left 1 place
  297. t0 = state[I10];
  298. t1 = state[I11];
  299. t2 = state[I12];
  300. t3 = state[I13];
  301. state[I10] = t1;
  302. state[I11] = t2;
  303. state[I12] = t3;
  304. state[I13] = t0;
  305. // next row (row 2) rotated left 2 places
  306. t0 = state[I20];
  307. t1 = state[I21];
  308. t2 = state[I22];
  309. t3 = state[I23];
  310. state[I20] = t2;
  311. state[I21] = t3;
  312. state[I22] = t0;
  313. state[I23] = t1;
  314. // bottom row (row 3) rotated left 3 places
  315. t0 = state[I30];
  316. t1 = state[I31];
  317. t2 = state[I32];
  318. t3 = state[I33];
  319. state[I30] = t3;
  320. state[I31] = t0;
  321. state[I32] = t1;
  322. state[I33] = t2;
  323. return state;
  324. }
  325. // inverset shift each row as appropriate
  326. function InvShiftRows(state)
  327. {
  328. var t0, t1, t2, t3;
  329. // top row (row 0) isn't shifted
  330. // next row (row 1) rotated left 1 place
  331. t0 = state[I10];
  332. t1 = state[I11];
  333. t2 = state[I12];
  334. t3 = state[I13];
  335. state[I10] = t3;
  336. state[I11] = t0;
  337. state[I12] = t1;
  338. state[I13] = t2;
  339. // next row (row 2) rotated left 2 places
  340. t0 = state[I20];
  341. t1 = state[I21];
  342. t2 = state[I22];
  343. t3 = state[I23];
  344. state[I20] = t2;
  345. state[I21] = t3;
  346. state[I22] = t0;
  347. state[I23] = t1;
  348. // bottom row (row 3) rotated left 3 places
  349. t0 = state[I30];
  350. t1 = state[I31];
  351. t2 = state[I32];
  352. t3 = state[I33];
  353. state[I30] = t1;
  354. state[I31] = t2;
  355. state[I32] = t3;
  356. state[I33] = t0;
  357. return state;
  358. }
  359. // process column info
  360. function MixColumns(state)
  361. {
  362. var col;
  363. var c0, c1, c2, c3;
  364. for( col=0; col<4; col++ )
  365. {
  366. c0 = state[I(0,col)];
  367. c1 = state[I(1,col)];
  368. c2 = state[I(2,col)];
  369. c3 = state[I(3,col)];
  370. // do mixing, and put back into array
  371. state[I(0,col)] = aes_mul(2,c0) ^ aes_mul(3,c1) ^ c2 ^ c3;
  372. state[I(1,col)] = c0 ^ aes_mul(2,c1) ^ aes_mul(3,c2) ^ c3;
  373. state[I(2,col)] = c0 ^ c1 ^ aes_mul(2,c2) ^ aes_mul(3,c3);
  374. state[I(3,col)] = aes_mul(3,c0) ^ c1 ^ c2 ^ aes_mul(2,c3);
  375. }
  376. return state;
  377. }
  378. // inverse process column info
  379. function InvMixColumns(state)
  380. {
  381. var col;
  382. var c0, c1, c2, c3;
  383. for( col=0; col<4; col++ )
  384. {
  385. c0 = state[I(0,col)];
  386. c1 = state[I(1,col)];
  387. c2 = state[I(2,col)];
  388. c3 = state[I(3,col)];
  389. // do inverse mixing, and put back into array
  390. state[I(0,col)] = aes_mul(0x0e,c0) ^ aes_mul(0x0b,c1)
  391. ^ aes_mul(0x0d,c2) ^ aes_mul(0x09,c3);
  392. state[I(1,col)] = aes_mul(0x09,c0) ^ aes_mul(0x0e,c1)
  393. ^ aes_mul(0x0b,c2) ^ aes_mul(0x0d,c3);
  394. state[I(2,col)] = aes_mul(0x0d,c0) ^ aes_mul(0x09,c1)
  395. ^ aes_mul(0x0e,c2) ^ aes_mul(0x0b,c3);
  396. state[I(3,col)] = aes_mul(0x0b,c0) ^ aes_mul(0x0d,c1)
  397. ^ aes_mul(0x09,c2) ^ aes_mul(0x0e,c3);
  398. }
  399. return state;
  400. }
  401. // insert subkey information
  402. function AddRoundKey( state, w, base )
  403. {
  404. var col;
  405. for( col=0; col<4; col++ )
  406. {
  407. state[I(0,col)] ^= w[base+col*4];
  408. state[I(1,col)] ^= w[base+col*4+1];
  409. state[I(2,col)] ^= w[base+col*4+2];
  410. state[I(3,col)] ^= w[base+col*4+3];
  411. }
  412. return state;
  413. }
  414. // return a transposed array
  415. function transpose( msg )
  416. {
  417. var row, col;
  418. var state = new Array( 16 );
  419. for( row=0; row<4; row++ )
  420. for( col=0; col<4; col++ )
  421. state[I(row,col)] = msg[I(col,row)];
  422. return state;
  423. }
  424. // final AES state
  425. var AES_output = new Array(16);
  426. // format AES output
  427. // -- uses the global array DES_output
  428. function format_AES_output(bASCII)
  429. {
  430. var i;
  431. var bits;
  432. var str="";
  433. // what type of data do we have to work with?
  434. if (bASCII)
  435. {
  436. // convert each set of bits back to ASCII
  437. for( i=0; i<16; i++ )
  438. str += String.fromCharCode( AES_output[i] );
  439. }
  440. else
  441. {
  442. // output hexdecimal data (insert spaces)
  443. str = cvt_hex8( AES_output[0] );
  444. for( i=1; i<16; i++ )
  445. {
  446. str += "" + cvt_hex8( AES_output[i] );
  447. }
  448. }
  449. return str;
  450. }
  451. // do encrytion
  452. function aes_encrypt(str, key, bASCII)
  453. {
  454. //console.log(" aes_encrypt:\tstr = " + str + "\tkey = " + key + "\t bASCII = " + bASCII);
  455. var w = new Array( 4*(Nr+1) ); // subkey information
  456. var state = new Array( 16 ); // working state
  457. var round;
  458. //accumulated_output_info = "";
  459. // get the message from the user
  460. // also check if it is ASCII or hex
  461. var msg = get_value(str, bASCII);
  462. // problems??
  463. if ( msg[0] < 0 )
  464. {
  465. return;
  466. }
  467. // get the key from the user
  468. var key = get_value(key, false);
  469. // problems??
  470. if ( key[0] < 0 )
  471. {
  472. return;
  473. }
  474. // expand the key
  475. w = key_expand( key );
  476. // initial state = message in columns (transposed from what we input)
  477. state = transpose( msg );
  478. // display the round key - Transpose due to the way it is stored/used
  479. state = AddRoundKey(state, w, 0);
  480. for( round=1; round<Nr; round++ )
  481. {
  482. state = SubBytes(state, S_enc);
  483. state = ShiftRows(state);
  484. state = MixColumns(state);
  485. // display the round key - Transpose due to the way it is stored/used
  486. // note here the spec uses 32-bit words, we are using bytes, so an extra *4
  487. state = AddRoundKey(state, w, round*4*4);
  488. }
  489. SubBytes(state, S_enc);
  490. ShiftRows(state);
  491. AddRoundKey(state, w, Nr*4*4);
  492. // process output
  493. AES_output = transpose( state );
  494. var szOutput = format_AES_output(!bASCII);
  495. return szOutput;
  496. }
  497. // do decryption
  498. function aes_decrypt(str, key, bASCII)
  499. {
  500. //console.log(" aes_decrypt:\tstr = " + str + "\tkey = " + key + "\tbASCII = " + bASCII);
  501. var w = new Array( 4*(Nr+1) ); // subkey information
  502. var state = new Array( 16 ); // working state
  503. var round;
  504. //accumulated_output_info = "";
  505. // get the message from the user
  506. // also check if it is ASCII or hex
  507. var msg = get_value(str, bASCII);
  508. // problems??
  509. if ( msg[0] < 0 )
  510. {
  511. return;
  512. }
  513. // get the key from the user
  514. var key = get_value(key, false);
  515. // problems??
  516. if ( key[0] < 0 )
  517. {
  518. return;
  519. }
  520. // expand the key
  521. w = key_expand( key );
  522. // initial state = message
  523. state = transpose( msg );
  524. // display the round key - Transpose due to the way it is stored/used
  525. state = AddRoundKey(state, w, Nr*4*4);
  526. for( round=Nr-1; round>=1; round-- )
  527. {
  528. state = InvShiftRows(state);
  529. state = SubBytes(state, S_dec);
  530. // display the round key - Transpose due to the way it is stored/used
  531. // note here the spec uses 32-bit words, we are using bytes, so an extra *4
  532. state = AddRoundKey(state, w, round*4*4);
  533. state = InvMixColumns(state);
  534. }
  535. InvShiftRows(state);
  536. SubBytes(state, S_dec);
  537. AddRoundKey(state, w, 0);
  538. // process output
  539. AES_output = transpose( state );
  540. var szOutput = format_AES_output(!bASCII);
  541. return szOutput;
  542. }
  543. window.aes_encrypt = aes_encrypt;
  544. window.aes_decrypt = aes_decrypt;
  545. window.console = window.console || {
  546. log: function() {}
  547. };
  548. }());