Stary2001

aes.lua

Mar 23rd, 2013
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.90 KB | None | 0 0
  1. require("bit");
  2.  
  3. local gf = require("aeslua.gf");
  4. local util = require("aeslua.util");
  5.  
  6. --
  7. -- Implementation of AES with nearly pure lua (only bitlib is needed)
  8. --
  9. -- AES with lua is slow, really slow :-)
  10. --
  11.  
  12. local public = {};
  13. local private = {};
  14.  
  15. aeslua.aes = public;
  16.  
  17. -- some constants
  18. public.ROUNDS = "rounds";
  19. public.KEY_TYPE = "type";
  20. public.ENCRYPTION_KEY=1;
  21. public.DECRYPTION_KEY=2;
  22.  
  23. -- aes SBOX
  24. private.SBox = {};
  25. private.iSBox = {};
  26.  
  27. -- aes tables
  28. private.table0 = {};
  29. private.table1 = {};
  30. private.table2 = {};
  31. private.table3 = {};
  32.  
  33. private.tableInv0 = {};
  34. private.tableInv1 = {};
  35. private.tableInv2 = {};
  36. private.tableInv3 = {};
  37.  
  38. -- round constants
  39. private.rCon = {0x01000000,
  40. 0x02000000,
  41. 0x04000000,
  42. 0x08000000,
  43. 0x10000000,
  44. 0x20000000,
  45. 0x40000000,
  46. 0x80000000,
  47. 0x1b000000,
  48. 0x36000000,
  49. 0x6c000000,
  50. 0xd8000000,
  51. 0xab000000,
  52. 0x4d000000,
  53. 0x9a000000,
  54. 0x2f000000};
  55.  
  56. --
  57. -- affine transformation for calculating the S-Box of AES
  58. --
  59. function private.affinMap(byte)
  60. mask = 0xf8;
  61. result = 0;
  62. for i = 1,8 do
  63. result = bit.lshift(result,1);
  64.  
  65. parity = util.byteParity(bit.band(byte,mask));
  66. result = result + parity
  67.  
  68. -- simulate roll
  69. lastbit = bit.band(mask, 1);
  70. mask = bit.band(bit.rshift(mask, 1),0xff);
  71. if (lastbit ~= 0) then
  72. mask = bit.bor(mask, 0x80);
  73. else
  74. mask = bit.band(mask, 0x7f);
  75. end
  76. end
  77.  
  78. return bit.bxor(result, 0x63);
  79. end
  80.  
  81. --
  82. -- calculate S-Box and inverse S-Box of AES
  83. -- apply affine transformation to inverse in finite field 2^8
  84. --
  85. function private.calcSBox()
  86. for i = 0, 255 do
  87. if (i ~= 0) then
  88. inverse = gf.invert(i);
  89. else
  90. inverse = i;
  91. end
  92. mapped = private.affinMap(inverse);
  93. private.SBox[i] = mapped;
  94. private.iSBox[mapped] = i;
  95. end
  96. end
  97.  
  98. --
  99. -- Calculate round tables
  100. -- round tables are used to calculate shiftRow, MixColumn and SubBytes
  101. -- with 4 table lookups and 4 xor operations.
  102. --
  103. function private.calcRoundTables()
  104. for x = 0,255 do
  105. byte = private.SBox[x];
  106. private.table0[x] = util.putByte(gf.mul(0x03, byte), 0)
  107. + util.putByte( byte , 1)
  108. + util.putByte( byte , 2)
  109. + util.putByte(gf.mul(0x02, byte), 3);
  110. private.table1[x] = util.putByte( byte , 0)
  111. + util.putByte( byte , 1)
  112. + util.putByte(gf.mul(0x02, byte), 2)
  113. + util.putByte(gf.mul(0x03, byte), 3);
  114. private.table2[x] = util.putByte( byte , 0)
  115. + util.putByte(gf.mul(0x02, byte), 1)
  116. + util.putByte(gf.mul(0x03, byte), 2)
  117. + util.putByte( byte , 3);
  118. private.table3[x] = util.putByte(gf.mul(0x02, byte), 0)
  119. + util.putByte(gf.mul(0x03, byte), 1)
  120. + util.putByte( byte , 2)
  121. + util.putByte( byte , 3);
  122. end
  123. end
  124.  
  125. --
  126. -- Calculate inverse round tables
  127. -- does the inverse of the normal roundtables for the equivalent
  128. -- decryption algorithm.
  129. --
  130. function private.calcInvRoundTables()
  131. for x = 0,255 do
  132. byte = private.iSBox[x];
  133. private.tableInv0[x] = util.putByte(gf.mul(0x0b, byte), 0)
  134. + util.putByte(gf.mul(0x0d, byte), 1)
  135. + util.putByte(gf.mul(0x09, byte), 2)
  136. + util.putByte(gf.mul(0x0e, byte), 3);
  137. private.tableInv1[x] = util.putByte(gf.mul(0x0d, byte), 0)
  138. + util.putByte(gf.mul(0x09, byte), 1)
  139. + util.putByte(gf.mul(0x0e, byte), 2)
  140. + util.putByte(gf.mul(0x0b, byte), 3);
  141. private.tableInv2[x] = util.putByte(gf.mul(0x09, byte), 0)
  142. + util.putByte(gf.mul(0x0e, byte), 1)
  143. + util.putByte(gf.mul(0x0b, byte), 2)
  144. + util.putByte(gf.mul(0x0d, byte), 3);
  145. private.tableInv3[x] = util.putByte(gf.mul(0x0e, byte), 0)
  146. + util.putByte(gf.mul(0x0b, byte), 1)
  147. + util.putByte(gf.mul(0x0d, byte), 2)
  148. + util.putByte(gf.mul(0x09, byte), 3);
  149. end
  150. end
  151.  
  152.  
  153. --
  154. -- rotate word: 0xaabbccdd gets 0xbbccddaa
  155. -- used for key schedule
  156. --
  157. function private.rotWord(word)
  158. local tmp = bit.band(word,0xff000000);
  159. return (bit.lshift(word,8) + bit.rshift(tmp,24)) ;
  160. end
  161.  
  162. --
  163. -- replace all bytes in a word with the SBox.
  164. -- used for key schedule
  165. --
  166. function private.subWord(word)
  167. return util.putByte(private.SBox[util.getByte(word,0)],0)
  168. + util.putByte(private.SBox[util.getByte(word,1)],1)
  169. + util.putByte(private.SBox[util.getByte(word,2)],2)
  170. + util.putByte(private.SBox[util.getByte(word,3)],3);
  171. end
  172.  
  173. --
  174. -- generate key schedule for aes encryption
  175. --
  176. -- returns table with all round keys and
  177. -- the necessary number of rounds saved in [public.ROUNDS]
  178. --
  179. function public.expandEncryptionKey(key)
  180. local keySchedule = {};
  181. local keyWords = math.floor(#key / 4);
  182.  
  183.  
  184. if ((keyWords ~= 4 and keyWords ~= 6 and keyWords ~= 8) or (keyWords * 4 ~= #key)) then
  185. print("Invalid key size: ", keyWords);
  186. return nil;
  187. end
  188.  
  189. keySchedule[public.ROUNDS] = keyWords + 6;
  190. keySchedule[public.KEY_TYPE] = public.ENCRYPTION_KEY;
  191.  
  192. for i = 0,keyWords - 1 do
  193. keySchedule[i] = util.putByte(key[i*4+1], 3)
  194. + util.putByte(key[i*4+2], 2)
  195. + util.putByte(key[i*4+3], 1)
  196. + util.putByte(key[i*4+4], 0);
  197. end
  198.  
  199. for i = keyWords, (keySchedule[public.ROUNDS] + 1)*4 - 1 do
  200. local tmp = keySchedule[i-1];
  201.  
  202. if ( i % keyWords == 0) then
  203. tmp = private.rotWord(tmp);
  204. tmp = private.subWord(tmp);
  205.  
  206. local index = math.floor(i/keyWords);
  207. tmp = bit.bxor(tmp,private.rCon[index]);
  208. elseif (keyWords > 6 and i % keyWords == 4) then
  209. tmp = private.subWord(tmp);
  210. end
  211.  
  212. keySchedule[i] = bit.bxor(keySchedule[(i-keyWords)],tmp);
  213. end
  214.  
  215. return keySchedule;
  216. end
  217.  
  218. --
  219. -- Inverse mix column
  220. -- used for key schedule of decryption key
  221. --
  222. function private.invMixColumnOld(word)
  223. local b0 = util.getByte(word,3);
  224. local b1 = util.getByte(word,2);
  225. local b2 = util.getByte(word,1);
  226. local b3 = util.getByte(word,0);
  227.  
  228. return util.putByte(gf.add(gf.add(gf.add(gf.mul(0x0b, b1),
  229. gf.mul(0x0d, b2)),
  230. gf.mul(0x09, b3)),
  231. gf.mul(0x0e, b0)),3)
  232. + util.putByte(gf.add(gf.add(gf.add(gf.mul(0x0b, b2),
  233. gf.mul(0x0d, b3)),
  234. gf.mul(0x09, b0)),
  235. gf.mul(0x0e, b1)),2)
  236. + util.putByte(gf.add(gf.add(gf.add(gf.mul(0x0b, b3),
  237. gf.mul(0x0d, b0)),
  238. gf.mul(0x09, b1)),
  239. gf.mul(0x0e, b2)),1)
  240. + util.putByte(gf.add(gf.add(gf.add(gf.mul(0x0b, b0),
  241. gf.mul(0x0d, b1)),
  242. gf.mul(0x09, b2)),
  243. gf.mul(0x0e, b3)),0);
  244. end
  245.  
  246. --
  247. -- Optimized inverse mix column
  248. -- look at http://fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.311.pdf
  249. -- TODO: make it work
  250. --
  251. function private.invMixColumn(word)
  252. local b0 = util.getByte(word,3);
  253. local b1 = util.getByte(word,2);
  254. local b2 = util.getByte(word,1);
  255. local b3 = util.getByte(word,0);
  256.  
  257. local t = bit.bxor(b3,b2);
  258. local u = bit.bxor(b1,b0);
  259. local v = bit.bxor(t,u);
  260. v = bit.bxor(v,gf.mul(0x08,v));
  261. w = bit.bxor(v,gf.mul(0x04, bit.bxor(b2,b0)));
  262. v = bit.bxor(v,gf.mul(0x04, bit.bxor(b3,b1)));
  263.  
  264. return util.putByte( bit.bxor(bit.bxor(b3,v), gf.mul(0x02, bit.bxor(b0,b3))), 0)
  265. + util.putByte( bit.bxor(bit.bxor(b2,w), gf.mul(0x02, t )), 1)
  266. + util.putByte( bit.bxor(bit.bxor(b1,v), gf.mul(0x02, bit.bxor(b0,b3))), 2)
  267. + util.putByte( bit.bxor(bit.bxor(b0,w), gf.mul(0x02, u )), 3);
  268. end
  269.  
  270. --
  271. -- generate key schedule for aes decryption
  272. --
  273. -- uses key schedule for aes encryption and transforms each
  274. -- key by inverse mix column.
  275. --
  276. function public.expandDecryptionKey(key)
  277. local keySchedule = public.expandEncryptionKey(key);
  278. if (keySchedule == nil) then
  279. return nil;
  280. end
  281.  
  282. keySchedule[public.KEY_TYPE] = public.DECRYPTION_KEY;
  283.  
  284. for i = 4, (keySchedule[public.ROUNDS] + 1)*4 - 5 do
  285. keySchedule[i] = private.invMixColumnOld(keySchedule[i]);
  286. end
  287.  
  288. return keySchedule;
  289. end
  290.  
  291. --
  292. -- xor round key to state
  293. --
  294. function private.addRoundKey(state, key, round)
  295. for i = 0, 3 do
  296. state[i] = bit.bxor(state[i], key[round*4+i]);
  297. end
  298. end
  299.  
  300. --
  301. -- do encryption round (ShiftRow, SubBytes, MixColumn together)
  302. --
  303. function private.doRound(origState, dstState)
  304. dstState[0] = bit.bxor(bit.bxor(bit.bxor(
  305. private.table0[util.getByte(origState[0],3)],
  306. private.table1[util.getByte(origState[1],2)]),
  307. private.table2[util.getByte(origState[2],1)]),
  308. private.table3[util.getByte(origState[3],0)]);
  309.  
  310. dstState[1] = bit.bxor(bit.bxor(bit.bxor(
  311. private.table0[util.getByte(origState[1],3)],
  312. private.table1[util.getByte(origState[2],2)]),
  313. private.table2[util.getByte(origState[3],1)]),
  314. private.table3[util.getByte(origState[0],0)]);
  315.  
  316. dstState[2] = bit.bxor(bit.bxor(bit.bxor(
  317. private.table0[util.getByte(origState[2],3)],
  318. private.table1[util.getByte(origState[3],2)]),
  319. private.table2[util.getByte(origState[0],1)]),
  320. private.table3[util.getByte(origState[1],0)]);
  321.  
  322. dstState[3] = bit.bxor(bit.bxor(bit.bxor(
  323. private.table0[util.getByte(origState[3],3)],
  324. private.table1[util.getByte(origState[0],2)]),
  325. private.table2[util.getByte(origState[1],1)]),
  326. private.table3[util.getByte(origState[2],0)]);
  327. end
  328.  
  329. --
  330. -- do last encryption round (ShiftRow and SubBytes)
  331. --
  332. function private.doLastRound(origState, dstState)
  333. dstState[0] = util.putByte(private.SBox[util.getByte(origState[0],3)], 3)
  334. + util.putByte(private.SBox[util.getByte(origState[1],2)], 2)
  335. + util.putByte(private.SBox[util.getByte(origState[2],1)], 1)
  336. + util.putByte(private.SBox[util.getByte(origState[3],0)], 0);
  337.  
  338. dstState[1] = util.putByte(private.SBox[util.getByte(origState[1],3)], 3)
  339. + util.putByte(private.SBox[util.getByte(origState[2],2)], 2)
  340. + util.putByte(private.SBox[util.getByte(origState[3],1)], 1)
  341. + util.putByte(private.SBox[util.getByte(origState[0],0)], 0);
  342.  
  343. dstState[2] = util.putByte(private.SBox[util.getByte(origState[2],3)], 3)
  344. + util.putByte(private.SBox[util.getByte(origState[3],2)], 2)
  345. + util.putByte(private.SBox[util.getByte(origState[0],1)], 1)
  346. + util.putByte(private.SBox[util.getByte(origState[1],0)], 0);
  347.  
  348. dstState[3] = util.putByte(private.SBox[util.getByte(origState[3],3)], 3)
  349. + util.putByte(private.SBox[util.getByte(origState[0],2)], 2)
  350. + util.putByte(private.SBox[util.getByte(origState[1],1)], 1)
  351. + util.putByte(private.SBox[util.getByte(origState[2],0)], 0);
  352. end
  353.  
  354. --
  355. -- do decryption round
  356. --
  357. function private.doInvRound(origState, dstState)
  358. dstState[0] = bit.bxor(bit.bxor(bit.bxor(
  359. private.tableInv0[util.getByte(origState[0],3)],
  360. private.tableInv1[util.getByte(origState[3],2)]),
  361. private.tableInv2[util.getByte(origState[2],1)]),
  362. private.tableInv3[util.getByte(origState[1],0)]);
  363.  
  364. dstState[1] = bit.bxor(bit.bxor(bit.bxor(
  365. private.tableInv0[util.getByte(origState[1],3)],
  366. private.tableInv1[util.getByte(origState[0],2)]),
  367. private.tableInv2[util.getByte(origState[3],1)]),
  368. private.tableInv3[util.getByte(origState[2],0)]);
  369.  
  370. dstState[2] = bit.bxor(bit.bxor(bit.bxor(
  371. private.tableInv0[util.getByte(origState[2],3)],
  372. private.tableInv1[util.getByte(origState[1],2)]),
  373. private.tableInv2[util.getByte(origState[0],1)]),
  374. private.tableInv3[util.getByte(origState[3],0)]);
  375.  
  376. dstState[3] = bit.bxor(bit.bxor(bit.bxor(
  377. private.tableInv0[util.getByte(origState[3],3)],
  378. private.tableInv1[util.getByte(origState[2],2)]),
  379. private.tableInv2[util.getByte(origState[1],1)]),
  380. private.tableInv3[util.getByte(origState[0],0)]);
  381. end
  382.  
  383. --
  384. -- do last decryption round
  385. --
  386. function private.doInvLastRound(origState, dstState)
  387. dstState[0] = util.putByte(private.iSBox[util.getByte(origState[0],3)], 3)
  388. + util.putByte(private.iSBox[util.getByte(origState[3],2)], 2)
  389. + util.putByte(private.iSBox[util.getByte(origState[2],1)], 1)
  390. + util.putByte(private.iSBox[util.getByte(origState[1],0)], 0);
  391.  
  392. dstState[1] = util.putByte(private.iSBox[util.getByte(origState[1],3)], 3)
  393. + util.putByte(private.iSBox[util.getByte(origState[0],2)], 2)
  394. + util.putByte(private.iSBox[util.getByte(origState[3],1)], 1)
  395. + util.putByte(private.iSBox[util.getByte(origState[2],0)], 0);
  396.  
  397. dstState[2] = util.putByte(private.iSBox[util.getByte(origState[2],3)], 3)
  398. + util.putByte(private.iSBox[util.getByte(origState[1],2)], 2)
  399. + util.putByte(private.iSBox[util.getByte(origState[0],1)], 1)
  400. + util.putByte(private.iSBox[util.getByte(origState[3],0)], 0);
  401.  
  402. dstState[3] = util.putByte(private.iSBox[util.getByte(origState[3],3)], 3)
  403. + util.putByte(private.iSBox[util.getByte(origState[2],2)], 2)
  404. + util.putByte(private.iSBox[util.getByte(origState[1],1)], 1)
  405. + util.putByte(private.iSBox[util.getByte(origState[0],0)], 0);
  406. end
  407.  
  408. --
  409. -- encrypts 16 Bytes
  410. -- key encryption key schedule
  411. -- input array with input data
  412. -- inputOffset start index for input
  413. -- output array for encrypted data
  414. -- outputOffset start index for output
  415. --
  416. function public.encrypt(key, input, inputOffset, output, outputOffset)
  417. --default parameters
  418. inputOffset = inputOffset or 1;
  419. output = output or {};
  420. outputOffset = outputOffset or 1;
  421.  
  422. local state = {};
  423. local tmpState = {};
  424.  
  425. if (key[public.KEY_TYPE] ~= public.ENCRYPTION_KEY) then
  426. print("No encryption key: ", key[public.KEY_TYPE]);
  427. return;
  428. end
  429.  
  430. state = util.bytesToInts(input, inputOffset, 4);
  431. private.addRoundKey(state, key, 0);
  432.  
  433. local round = 1;
  434. while (round < key[public.ROUNDS] - 1) do
  435. -- do a double round to save temporary assignments
  436. private.doRound(state, tmpState);
  437. private.addRoundKey(tmpState, key, round);
  438. round = round + 1;
  439.  
  440. private.doRound(tmpState, state);
  441. private.addRoundKey(state, key, round);
  442. round = round + 1;
  443. end
  444.  
  445. private.doRound(state, tmpState);
  446. private.addRoundKey(tmpState, key, round);
  447. round = round +1;
  448.  
  449. private.doLastRound(tmpState, state);
  450. private.addRoundKey(state, key, round);
  451.  
  452. return util.intsToBytes(state, output, outputOffset);
  453. end
  454.  
  455. --
  456. -- decrypt 16 bytes
  457. -- key decryption key schedule
  458. -- input array with input data
  459. -- inputOffset start index for input
  460. -- output array for decrypted data
  461. -- outputOffset start index for output
  462. ---
  463. function public.decrypt(key, input, inputOffset, output, outputOffset)
  464. -- default arguments
  465. inputOffset = inputOffset or 1;
  466. output = output or {};
  467. outputOffset = outputOffset or 1;
  468.  
  469. local state = {};
  470. local tmpState = {};
  471.  
  472. if (key[public.KEY_TYPE] ~= public.DECRYPTION_KEY) then
  473. print("No decryption key: ", key[public.KEY_TYPE]);
  474. return;
  475. end
  476.  
  477. state = util.bytesToInts(input, inputOffset, 4);
  478. private.addRoundKey(state, key, key[public.ROUNDS]);
  479.  
  480. local round = key[public.ROUNDS] - 1;
  481. while (round > 2) do
  482. -- do a double round to save temporary assignments
  483. private.doInvRound(state, tmpState);
  484. private.addRoundKey(tmpState, key, round);
  485. round = round - 1;
  486.  
  487. private.doInvRound(tmpState, state);
  488. private.addRoundKey(state, key, round);
  489. round = round - 1;
  490. end
  491.  
  492. private.doInvRound(state, tmpState);
  493. private.addRoundKey(tmpState, key, round);
  494. round = round - 1;
  495.  
  496. private.doInvLastRound(tmpState, state);
  497. private.addRoundKey(state, key, round);
  498.  
  499. return util.intsToBytes(state, output, outputOffset);
  500. end
  501.  
  502. -- calculate all tables when loading this file
  503. private.calcSBox();
  504. private.calcRoundTables();
  505. private.calcInvRoundTables();
  506.  
  507. return public;
Advertisement
Add Comment
Please, Sign In to add comment