aeslua

Run Settings
LanguageLua
Language Version
Run Command
local gf = (function() local bit = bit32 -- finite field with base 2 and modulo irreducible polynom x^8+x^4+x^3+x+1 = 0x11d local private = {}; local public = {}; -- private data of gf private.n = 0x100; private.ord = 0xff; private.irrPolynom = 0x11b; private.exp = {}; private.log = {}; -- -- add two polynoms (its simply xor) -- function public.add(operand1, operand2) return bit.bxor(operand1,operand2); end -- -- subtract two polynoms (same as addition) -- function public.sub(operand1, operand2) return bit.bxor(operand1,operand2); end -- -- inverts element -- a^(-1) = g^(order - log(a)) -- function public.invert(operand) -- special case for 1 if (operand == 1) then return 1; end; -- normal invert local exponent = private.ord - private.log[operand]; return private.exp[exponent]; end -- -- multiply two elements using a logarithm table -- a*b = g^(log(a)+log(b)) -- function public.mul(operand1, operand2) if (operand1 == 0 or operand2 == 0) then return 0; end local exponent = private.log[operand1] + private.log[operand2]; if (exponent >= private.ord) then exponent = exponent - private.ord; end return private.exp[exponent]; end -- -- divide two elements -- a/b = g^(log(a)-log(b)) -- function public.div(operand1, operand2) if (operand1 == 0) then return 0; end -- TODO: exception if operand2 == 0 local exponent = private.log[operand1] - private.log[operand2]; if (exponent < 0) then exponent = exponent + private.ord; end return private.exp[exponent]; end -- -- print logarithmic table -- function public.printLog() for i = 1, private.n do print("log(", i-1, ")=", private.log[i-1]); end end -- -- print exponentiation table -- function public.printExp() for i = 1, private.n do print("exp(", i-1, ")=", private.exp[i-1]); end end -- -- calculate logarithmic and exponentiation table -- function private.initMulTable() local a = 1; for i = 0,private.ord-1 do private.exp[i] = a; private.log[a] = i; -- multiply with generator x+1 -> left shift + 1 a = bit.bxor(bit.lshift(a, 1), a); -- if a gets larger than order, reduce modulo irreducible polynom if a > private.ord then a = public.sub(a, private.irrPolynom); end end end private.initMulTable(); return public; end)() local util = (function() local bit = bit32 local public = {}; local private = {}; -- -- calculate the parity of one byte -- function public.byteParity(byte) byte = bit.bxor(byte, bit.rshift(byte, 4)); byte = bit.bxor(byte, bit.rshift(byte, 2)); byte = bit.bxor(byte, bit.rshift(byte, 1)); return bit.band(byte, 1); end -- -- get byte at position index -- function public.getByte(number, index) if (index == 0) then return bit.band(number,0xff); else return bit.band(bit.rshift(number, index*8),0xff); end end -- -- put number into int at position index -- function public.putByte(number, index) if (index == 0) then return bit.band(number,0xff); else return bit.lshift(bit.band(number,0xff),index*8); end end -- -- convert byte array to int array -- function public.bytesToInts(bytes, start, n) local ints = {}; for i = 0, n - 1 do ints[i] = public.putByte(bytes[start + (i*4) ], 3) + public.putByte(bytes[start + (i*4) + 1], 2) + public.putByte(bytes[start + (i*4) + 2], 1) + public.putByte(bytes[start + (i*4) + 3], 0); end return ints; end -- -- convert int array to byte array -- function public.intsToBytes(ints, output, outputOffset, n) n = n or #ints; for i = 0, n do for j = 0,3 do output[outputOffset + i*4 + (3 - j)] = public.getByte(ints[i], j); end end return output; end -- -- convert bytes to hexString -- function private.bytesToHex(bytes) local hexBytes = ""; for i,byte in ipairs(bytes) do hexBytes = hexBytes .. string.format("%02x ", byte); end return hexBytes; end -- -- convert data to hex string -- function public.toHexString(data) local type = type(data); if (type == "number") then return string.format("%08x",data); elseif (type == "table") then return private.bytesToHex(data); elseif (type == "string") then local bytes = {string.byte(data, 1, #data)}; return private.bytesToHex(bytes); else return data; end end function public.padByteString(data) local dataLength = #data; local random1 = math.random(0,255); local random2 = math.random(0,255); local prefix = string.char(random1, random2, random1, random2, public.getByte(dataLength, 3), public.getByte(dataLength, 2), public.getByte(dataLength, 1), public.getByte(dataLength, 0)); data = prefix .. data; local paddingLength = math.ceil(#data/16)*16 - #data; local padding = ""; for i=1,paddingLength do padding = padding .. string.char(math.random(0,255)); end return data .. padding; end function private.properlyDecrypted(data) local random = {string.byte(data,1,4)}; if (random[1] == random[3] and random[2] == random[4]) then return true; end return false; end function public.unpadByteString(data) if (not private.properlyDecrypted(data)) then return nil; end local dataLength = public.putByte(string.byte(data,5), 3) + public.putByte(string.byte(data,6), 2) + public.putByte(string.byte(data,7), 1) + public.putByte(string.byte(data,8), 0); return string.sub(data,9,8+dataLength); end function public.xorIV(data, iv) for i = 1,16 do data[i] = bit.bxor(data[i], iv[i]); end end return public; end)() local buffer = (function() local public = {}; function public.new () return {}; end function public.addString (stack, s) table.insert(stack, s) for i = #stack - 1, 1, -1 do if #stack[i] > #stack[i+1] then break; end stack[i] = stack[i] .. table.remove(stack); end end function public.toString (stack) for i = #stack - 1, 1, -1 do stack[i] = stack[i] .. table.remove(stack); end return stack[1]; end return public; end) local aes = (function() local bit = bit32 -- -- Implementation of AES with nearly pure lua (only bitlib is needed) -- -- AES with lua is slow, really slow :-) -- local public = {}; local private = {}; -- some constants public.ROUNDS = "rounds"; public.KEY_TYPE = "type"; public.ENCRYPTION_KEY=1; public.DECRYPTION_KEY=2; -- aes SBOX private.SBox = {}; private.iSBox = {}; -- aes tables private.table0 = {}; private.table1 = {}; private.table2 = {}; private.table3 = {}; private.tableInv0 = {}; private.tableInv1 = {}; private.tableInv2 = {}; private.tableInv3 = {}; -- round constants private.rCon = {0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1b000000, 0x36000000, 0x6c000000, 0xd8000000, 0xab000000, 0x4d000000, 0x9a000000, 0x2f000000}; -- -- affine transformation for calculating the S-Box of AES -- function private.affinMap(byte) mask = 0xf8; result = 0; for i = 1,8 do result = bit.lshift(result,1); parity = util.byteParity(bit.band(byte,mask)); result = result + parity -- simulate roll lastbit = bit.band(mask, 1); mask = bit.band(bit.rshift(mask, 1),0xff); if (lastbit ~= 0) then mask = bit.bor(mask, 0x80); else mask = bit.band(mask, 0x7f); end end return bit.bxor(result, 0x63); end -- -- calculate S-Box and inverse S-Box of AES -- apply affine transformation to inverse in finite field 2^8 -- function private.calcSBox() for i = 0, 255 do if (i ~= 0) then inverse = gf.invert(i); else inverse = i; end mapped = private.affinMap(inverse); private.SBox[i] = mapped; private.iSBox[mapped] = i; end end -- -- Calculate round tables -- round tables are used to calculate shiftRow, MixColumn and SubBytes -- with 4 table lookups and 4 xor operations. -- function private.calcRoundTables() for x = 0,255 do byte = private.SBox[x]; private.table0[x] = util.putByte(gf.mul(0x03, byte), 0) + util.putByte( byte , 1) + util.putByte( byte , 2) + util.putByte(gf.mul(0x02, byte), 3); private.table1[x] = util.putByte( byte , 0) + util.putByte( byte , 1) + util.putByte(gf.mul(0x02, byte), 2) + util.putByte(gf.mul(0x03, byte), 3); private.table2[x] = util.putByte( byte , 0) + util.putByte(gf.mul(0x02, byte), 1) + util.putByte(gf.mul(0x03, byte), 2) + util.putByte( byte , 3); private.table3[x] = util.putByte(gf.mul(0x02, byte), 0) + util.putByte(gf.mul(0x03, byte), 1) + util.putByte( byte , 2) + util.putByte( byte , 3); end end -- -- Calculate inverse round tables -- does the inverse of the normal roundtables for the equivalent -- decryption algorithm. -- function private.calcInvRoundTables() for x = 0,255 do byte = private.iSBox[x]; private.tableInv0[x] = util.putByte(gf.mul(0x0b, byte), 0) + util.putByte(gf.mul(0x0d, byte), 1) + util.putByte(gf.mul(0x09, byte), 2) + util.putByte(gf.mul(0x0e, byte), 3); private.tableInv1[x] = util.putByte(gf.mul(0x0d, byte), 0) + util.putByte(gf.mul(0x09, byte), 1) + util.putByte(gf.mul(0x0e, byte), 2) + util.putByte(gf.mul(0x0b, byte), 3); private.tableInv2[x] = util.putByte(gf.mul(0x09, byte), 0) + util.putByte(gf.mul(0x0e, byte), 1) + util.putByte(gf.mul(0x0b, byte), 2) + util.putByte(gf.mul(0x0d, byte), 3); private.tableInv3[x] = util.putByte(gf.mul(0x0e, byte), 0) + util.putByte(gf.mul(0x0b, byte), 1) + util.putByte(gf.mul(0x0d, byte), 2) + util.putByte(gf.mul(0x09, byte), 3); end end -- -- rotate word: 0xaabbccdd gets 0xbbccddaa -- used for key schedule -- function private.rotWord(word) local tmp = bit.band(word,0xff000000); return (bit.lshift(word,8) + bit.rshift(tmp,24)) ; end -- -- replace all bytes in a word with the SBox. -- used for key schedule -- function private.subWord(word) return util.putByte(private.SBox[util.getByte(word,0)],0) + util.putByte(private.SBox[util.getByte(word,1)],1) + util.putByte(private.SBox[util.getByte(word,2)],2) + util.putByte(private.SBox[util.getByte(word,3)],3); end -- -- generate key schedule for aes encryption -- -- returns table with all round keys and -- the necessary number of rounds saved in [public.ROUNDS] -- function public.expandEncryptionKey(key) local keySchedule = {}; local keyWords = math.floor(#key / 4); if ((keyWords ~= 4 and keyWords ~= 6 and keyWords ~= 8) or (keyWords * 4 ~= #key)) then print("Invalid key size: ", keyWords); return nil; end keySchedule[public.ROUNDS] = keyWords + 6; keySchedule[public.KEY_TYPE] = public.ENCRYPTION_KEY; for i = 0,keyWords - 1 do keySchedule[i] = util.putByte(key[i*4+1], 3) + util.putByte(key[i*4+2], 2) + util.putByte(key[i*4+3], 1) + util.putByte(key[i*4+4], 0); end for i = keyWords, (keySchedule[public.ROUNDS] + 1)*4 - 1 do local tmp = keySchedule[i-1]; if ( i % keyWords == 0) then tmp = private.rotWord(tmp); tmp = private.subWord(tmp); local index = math.floor(i/keyWords); tmp = bit.bxor(tmp,private.rCon[index]); elseif (keyWords > 6 and i % keyWords == 4) then tmp = private.subWord(tmp); end keySchedule[i] = bit.bxor(keySchedule[(i-keyWords)],tmp); end return keySchedule; end -- -- Inverse mix column -- used for key schedule of decryption key -- function private.invMixColumnOld(word) local b0 = util.getByte(word,3); local b1 = util.getByte(word,2); local b2 = util.getByte(word,1); local b3 = util.getByte(word,0); return util.putByte(gf.add(gf.add(gf.add(gf.mul(0x0b, b1), gf.mul(0x0d, b2)), gf.mul(0x09, b3)), gf.mul(0x0e, b0)),3) + util.putByte(gf.add(gf.add(gf.add(gf.mul(0x0b, b2), gf.mul(0x0d, b3)), gf.mul(0x09, b0)), gf.mul(0x0e, b1)),2) + util.putByte(gf.add(gf.add(gf.add(gf.mul(0x0b, b3), gf.mul(0x0d, b0)), gf.mul(0x09, b1)), gf.mul(0x0e, b2)),1) + util.putByte(gf.add(gf.add(gf.add(gf.mul(0x0b, b0), gf.mul(0x0d, b1)), gf.mul(0x09, b2)), gf.mul(0x0e, b3)),0); end -- -- Optimized inverse mix column -- look at http://fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.311.pdf -- TODO: make it work -- function private.invMixColumn(word) local b0 = util.getByte(word,3); local b1 = util.getByte(word,2); local b2 = util.getByte(word,1); local b3 = util.getByte(word,0); local t = bit.bxor(b3,b2); local u = bit.bxor(b1,b0); local v = bit.bxor(t,u); v = bit.bxor(v,gf.mul(0x08,v)); w = bit.bxor(v,gf.mul(0x04, bit.bxor(b2,b0))); v = bit.bxor(v,gf.mul(0x04, bit.bxor(b3,b1))); return util.putByte( bit.bxor(bit.bxor(b3,v), gf.mul(0x02, bit.bxor(b0,b3))), 0) + util.putByte( bit.bxor(bit.bxor(b2,w), gf.mul(0x02, t )), 1) + util.putByte( bit.bxor(bit.bxor(b1,v), gf.mul(0x02, bit.bxor(b0,b3))), 2) + util.putByte( bit.bxor(bit.bxor(b0,w), gf.mul(0x02, u )), 3); end -- -- generate key schedule for aes decryption -- -- uses key schedule for aes encryption and transforms each -- key by inverse mix column. -- function public.expandDecryptionKey(key) local keySchedule = public.expandEncryptionKey(key); if (keySchedule == nil) then return nil; end keySchedule[public.KEY_TYPE] = public.DECRYPTION_KEY; for i = 4, (keySchedule[public.ROUNDS] + 1)*4 - 5 do keySchedule[i] = private.invMixColumnOld(keySchedule[i]); end return keySchedule; end -- -- xor round key to state -- function private.addRoundKey(state, key, round) for i = 0, 3 do state[i] = bit.bxor(state[i], key[round*4+i]); end end -- -- do encryption round (ShiftRow, SubBytes, MixColumn together) -- function private.doRound(origState, dstState) dstState[0] = bit.bxor(bit.bxor(bit.bxor( private.table0[util.getByte(origState[0],3)], private.table1[util.getByte(origState[1],2)]), private.table2[util.getByte(origState[2],1)]), private.table3[util.getByte(origState[3],0)]); dstState[1] = bit.bxor(bit.bxor(bit.bxor( private.table0[util.getByte(origState[1],3)], private.table1[util.getByte(origState[2],2)]), private.table2[util.getByte(origState[3],1)]), private.table3[util.getByte(origState[0],0)]); dstState[2] = bit.bxor(bit.bxor(bit.bxor( private.table0[util.getByte(origState[2],3)], private.table1[util.getByte(origState[3],2)]), private.table2[util.getByte(origState[0],1)]), private.table3[util.getByte(origState[1],0)]); dstState[3] = bit.bxor(bit.bxor(bit.bxor( private.table0[util.getByte(origState[3],3)], private.table1[util.getByte(origState[0],2)]), private.table2[util.getByte(origState[1],1)]), private.table3[util.getByte(origState[2],0)]); end -- -- do last encryption round (ShiftRow and SubBytes) -- function private.doLastRound(origState, dstState) dstState[0] = util.putByte(private.SBox[util.getByte(origState[0],3)], 3) + util.putByte(private.SBox[util.getByte(origState[1],2)], 2) + util.putByte(private.SBox[util.getByte(origState[2],1)], 1) + util.putByte(private.SBox[util.getByte(origState[3],0)], 0); dstState[1] = util.putByte(private.SBox[util.getByte(origState[1],3)], 3) + util.putByte(private.SBox[util.getByte(origState[2],2)], 2) + util.putByte(private.SBox[util.getByte(origState[3],1)], 1) + util.putByte(private.SBox[util.getByte(origState[0],0)], 0); dstState[2] = util.putByte(private.SBox[util.getByte(origState[2],3)], 3) + util.putByte(private.SBox[util.getByte(origState[3],2)], 2) + util.putByte(private.SBox[util.getByte(origState[0],1)], 1) + util.putByte(private.SBox[util.getByte(origState[1],0)], 0); dstState[3] = util.putByte(private.SBox[util.getByte(origState[3],3)], 3) + util.putByte(private.SBox[util.getByte(origState[0],2)], 2) + util.putByte(private.SBox[util.getByte(origState[1],1)], 1) + util.putByte(private.SBox[util.getByte(origState[2],0)], 0); end -- -- do decryption round -- function private.doInvRound(origState, dstState) dstState[0] = bit.bxor(bit.bxor(bit.bxor( private.tableInv0[util.getByte(origState[0],3)], private.tableInv1[util.getByte(origState[3],2)]), private.tableInv2[util.getByte(origState[2],1)]), private.tableInv3[util.getByte(origState[1],0)]); dstState[1] = bit.bxor(bit.bxor(bit.bxor( private.tableInv0[util.getByte(origState[1],3)], private.tableInv1[util.getByte(origState[0],2)]), private.tableInv2[util.getByte(origState[3],1)]), private.tableInv3[util.getByte(origState[2],0)]); dstState[2] = bit.bxor(bit.bxor(bit.bxor( private.tableInv0[util.getByte(origState[2],3)], private.tableInv1[util.getByte(origState[1],2)]), private.tableInv2[util.getByte(origState[0],1)]), private.tableInv3[util.getByte(origState[3],0)]); dstState[3] = bit.bxor(bit.bxor(bit.bxor( private.tableInv0[util.getByte(origState[3],3)], private.tableInv1[util.getByte(origState[2],2)]), private.tableInv2[util.getByte(origState[1],1)]), private.tableInv3[util.getByte(origState[0],0)]); end -- -- do last decryption round -- function private.doInvLastRound(origState, dstState) dstState[0] = util.putByte(private.iSBox[util.getByte(origState[0],3)], 3) + util.putByte(private.iSBox[util.getByte(origState[3],2)], 2) + util.putByte(private.iSBox[util.getByte(origState[2],1)], 1) + util.putByte(private.iSBox[util.getByte(origState[1],0)], 0); dstState[1] = util.putByte(private.iSBox[util.getByte(origState[1],3)], 3) + util.putByte(private.iSBox[util.getByte(origState[0],2)], 2) + util.putByte(private.iSBox[util.getByte(origState[3],1)], 1) + util.putByte(private.iSBox[util.getByte(origState[2],0)], 0); dstState[2] = util.putByte(private.iSBox[util.getByte(origState[2],3)], 3) + util.putByte(private.iSBox[util.getByte(origState[1],2)], 2) + util.putByte(private.iSBox[util.getByte(origState[0],1)], 1) + util.putByte(private.iSBox[util.getByte(origState[3],0)], 0); dstState[3] = util.putByte(private.iSBox[util.getByte(origState[3],3)], 3) + util.putByte(private.iSBox[util.getByte(origState[2],2)], 2) + util.putByte(private.iSBox[util.getByte(origState[1],1)], 1) + util.putByte(private.iSBox[util.getByte(origState[0],0)], 0); end -- -- encrypts 16 Bytes -- key encryption key schedule -- input array with input data -- inputOffset start index for input -- output array for encrypted data -- outputOffset start index for output -- function public.encrypt(key, input, inputOffset, output, outputOffset) --default parameters inputOffset = inputOffset or 1; output = output or {}; outputOffset = outputOffset or 1; local state = {}; local tmpState = {}; if (key[public.KEY_TYPE] ~= public.ENCRYPTION_KEY) then print("No encryption key: ", key[public.KEY_TYPE]); return; end state = util.bytesToInts(input, inputOffset, 4); private.addRoundKey(state, key, 0); local round = 1; while (round < key[public.ROUNDS] - 1) do -- do a double round to save temporary assignments private.doRound(state, tmpState); private.addRoundKey(tmpState, key, round); round = round + 1; private.doRound(tmpState, state); private.addRoundKey(state, key, round); round = round + 1; end private.doRound(state, tmpState); private.addRoundKey(tmpState, key, round); round = round +1; private.doLastRound(tmpState, state); private.addRoundKey(state, key, round); return util.intsToBytes(state, output, outputOffset); end -- -- decrypt 16 bytes -- key decryption key schedule -- input array with input data -- inputOffset start index for input -- output array for decrypted data -- outputOffset start index for output --- function public.decrypt(key, input, inputOffset, output, outputOffset) -- default arguments inputOffset = inputOffset or 1; output = output or {}; outputOffset = outputOffset or 1; local state = {}; local tmpState = {}; if (key[public.KEY_TYPE] ~= public.DECRYPTION_KEY) then print("No decryption key: ", key[public.KEY_TYPE]); return; end state = util.bytesToInts(input, inputOffset, 4); private.addRoundKey(state, key, key[public.ROUNDS]); local round = key[public.ROUNDS] - 1; while (round > 2) do -- do a double round to save temporary assignments private.doInvRound(state, tmpState); private.addRoundKey(tmpState, key, round); round = round - 1; private.doInvRound(tmpState, state); private.addRoundKey(state, key, round); round = round - 1; end private.doInvRound(state, tmpState); private.addRoundKey(tmpState, key, round); round = round - 1; private.doInvLastRound(tmpState, state); private.addRoundKey(state, key, round); return util.intsToBytes(state, output, outputOffset); end -- calculate all tables when loading this file private.calcSBox(); private.calcRoundTables(); private.calcInvRoundTables(); return public; end)() local ciphermode = (function() local public = {}; -- -- Encrypt strings -- key - byte array with key -- string - string to encrypt -- modefunction - function for cipher mode to use -- function public.encryptString(key, data, modeFunction) local iv = iv or {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; local keySched = aes.expandEncryptionKey(key); local encryptedData = buffer.new(); for i = 1, #data/16 do local offset = (i-1)*16 + 1; local byteData = {string.byte(data,offset,offset +15)}; modeFunction(keySched, byteData, iv); buffer.addString(encryptedData, string.char(unpack(byteData))); end return buffer.toString(encryptedData); end -- -- the following 4 functions can be used as -- modefunction for encryptString -- -- Electronic code book mode encrypt function function public.encryptECB(keySched, byteData, iv) aes.encrypt(keySched, byteData, 1, byteData, 1); end -- Cipher block chaining mode encrypt function function public.encryptCBC(keySched, byteData, iv) util.xorIV(byteData, iv); aes.encrypt(keySched, byteData, 1, byteData, 1); for j = 1,16 do iv[j] = byteData[j]; end end -- Output feedback mode encrypt function function public.encryptOFB(keySched, byteData, iv) aes.encrypt(keySched, iv, 1, iv, 1); util.xorIV(byteData, iv); end -- Cipher feedback mode encrypt function function public.encryptCFB(keySched, byteData, iv) aes.encrypt(keySched, iv, 1, iv, 1); util.xorIV(byteData, iv); for j = 1,16 do iv[j] = byteData[j]; end end -- -- Decrypt strings -- key - byte array with key -- string - string to decrypt -- modefunction - function for cipher mode to use -- function public.decryptString(key, data, modeFunction) local iv = iv or {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; local keySched; if (modeFunction == public.decryptOFB or modeFunction == public.decryptCFB) then keySched = aes.expandEncryptionKey(key); else keySched = aes.expandDecryptionKey(key); end local decryptedData = buffer.new(); for i = 1, #data/16 do local offset = (i-1)*16 + 1; local byteData = {string.byte(data,offset,offset +15)}; iv = modeFunction(keySched, byteData, iv); buffer.addString(decryptedData, string.char(unpack(byteData))); end return buffer.toString(decryptedData); end -- -- the following 4 functions can be used as -- modefunction for decryptString -- -- Electronic code book mode decrypt function function public.decryptECB(keySched, byteData, iv) aes.decrypt(keySched, byteData, 1, byteData, 1); return iv; end -- Cipher block chaining mode decrypt function function public.decryptCBC(keySched, byteData, iv) local nextIV = {}; for j = 1,16 do nextIV[j] = byteData[j]; end aes.decrypt(keySched, byteData, 1, byteData, 1); util.xorIV(byteData, iv); return nextIV; end -- Output feedback mode decrypt function function public.decryptOFB(keySched, byteData, iv) aes.encrypt(keySched, iv, 1, iv, 1); util.xorIV(byteData, iv); return iv; end -- Cipher feedback mode decrypt function function public.decryptCFB(keySched, byteData, iv) local nextIV = {}; for j = 1,16 do nextIV[j] = byteData[j]; end aes.encrypt(keySched, iv, 1, iv, 1); util.xorIV(byteData, iv); return nextIV; end return public; end) local main = (function() local private = {}; local public = {}; local ciphermode = require("aeslua.ciphermode"); local util = require("aeslua.util"); -- -- Simple API for encrypting strings. -- public.AES128 = 16; public.AES192 = 24; public.AES256 = 32; public.ECBMODE = 1; public.CBCMODE = 2; public.OFBMODE = 3; public.CFBMODE = 4; function private.pwToKey(password, keyLength) local padLength = keyLength; if (keyLength == public.AES192) then padLength = 32; end if (padLength > #password) then local postfix = ""; for i = 1,padLength - #password do postfix = postfix .. string.char(0); end password = password .. postfix; else password = string.sub(password, 1, padLength); end local pwBytes = {string.byte(password,1,#password)}; password = ciphermode.encryptString(pwBytes, password, ciphermode.encryptCBC); password = string.sub(password, 1, keyLength); return {string.byte(password,1,#password)}; end -- -- Encrypts string data with password password. -- password - the encryption key is generated from this string -- data - string to encrypt (must not be too large) -- keyLength - length of aes key: 128(default), 192 or 256 Bit -- mode - mode of encryption: ecb, cbc(default), ofb, cfb -- -- mode and keyLength must be the same for encryption and decryption. -- function public.encrypt(password, data, keyLength, mode) assert(password ~= nil, "Empty password."); assert(password ~= nil, "Empty data."); local mode = mode or public.CBCMODE; local keyLength = keyLength or public.AES128; local key = private.pwToKey(password, keyLength); local paddedData = util.padByteString(data); if (mode == public.ECBMODE) then return ciphermode.encryptString(key, paddedData, ciphermode.encryptECB); elseif (mode == public.CBCMODE) then return ciphermode.encryptString(key, paddedData, ciphermode.encryptCBC); elseif (mode == public.OFBMODE) then return ciphermode.encryptString(key, paddedData, ciphermode.encryptOFB); elseif (mode == public.CFBMODE) then return ciphermode.encryptString(key, paddedData, ciphermode.encryptCFB); else return nil; end end -- -- Decrypts string data with password password. -- password - the decryption key is generated from this string -- data - string to encrypt -- keyLength - length of aes key: 128(default), 192 or 256 Bit -- mode - mode of decryption: ecb, cbc(default), ofb, cfb -- -- mode and keyLength must be the same for encryption and decryption. -- function public.decrypt(password, data, keyLength, mode) local mode = mode or public.CBCMODE; local keyLength = keyLength or public.AES128; local key = private.pwToKey(password, keyLength); local plain; if (mode == public.ECBMODE) then plain = ciphermode.decryptString(key, data, ciphermode.decryptECB); elseif (mode == public.CBCMODE) then plain = ciphermode.decryptString(key, data, ciphermode.decryptCBC); elseif (mode == public.OFBMODE) then plain = ciphermode.decryptString(key, data, ciphermode.decryptOFB); elseif (mode == public.CFBMODE) then plain = ciphermode.decryptString(key, data, ciphermode.decryptCFB); end result = util.unpadByteString(plain); if (result == nil) then return nil; end return result; end return public end)() return main
Editor Settings
Theme
Key bindings
Full width
Lines