gknova61

AES API

Nov 29th, 2012
136
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 12.92 KB | None | 0 0
  1. -- cccAES is an implementation of the Advanced Encryption Standard for ComputerCraft lua.
  2.  
  3. -- Copyright (c) 2012 KleinRefrigerator
  4. -- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
  5. -- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
  6. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  7.  
  8. -- pyAES by Brandon Stearne was immensely helpful in writing this.
  9. --      See: http://brandon.sternefamily.net/files/mit-license.txt
  10. -- Laws of Cryptography by Neal R. Wagner was also helpful in understanding the underlying algorithm
  11. --      See: http://www.cs.utsa.edu/~wagner/laws/
  12.  
  13. -- "Law AES-1: Conventional block ciphers are always ugly, complicated, inelegant brutes, and the AES is no exception."
  14. --          -Neal R. Wagner
  15.  
  16.  
  17.  
  18.  
  19. -- the sbox and inverse sbox are used throughout AES to transform bytes
  20. -- the sbox transform works as follows: for each byte in a string, append
  21. -- sbox[byte+1] to a new string and then return it, e.g. "\0\1" transformed
  22. -- will be "\99\124", since those are the first two bytes of sbox
  23. -- the inverse transform works the same but with sboxInv
  24. -- note that sboxInv[sbox[byte+1]+1] == byte
  25. -- this transform can be done algorithmically, but it's faster to define it as a constant
  26. local sbox = "\099\124\119\123\242\107\111\197\048\001\103\043\254\215\171\118\202\130\201\125\250\089\071\240\173\212\162\175\156\164\114\192\183\253\147\038\054\063\247\204\052\165\229\241\113\216\049\021\004\199\035\195\024\150\005\154\007\018\128\226\235\039\178\117\009\131\044\026\027\110\090\160\082\059\214\179\041\227\047\132\083\209\000\237\032\252\177\091\106\203\190\057\074\076\088\207\208\239\170\251\067\077\051\133\069\249\002\127\080\060\159\168\081\163\064\143\146\157\056\245\188\182\218\033\016\255\243\210\205\012\019\236\095\151\068\023\196\167\126\061\100\093\025\115\096\129\079\220\034\042\144\136\070\238\184\020\222\094\011\219\224\050\058\010\073\006\036\092\194\211\172\098\145\149\228\121\231\200\055\109\141\213\078\169\108\086\244\234\101\122\174\008\186\120\037\046\028\166\180\198\232\221\116\031\075\189\139\138\112\062\181\102\072\003\246\014\097\053\087\185\134\193\029\158\225\248\152\017\105\217\142\148\155\030\135\233\206\085\040\223\140\161\137\013\191\230\066\104\065\153\045\015\176\084\187\022"
  27. local sboxInv = "\082\009\106\213\048\054\165\056\191\064\163\158\129\243\215\251\124\227\057\130\155\047\255\135\052\142\067\068\196\222\233\203\084\123\148\050\166\194\035\061\238\076\149\011\066\250\195\078\008\046\161\102\040\217\036\178\118\091\162\073\109\139\209\037\114\248\246\100\134\104\152\022\212\164\092\204\093\101\182\146\108\112\072\080\253\237\185\218\094\021\070\087\167\141\157\132\144\216\171\000\140\188\211\010\247\228\088\005\184\179\069\006\208\044\030\143\202\063\015\002\193\175\189\003\001\019\138\107\058\145\017\065\079\103\220\234\151\242\207\206\240\180\230\115\150\172\116\034\231\173\053\133\226\249\055\232\028\117\223\110\071\241\026\113\029\041\197\137\111\183\098\014\170\024\190\027\252\086\062\075\198\210\121\032\154\219\192\254\120\205\090\244\031\221\168\051\136\007\199\049\177\018\016\089\039\128\236\095\096\081\127\169\025\181\074\013\045\229\122\159\147\201\156\239\160\224\059\077\174\042\245\176\200\235\187\060\131\083\153\097\023\043\004\126\186\119\214\038\225\105\020\099\085\033\012\125"
  28.  
  29. -- these values are used to expand keys
  30. local rcon = "\141\001\002\004\008\016\032\064\128\027\054\108\216\171\077\154\047\094\188\099\198\151\053\106\212\179\125\250\239\197\145\057\114\228\211\189\097\194\159\037\074\148\051\102\204\131\029\058\116\232\203\141\001\002\004\008\016\032\064\128\027\054\108\216\171\077\154\047\094\188\099\198\151\053\106\212\179\125\250\239\197\145\057\114\228\211\189\097\194\159\037\074\148\051\102\204\131\029\058\116\232\203\141\001\002\004\008\016\032\064\128\027\054\108\216\171\077\154\047\094\188\099\198\151\053\106\212\179\125\250\239\197\145\057\114\228\211\189\097\194\159\037\074\148\051\102\204\131\029\058\116\232\203\141\001\002\004\008\016\032\064\128\027\054\108\216\171\077\154\047\094\188\099\198\151\053\106\212\179\125\250\239\197\145\057\114\228\211\189\097\194\159\037\074\148\051\102\204\131\029\058\116\232\203\141\001\002\004\008\016\032\064\128\027\054\108\216\171\077\154\047\094\188\099\198\151\053\106\212\179\125\250\239\197\145\057\114\228\211\189\097\194\159\037\074\148\051\102\204\131\029\058\116\232\203"
  31.  
  32.  
  33. -- argument names denote what a function can or should work with
  34. -- str: arbitrary length bytestrings
  35. --      often, however, a function that takes a "str" argument typically takes
  36. --      a specific type--I have denoted this with comments on such functions
  37. -- word: 4 byte strings
  38. --      the AES standard is defined in terms of words
  39. --      however, my implementation focuses on bytes instead
  40. -- state: 16 byte strings
  41. --      a state represents the current status of the algorithm
  42. --      the main operations of AES work on states
  43. -- key: 16, 24, or 32 byte strings
  44. --      AES supports three key lengths, all implemented here:
  45. --      128 bit (16 byte), 192 bit (24 byte), and 256 bit (32 byte)
  46.  
  47.  
  48. -- returns a copy of a string shifted to the left for positive values of n
  49. -- and to the right for negative values, wrapping values around to the other side
  50. -- e.g. rotate("foo", 1) == "ofo" and rotate("foo",-1) == "oof"
  51. -- the result is undefined if math.abs(n) > str:len(), but it should just return str
  52.  
  53. local function rotate(str, n) -- str is usually word
  54.     local a
  55.     -- correction for 1-based string indexing (damn you, lua)
  56.     if (n > 0) then
  57.         a = n + 1
  58.     elseif (n < 0) then
  59.         a = n
  60.     else
  61.         return str
  62.     end
  63.     return str:sub(a)..str:sub(1,a-1)
  64. end
  65.  
  66.  
  67. -- divides a 16 byte state into 4 virtual rows of 4 bytes each
  68. -- then rotates the nth row n-1 and returns the result
  69. -- this is one of the four AES round operations
  70.  
  71. local function shiftRows(state)
  72.     local newS = ""
  73.     for i = 0, 3 do
  74.         newS = newS..rotate(state:sub(i*4+1,(i+1)*4),i)
  75.     end
  76.     return newS
  77. end
  78.  
  79.  
  80. -- the inverse transform of shiftRows: shifts by -(n-1) instead
  81. -- shiftRowsInv(shiftRows(state)) == state
  82.  
  83. local function shiftRowsInv(state)
  84.     local newS = ""
  85.     for i = 0, 3 do
  86.         newS = newS..rotate(state:sub(i*4+1,(i+1)*4),-i)
  87.     end
  88.     return newS
  89. end
  90.  
  91.  
  92. -- sbox transform: described above
  93. -- this is one of the four AES round operations
  94.  
  95. local function subBytes(str) -- str is usually state
  96.     local newW = ""
  97.     for i = 1, #str do
  98.         newW = newW .. sbox:sub(str:byte(i)+1,str:byte(i)+1)
  99.     end
  100.     return newW
  101. end
  102.  
  103.  
  104. -- inverse sbox
  105.  
  106. local function subBytesInv(str) -- str is usually state
  107.     local newW = ""
  108.     for i = 1, #str do
  109.         newW = newW .. sboxInv:sub(str:byte(i)+1,str:byte(i)+1)
  110.     end
  111.     return newW
  112. end
  113.  
  114.  
  115. -- this takes two strings of equal length and returns a string that is
  116. -- the bytewise xor of them
  117. -- if strings are not of equal length, returns nil
  118. -- this is one of the four AES round operations
  119.  
  120. local function strXor(str1, str2)
  121.     if (#str1 ~= #str2) then return nil end
  122.     res = ""
  123.     for i = 1, #str1 do
  124.         res = res .. string.char(bit.bxor(str1:byte(i), str2:byte(i)))
  125.     end
  126.     return res
  127. end
  128.  
  129.  
  130. -- Galois Multiplication
  131. -- takes two bytes, does some shit, gives you another byte
  132.  
  133. local function galoisMult(a, b)
  134.     local p = 0
  135.     local hiBit = 0
  136.     for i = 1,8 do
  137.         if (bit.band(b,1) == 1) then
  138.             p = bit.bxor(p, a)
  139.         end
  140.         hiBit = bit.band(a, 0x80)
  141.         a = bit.blshift(a, 1)
  142.         if hiBit == 0x80 then
  143.             a = bit.bxor(a, 0x1b)
  144.         end
  145.         b = bit.brshift(b, 1)
  146.     end
  147.     return p % 256
  148. end
  149.  
  150.  
  151. -- does a bunch of galois multiplication and xor'ing to a column
  152.  
  153. local function mixColumn(word)
  154.     local temp = ""
  155.     for i = 1,4 do temp = temp .. word:sub(5-i,5-i) end
  156.     local newW = ""
  157.     for i = 1,4 do
  158.         temp = rotate(temp,-1)
  159.         newW = newW .. string.char(bit.bxor(bit.bxor(bit.bxor(galoisMult(temp:byte(1),2), galoisMult(temp:byte(2),1)), galoisMult(temp:byte(3),1)), galoisMult(temp:byte(4),3)))
  160.     end
  161.     return newW
  162. end
  163.  
  164.  
  165. -- inverse transform of mixColumn
  166.  
  167. local function mixColumnInv(word)
  168.     local temp = ""
  169.     for i = 1,4 do temp = temp .. word:sub(5-i,5-i) end
  170.     local newW = ""
  171.     for i = 1,4 do
  172.         temp = rotate(temp,-1)
  173.         newW = newW .. string.char(bit.bxor(bit.bxor(bit.bxor(galoisMult(temp:byte(1),14), galoisMult(temp:byte(2),9)), galoisMult(temp:byte(3),13)), galoisMult(temp:byte(4),11)))
  174.     end
  175.     return newW
  176. end
  177.  
  178.  
  179. -- wrapper for mixColumn: applies it to each of the four virtual columns
  180. -- this is one of the four AES round operations
  181.  
  182. local function mixColumns(state)
  183.     local cols = {}
  184.     for i=1,4 do
  185.         local temp = ""
  186.         for j=0,3 do
  187.             temp = temp .. state:sub(i+j*4,i+j*4)
  188.         end
  189.         cols[i] = mixColumn(temp)
  190.     end
  191.     state = ""
  192.     for i=1,4 do for j=1,4 do
  193.         state = state .. cols[j]:sub(i,i)
  194.     end end
  195.     return state
  196. end
  197.  
  198.  
  199. -- inverse of mixColumns
  200.  
  201. local function mixColumnsInv(state)
  202.     local cols = {}
  203.     for i=1,4 do
  204.         local temp = ""
  205.         for j=0,3 do
  206.             temp = temp .. state:sub(i+j*4,i+j*4)
  207.         end
  208.         cols[i] = mixColumnInv(temp)
  209.     end
  210.     state = ""
  211.     for i=1,4 do for j=1,4 do
  212.         state = state .. cols[j]:sub(i,i)
  213.     end end
  214.     return state
  215. end
  216.  
  217.  
  218. -- this is a sub-operation of expandKey
  219.  
  220. local function keyScheduleCore(word, i)
  221.     word = rotate(word, 1)
  222.     local newW = ""
  223.     for j = 1, #word do
  224.         local c = sbox:byte(word:byte(j)+1)
  225.         if (j == 1) then
  226.             c = bit.bxor(c,rcon:byte(i+1))
  227.         end
  228.         newW = newW .. string.char(c)
  229.     end
  230.     return newW
  231. end
  232.  
  233.  
  234. -- expands the key to give sufficient round keys for the 10, 12, or 14 rounds
  235. -- 16 byte keys -> 176 bytes, 24 -> 208, 32 -> 240
  236.  
  237. function expandKey(key)
  238.     local nWord = #key / 4
  239.     if (nWord ~= 4 and nWord ~= 6 and nWord ~= 8) then
  240.         return nil
  241.     end
  242.     local nRound = nWord + 6
  243.     local eKey = key
  244.     local i = nWord
  245.     while (i < 4*(nRound+1)) do
  246.         local temp = eKey:sub((i-1)*4+1,i*4)
  247.         if (i % nWord == 0) then
  248.             temp = keyScheduleCore(temp, i/nWord)
  249.         elseif (nWord == 8 and (i%8) == 4) then
  250.             temp = subBytes(temp)
  251.         end
  252.         local temp2 = eKey:sub((i-nWord)*4+1,(i-nWord+1)*4)
  253.         for i = 1, 4 do
  254.             eKey = eKey .. string.char(bit.bxor(temp:byte(i),temp2:byte(i)))
  255.         end
  256.         i = i + 1
  257.     end
  258.     return eKey
  259. end
  260.  
  261.  
  262. -- this runs one round of AES given a state and a round key
  263.  
  264. function AESRound(state, roundKey)
  265.     state = subBytes(state)
  266.     state = shiftRows(state)   
  267.     state = mixColumns(state)  
  268.     -- add the round key
  269.     state = strXor(state, roundKey)
  270.     return state
  271. end
  272.  
  273.  
  274. -- this runs one round of AES backwards given a state and a round key
  275. -- note that strXor has no inverse since xor is symmetric -- x ^ y ^ y = x
  276.  
  277. function AESRoundInv(state, roundKey)
  278.     -- add the round key
  279.     state = strXor(state, roundKey)
  280.     state = mixColumnsInv(state)   
  281.     state = shiftRowsInv(state)
  282.     state = subBytesInv(state)
  283.     return state
  284. end
  285.  
  286.  
  287. -- retrieves the (round+1)th group of 16 bytes from an expanded key
  288.  
  289. function getRoundKey(eKey, round)
  290.     return eKey:sub(16*round+1,16*(round+1))
  291. end
  292.  
  293.  
  294. -- this function represents a single block cipher operation
  295. -- given a state and an expanded key, it runs the full 10-14 rounds
  296. -- on a single block of data
  297. -- these block cipher operations can be used together in different modes
  298.  
  299. function AESMain(state, eKey)
  300.     local nRound = #eKey/16-1
  301.     if (nRound ~= 10 and nRound ~= 12 and nRound ~= 14) then return nil end
  302.    
  303.     -- zeroth round has only a round key
  304.     local roundKey = getRoundKey(eKey, 0)
  305.     state = strXor(state, roundKey)
  306.    
  307.     for i=1,nRound-1 do
  308.         roundKey = getRoundKey(eKey, i)
  309.         state = AESRound(state, roundKey)
  310.     end
  311.     -- no mixColumns in final round
  312.     roundKey = getRoundKey(eKey,nRound)
  313.     state = subBytes(state)
  314.     state = shiftRows(state)
  315.     state = strXor(state, roundKey)
  316.    
  317.     return state
  318. end
  319.  
  320.  
  321. -- single decryption operation, inverse of AESMain
  322.  
  323. function AESMainInv(state, eKey)
  324.     local nRound = #eKey/16-1
  325.     if (nRound ~= 10 and nRound ~= 12 and nRound ~= 14) then return nil end
  326.    
  327.     -- going in reverse, so do the last round first with no mixColumns
  328.     roundKey = getRoundKey(eKey, nRound)
  329.     state = strXor(state, roundKey)
  330.     state = shiftRowsInv(state)
  331.     state = subBytesInv(state)
  332.    
  333.     for i=nRound-1,1,-1 do
  334.         roundKey = getRoundKey(eKey, i)
  335.         state = AESRoundInv(state, roundKey)
  336.     end
  337.    
  338.     -- zeroth round with only a round key
  339.     roundKey = getRoundKey(eKey, 0)
  340.     state = strXor(state, roundKey)
  341.    
  342.     return state
  343. end
Advertisement
Add Comment
Please, Sign In to add comment