Advertisement
Alakazard12

AES

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