· 5 years ago · Jun 22, 2020, 12:48 PM
1local function _W(f) local e=setmetatable({}, {__index = _ENV or getfenv()}) if setfenv then setfenv(f, e) end return f(e) or e end
2local bit=_W(function(_ENV, ...)
3--[[
4 This bit API is designed to cope with unsigned integers instead of normal integers
5
6 To do this we add checks for overflows: (x > 2^31 ? x - 2 ^ 32 : x)
7 These are written in long form because no constant folding.
8]]
9
10local floor = math.floor
11
12local lshift, rshift
13
14rshift = function(a,disp)
15 return floor(a % 4294967296 / 2^disp)
16end
17
18lshift = function(a,disp)
19 return (a * 2^disp) % 4294967296
20end
21
22return {
23 -- bit operations
24 bnot = bit.bnot,
25 band = bit.band,
26 bor = bit.bor,
27 bxor = bit.bxor,
28 rshift = rshift,
29 lshift = lshift,
30}
31end)
32local gf=_W(function(_ENV, ...)
33-- finite field with base 2 and modulo irreducible polynom x^8+x^4+x^3+x+1 = 0x11d
34local bxor = bit.bxor
35local lshift = bit.lshift
36
37-- private data of gf
38local n = 0x100
39local ord = 0xff
40local irrPolynom = 0x11b
41local exp = {}
42local log = {}
43
44--
45-- add two polynoms (its simply xor)
46--
47local function add(operand1, operand2)
48 return bxor(operand1,operand2)
49end
50
51--
52-- subtract two polynoms (same as addition)
53--
54local function sub(operand1, operand2)
55 return bxor(operand1,operand2)
56end
57
58--
59-- inverts element
60-- a^(-1) = g^(order - log(a))
61--
62local function invert(operand)
63 -- special case for 1
64 if (operand == 1) then
65 return 1
66 end
67 -- normal invert
68 local exponent = ord - log[operand]
69 return exp[exponent]
70end
71
72--
73-- multiply two elements using a logarithm table
74-- a*b = g^(log(a)+log(b))
75--
76local function mul(operand1, operand2)
77 if (operand1 == 0 or operand2 == 0) then
78 return 0
79 end
80
81 local exponent = log[operand1] + log[operand2]
82 if (exponent >= ord) then
83 exponent = exponent - ord
84 end
85 return exp[exponent]
86end
87
88--
89-- divide two elements
90-- a/b = g^(log(a)-log(b))
91--
92local function div(operand1, operand2)
93 if (operand1 == 0) then
94 return 0
95 end
96 -- TODO: exception if operand2 == 0
97 local exponent = log[operand1] - log[operand2]
98 if (exponent < 0) then
99 exponent = exponent + ord
100 end
101 return exp[exponent]
102end
103
104--
105-- print logarithmic table
106--
107local function printLog()
108 for i = 1, n do
109 print("log(", i-1, ")=", log[i-1])
110 end
111end
112
113--
114-- print exponentiation table
115--
116local function printExp()
117 for i = 1, n do
118 print("exp(", i-1, ")=", exp[i-1])
119 end
120end
121
122--
123-- calculate logarithmic and exponentiation table
124--
125local function initMulTable()
126 local a = 1
127
128 for i = 0,ord-1 do
129 exp[i] = a
130 log[a] = i
131
132 -- multiply with generator x+1 -> left shift + 1
133 a = bxor(lshift(a, 1), a)
134
135 -- if a gets larger than order, reduce modulo irreducible polynom
136 if a > ord then
137 a = sub(a, irrPolynom)
138 end
139 end
140end
141
142initMulTable()
143
144return {
145 add = add,
146 sub = sub,
147 invert = invert,
148 mul = mul,
149 div = dib,
150 printLog = printLog,
151 printExp = printExp,
152}
153end)
154util=_W(function(_ENV, ...)
155-- Cache some bit operators
156local bxor = bit.bxor
157local rshift = bit.rshift
158local band = bit.band
159local lshift = bit.lshift
160
161local sleepCheckIn
162--
163-- calculate the parity of one byte
164--
165local function byteParity(byte)
166 byte = bxor(byte, rshift(byte, 4))
167 byte = bxor(byte, rshift(byte, 2))
168 byte = bxor(byte, rshift(byte, 1))
169 return band(byte, 1)
170end
171
172--
173-- get byte at position index
174--
175local function getByte(number, index)
176 if (index == 0) then
177 return band(number,0xff)
178 else
179 return band(rshift(number, index*8),0xff)
180 end
181end
182
183
184--
185-- put number into int at position index
186--
187local function putByte(number, index)
188 if (index == 0) then
189 return band(number,0xff)
190 else
191 return lshift(band(number,0xff),index*8)
192 end
193end
194
195--
196-- convert byte array to int array
197--
198local function bytesToInts(bytes, start, n)
199 local ints = {}
200 for i = 0, n - 1 do
201 ints[i + 1] =
202 putByte(bytes[start + (i*4)], 3) +
203 putByte(bytes[start + (i*4) + 1], 2) +
204 putByte(bytes[start + (i*4) + 2], 1) +
205 putByte(bytes[start + (i*4) + 3], 0)
206
207 if n % 10000 == 0 then sleepCheckIn() end
208 end
209 return ints
210end
211
212--
213-- convert int array to byte array
214--
215local function intsToBytes(ints, output, outputOffset, n)
216 n = n or #ints
217 for i = 0, n - 1 do
218 for j = 0,3 do
219 output[outputOffset + i*4 + (3 - j)] = getByte(ints[i + 1], j)
220 end
221
222 if n % 10000 == 0 then sleepCheckIn() end
223 end
224 return output
225end
226
227--
228-- convert bytes to hexString
229--
230local function bytesToHex(bytes)
231 local hexBytes = ""
232
233 for i,byte in ipairs(bytes) do
234 hexBytes = hexBytes .. string.format("%02x ", byte)
235 end
236
237 return hexBytes
238end
239
240local function hexToBytes(bytes)
241 local out = {}
242 for i = 1, #bytes, 2 do
243 out[#out + 1] = tonumber(bytes:sub(i, i + 1), 16)
244 end
245
246 return out
247end
248
249--
250-- convert data to hex string
251--
252local function toHexString(data)
253 local type = type(data)
254 if (type == "number") then
255 return string.format("%08x",data)
256 elseif (type == "table") then
257 return bytesToHex(data)
258 elseif (type == "string") then
259 local bytes = {string.byte(data, 1, #data)}
260
261 return bytesToHex(bytes)
262 else
263 return data
264 end
265end
266
267local function padByteString(data)
268 local dataLength = #data
269
270 local random1 = math.random(0,255)
271 local random2 = math.random(0,255)
272
273 local prefix = string.char(random1,
274 random2,
275 random1,
276 random2,
277 getByte(dataLength, 3),
278 getByte(dataLength, 2),
279 getByte(dataLength, 1),
280 getByte(dataLength, 0)
281 )
282
283 data = prefix .. data
284
285 local paddingLength = math.ceil(#data/16)*16 - #data
286 local padding = ""
287 for i=1,paddingLength do
288 padding = padding .. string.char(math.random(0,255))
289 end
290
291 return data .. padding
292end
293
294local function properlyDecrypted(data)
295 local random = {string.byte(data,1,4)}
296
297 if (random[1] == random[3] and random[2] == random[4]) then
298 return true
299 end
300
301 return false
302end
303
304local function unpadByteString(data)
305 if (not properlyDecrypted(data)) then
306 return nil
307 end
308
309 local dataLength = putByte(string.byte(data,5), 3)
310 + putByte(string.byte(data,6), 2)
311 + putByte(string.byte(data,7), 1)
312 + putByte(string.byte(data,8), 0)
313
314 return string.sub(data,9,8+dataLength)
315end
316
317local function xorIV(data, iv)
318 for i = 1,16 do
319 data[i] = bxor(data[i], iv[i])
320 end
321end
322
323local function increment(data)
324 local i = 16
325 while true do
326 local value = data[i] + 1
327 if value >= 256 then
328 data[i] = value - 256
329 i = (i - 2) % 16 + 1
330 else
331 data[i] = value
332 break
333 end
334 end
335end
336
337-- Called every encryption cycle
338local push, pull, time = os.queueEvent, coroutine.yield, os.time
339local oldTime = time()
340local function sleepCheckIn()
341 local newTime = time()
342 if newTime - oldTime >= 0.03 then -- (0.020 * 1.5)
343 oldTime = newTime
344 push("sleep")
345 pull("sleep")
346 end
347end
348
349local function getRandomData(bytes)
350 local char, random, sleep, insert = string.char, math.random, sleepCheckIn, table.insert
351 local result = {}
352
353 for i=1,bytes do
354 insert(result, random(0,255))
355 if i % 10240 == 0 then sleep() end
356 end
357
358 return result
359end
360
361local function getRandomString(bytes)
362 local char, random, sleep, insert = string.char, math.random, sleepCheckIn, table.insert
363 local result = {}
364
365 for i=1,bytes do
366 insert(result, char(random(0,255)))
367 if i % 10240 == 0 then sleep() end
368 end
369
370 return table.concat(result)
371end
372
373return {
374 byteParity = byteParity,
375 getByte = getByte,
376 putByte = putByte,
377 bytesToInts = bytesToInts,
378 intsToBytes = intsToBytes,
379 bytesToHex = bytesToHex,
380 hexToBytes = hexToBytes,
381 toHexString = toHexString,
382 padByteString = padByteString,
383 properlyDecrypted = properlyDecrypted,
384 unpadByteString = unpadByteString,
385 xorIV = xorIV,
386 increment = increment,
387
388 sleepCheckIn = sleepCheckIn,
389
390 getRandomData = getRandomData,
391 getRandomString = getRandomString,
392}
393end)
394aes=_W(function(_ENV, ...)
395-- Implementation of AES with nearly pure lua
396-- AES with lua is slow, really slow :-)
397
398local putByte = util.putByte
399local getByte = util.getByte
400
401-- some constants
402local ROUNDS = 'rounds'
403local KEY_TYPE = "type"
404local ENCRYPTION_KEY=1
405local DECRYPTION_KEY=2
406
407-- aes SBOX
408local SBox = {}
409local iSBox = {}
410
411-- aes tables
412local table0 = {}
413local table1 = {}
414local table2 = {}
415local table3 = {}
416
417local tableInv0 = {}
418local tableInv1 = {}
419local tableInv2 = {}
420local tableInv3 = {}
421
422-- round constants
423local rCon = {
424 0x01000000,
425 0x02000000,
426 0x04000000,
427 0x08000000,
428 0x10000000,
429 0x20000000,
430 0x40000000,
431 0x80000000,
432 0x1b000000,
433 0x36000000,
434 0x6c000000,
435 0xd8000000,
436 0xab000000,
437 0x4d000000,
438 0x9a000000,
439 0x2f000000,
440}
441
442--
443-- affine transformation for calculating the S-Box of AES
444--
445local function affinMap(byte)
446 mask = 0xf8
447 result = 0
448 for i = 1,8 do
449 result = bit.lshift(result,1)
450
451 parity = util.byteParity(bit.band(byte,mask))
452 result = result + parity
453
454 -- simulate roll
455 lastbit = bit.band(mask, 1)
456 mask = bit.band(bit.rshift(mask, 1),0xff)
457 if (lastbit ~= 0) then
458 mask = bit.bor(mask, 0x80)
459 else
460 mask = bit.band(mask, 0x7f)
461 end
462 end
463
464 return bit.bxor(result, 0x63)
465end
466
467--
468-- calculate S-Box and inverse S-Box of AES
469-- apply affine transformation to inverse in finite field 2^8
470--
471local function calcSBox()
472 for i = 0, 255 do
473 if (i ~= 0) then
474 inverse = gf.invert(i)
475 else
476 inverse = i
477 end
478 mapped = affinMap(inverse)
479 SBox[i] = mapped
480 iSBox[mapped] = i
481 end
482end
483
484--
485-- Calculate round tables
486-- round tables are used to calculate shiftRow, MixColumn and SubBytes
487-- with 4 table lookups and 4 xor operations.
488--
489local function calcRoundTables()
490 for x = 0,255 do
491 byte = SBox[x]
492 table0[x] = putByte(gf.mul(0x03, byte), 0)
493 + putByte( byte , 1)
494 + putByte( byte , 2)
495 + putByte(gf.mul(0x02, byte), 3)
496 table1[x] = putByte( byte , 0)
497 + putByte( byte , 1)
498 + putByte(gf.mul(0x02, byte), 2)
499 + putByte(gf.mul(0x03, byte), 3)
500 table2[x] = putByte( byte , 0)
501 + putByte(gf.mul(0x02, byte), 1)
502 + putByte(gf.mul(0x03, byte), 2)
503 + putByte( byte , 3)
504 table3[x] = putByte(gf.mul(0x02, byte), 0)
505 + putByte(gf.mul(0x03, byte), 1)
506 + putByte( byte , 2)
507 + putByte( byte , 3)
508 end
509end
510
511--
512-- Calculate inverse round tables
513-- does the inverse of the normal roundtables for the equivalent
514-- decryption algorithm.
515--
516local function calcInvRoundTables()
517 for x = 0,255 do
518 byte = iSBox[x]
519 tableInv0[x] = putByte(gf.mul(0x0b, byte), 0)
520 + putByte(gf.mul(0x0d, byte), 1)
521 + putByte(gf.mul(0x09, byte), 2)
522 + putByte(gf.mul(0x0e, byte), 3)
523 tableInv1[x] = putByte(gf.mul(0x0d, byte), 0)
524 + putByte(gf.mul(0x09, byte), 1)
525 + putByte(gf.mul(0x0e, byte), 2)
526 + putByte(gf.mul(0x0b, byte), 3)
527 tableInv2[x] = putByte(gf.mul(0x09, byte), 0)
528 + putByte(gf.mul(0x0e, byte), 1)
529 + putByte(gf.mul(0x0b, byte), 2)
530 + putByte(gf.mul(0x0d, byte), 3)
531 tableInv3[x] = putByte(gf.mul(0x0e, byte), 0)
532 + putByte(gf.mul(0x0b, byte), 1)
533 + putByte(gf.mul(0x0d, byte), 2)
534 + putByte(gf.mul(0x09, byte), 3)
535 end
536end
537
538
539--
540-- rotate word: 0xaabbccdd gets 0xbbccddaa
541-- used for key schedule
542--
543local function rotWord(word)
544 local tmp = bit.band(word,0xff000000)
545 return (bit.lshift(word,8) + bit.rshift(tmp,24))
546end
547
548--
549-- replace all bytes in a word with the SBox.
550-- used for key schedule
551--
552local function subWord(word)
553 return putByte(SBox[getByte(word,0)],0)
554 + putByte(SBox[getByte(word,1)],1)
555 + putByte(SBox[getByte(word,2)],2)
556 + putByte(SBox[getByte(word,3)],3)
557end
558
559--
560-- generate key schedule for aes encryption
561--
562-- returns table with all round keys and
563-- the necessary number of rounds saved in [ROUNDS]
564--
565local function expandEncryptionKey(key)
566 local keySchedule = {}
567 local keyWords = math.floor(#key / 4)
568
569
570 if ((keyWords ~= 4 and keyWords ~= 6 and keyWords ~= 8) or (keyWords * 4 ~= #key)) then
571 error("Invalid key size: " .. tostring(keyWords))
572 return nil
573 end
574
575 keySchedule[ROUNDS] = keyWords + 6
576 keySchedule[KEY_TYPE] = ENCRYPTION_KEY
577
578 for i = 0,keyWords - 1 do
579 keySchedule[i] = putByte(key[i*4+1], 3)
580 + putByte(key[i*4+2], 2)
581 + putByte(key[i*4+3], 1)
582 + putByte(key[i*4+4], 0)
583 end
584
585 for i = keyWords, (keySchedule[ROUNDS] + 1)*4 - 1 do
586 local tmp = keySchedule[i-1]
587
588 if ( i % keyWords == 0) then
589 tmp = rotWord(tmp)
590 tmp = subWord(tmp)
591
592 local index = math.floor(i/keyWords)
593 tmp = bit.bxor(tmp,rCon[index])
594 elseif (keyWords > 6 and i % keyWords == 4) then
595 tmp = subWord(tmp)
596 end
597
598 keySchedule[i] = bit.bxor(keySchedule[(i-keyWords)],tmp)
599 end
600
601 return keySchedule
602end
603
604--
605-- Inverse mix column
606-- used for key schedule of decryption key
607--
608local function invMixColumnOld(word)
609 local b0 = getByte(word,3)
610 local b1 = getByte(word,2)
611 local b2 = getByte(word,1)
612 local b3 = getByte(word,0)
613
614 return putByte(gf.add(gf.add(gf.add(gf.mul(0x0b, b1),
615 gf.mul(0x0d, b2)),
616 gf.mul(0x09, b3)),
617 gf.mul(0x0e, b0)),3)
618 + putByte(gf.add(gf.add(gf.add(gf.mul(0x0b, b2),
619 gf.mul(0x0d, b3)),
620 gf.mul(0x09, b0)),
621 gf.mul(0x0e, b1)),2)
622 + putByte(gf.add(gf.add(gf.add(gf.mul(0x0b, b3),
623 gf.mul(0x0d, b0)),
624 gf.mul(0x09, b1)),
625 gf.mul(0x0e, b2)),1)
626 + putByte(gf.add(gf.add(gf.add(gf.mul(0x0b, b0),
627 gf.mul(0x0d, b1)),
628 gf.mul(0x09, b2)),
629 gf.mul(0x0e, b3)),0)
630end
631
632--
633-- Optimized inverse mix column
634-- look at http://fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.311.pdf
635-- TODO: make it work
636--
637local function invMixColumn(word)
638 local b0 = getByte(word,3)
639 local b1 = getByte(word,2)
640 local b2 = getByte(word,1)
641 local b3 = getByte(word,0)
642
643 local t = bit.bxor(b3,b2)
644 local u = bit.bxor(b1,b0)
645 local v = bit.bxor(t,u)
646 v = bit.bxor(v,gf.mul(0x08,v))
647 w = bit.bxor(v,gf.mul(0x04, bit.bxor(b2,b0)))
648 v = bit.bxor(v,gf.mul(0x04, bit.bxor(b3,b1)))
649
650 return putByte( bit.bxor(bit.bxor(b3,v), gf.mul(0x02, bit.bxor(b0,b3))), 0)
651 + putByte( bit.bxor(bit.bxor(b2,w), gf.mul(0x02, t )), 1)
652 + putByte( bit.bxor(bit.bxor(b1,v), gf.mul(0x02, bit.bxor(b0,b3))), 2)
653 + putByte( bit.bxor(bit.bxor(b0,w), gf.mul(0x02, u )), 3)
654end
655
656--
657-- generate key schedule for aes decryption
658--
659-- uses key schedule for aes encryption and transforms each
660-- key by inverse mix column.
661--
662local function expandDecryptionKey(key)
663 local keySchedule = expandEncryptionKey(key)
664 if (keySchedule == nil) then
665 return nil
666 end
667
668 keySchedule[KEY_TYPE] = DECRYPTION_KEY
669
670 for i = 4, (keySchedule[ROUNDS] + 1)*4 - 5 do
671 keySchedule[i] = invMixColumnOld(keySchedule[i])
672 end
673
674 return keySchedule
675end
676
677--
678-- xor round key to state
679--
680local function addRoundKey(state, key, round)
681 for i = 0, 3 do
682 state[i + 1] = bit.bxor(state[i + 1], key[round*4+i])
683 end
684end
685
686--
687-- do encryption round (ShiftRow, SubBytes, MixColumn together)
688--
689local function doRound(origState, dstState)
690 dstState[1] = bit.bxor(bit.bxor(bit.bxor(
691 table0[getByte(origState[1],3)],
692 table1[getByte(origState[2],2)]),
693 table2[getByte(origState[3],1)]),
694 table3[getByte(origState[4],0)])
695
696 dstState[2] = bit.bxor(bit.bxor(bit.bxor(
697 table0[getByte(origState[2],3)],
698 table1[getByte(origState[3],2)]),
699 table2[getByte(origState[4],1)]),
700 table3[getByte(origState[1],0)])
701
702 dstState[3] = bit.bxor(bit.bxor(bit.bxor(
703 table0[getByte(origState[3],3)],
704 table1[getByte(origState[4],2)]),
705 table2[getByte(origState[1],1)]),
706 table3[getByte(origState[2],0)])
707
708 dstState[4] = bit.bxor(bit.bxor(bit.bxor(
709 table0[getByte(origState[4],3)],
710 table1[getByte(origState[1],2)]),
711 table2[getByte(origState[2],1)]),
712 table3[getByte(origState[3],0)])
713end
714
715--
716-- do last encryption round (ShiftRow and SubBytes)
717--
718local function doLastRound(origState, dstState)
719 dstState[1] = putByte(SBox[getByte(origState[1],3)], 3)
720 + putByte(SBox[getByte(origState[2],2)], 2)
721 + putByte(SBox[getByte(origState[3],1)], 1)
722 + putByte(SBox[getByte(origState[4],0)], 0)
723
724 dstState[2] = putByte(SBox[getByte(origState[2],3)], 3)
725 + putByte(SBox[getByte(origState[3],2)], 2)
726 + putByte(SBox[getByte(origState[4],1)], 1)
727 + putByte(SBox[getByte(origState[1],0)], 0)
728
729 dstState[3] = putByte(SBox[getByte(origState[3],3)], 3)
730 + putByte(SBox[getByte(origState[4],2)], 2)
731 + putByte(SBox[getByte(origState[1],1)], 1)
732 + putByte(SBox[getByte(origState[2],0)], 0)
733
734 dstState[4] = putByte(SBox[getByte(origState[4],3)], 3)
735 + putByte(SBox[getByte(origState[1],2)], 2)
736 + putByte(SBox[getByte(origState[2],1)], 1)
737 + putByte(SBox[getByte(origState[3],0)], 0)
738end
739
740--
741-- do decryption round
742--
743local function doInvRound(origState, dstState)
744 dstState[1] = bit.bxor(bit.bxor(bit.bxor(
745 tableInv0[getByte(origState[1],3)],
746 tableInv1[getByte(origState[4],2)]),
747 tableInv2[getByte(origState[3],1)]),
748 tableInv3[getByte(origState[2],0)])
749
750 dstState[2] = bit.bxor(bit.bxor(bit.bxor(
751 tableInv0[getByte(origState[2],3)],
752 tableInv1[getByte(origState[1],2)]),
753 tableInv2[getByte(origState[4],1)]),
754 tableInv3[getByte(origState[3],0)])
755
756 dstState[3] = bit.bxor(bit.bxor(bit.bxor(
757 tableInv0[getByte(origState[3],3)],
758 tableInv1[getByte(origState[2],2)]),
759 tableInv2[getByte(origState[1],1)]),
760 tableInv3[getByte(origState[4],0)])
761
762 dstState[4] = bit.bxor(bit.bxor(bit.bxor(
763 tableInv0[getByte(origState[4],3)],
764 tableInv1[getByte(origState[3],2)]),
765 tableInv2[getByte(origState[2],1)]),
766 tableInv3[getByte(origState[1],0)])
767end
768
769--
770-- do last decryption round
771--
772local function doInvLastRound(origState, dstState)
773 dstState[1] = putByte(iSBox[getByte(origState[1],3)], 3)
774 + putByte(iSBox[getByte(origState[4],2)], 2)
775 + putByte(iSBox[getByte(origState[3],1)], 1)
776 + putByte(iSBox[getByte(origState[2],0)], 0)
777
778 dstState[2] = putByte(iSBox[getByte(origState[2],3)], 3)
779 + putByte(iSBox[getByte(origState[1],2)], 2)
780 + putByte(iSBox[getByte(origState[4],1)], 1)
781 + putByte(iSBox[getByte(origState[3],0)], 0)
782
783 dstState[3] = putByte(iSBox[getByte(origState[3],3)], 3)
784 + putByte(iSBox[getByte(origState[2],2)], 2)
785 + putByte(iSBox[getByte(origState[1],1)], 1)
786 + putByte(iSBox[getByte(origState[4],0)], 0)
787
788 dstState[4] = putByte(iSBox[getByte(origState[4],3)], 3)
789 + putByte(iSBox[getByte(origState[3],2)], 2)
790 + putByte(iSBox[getByte(origState[2],1)], 1)
791 + putByte(iSBox[getByte(origState[1],0)], 0)
792end
793
794--
795-- encrypts 16 Bytes
796-- key encryption key schedule
797-- input array with input data
798-- inputOffset start index for input
799-- output array for encrypted data
800-- outputOffset start index for output
801--
802local function encrypt(key, input, inputOffset, output, outputOffset)
803 --default parameters
804 inputOffset = inputOffset or 1
805 output = output or {}
806 outputOffset = outputOffset or 1
807
808 local state = {}
809 local tmpState = {}
810
811 if (key[KEY_TYPE] ~= ENCRYPTION_KEY) then
812 error("No encryption key: " .. tostring(key[KEY_TYPE]) .. ", expected " .. ENCRYPTION_KEY)
813 return
814 end
815
816 state = util.bytesToInts(input, inputOffset, 4)
817 addRoundKey(state, key, 0)
818
819
820 local round = 1
821 while (round < key[ROUNDS] - 1) do
822 -- do a double round to save temporary assignments
823 doRound(state, tmpState)
824 addRoundKey(tmpState, key, round)
825 round = round + 1
826
827 doRound(tmpState, state)
828 addRoundKey(state, key, round)
829 round = round + 1
830 end
831
832 doRound(state, tmpState)
833 addRoundKey(tmpState, key, round)
834 round = round +1
835
836 doLastRound(tmpState, state)
837 addRoundKey(state, key, round)
838
839 util.sleepCheckIn()
840 return util.intsToBytes(state, output, outputOffset)
841end
842
843--
844-- decrypt 16 bytes
845-- key decryption key schedule
846-- input array with input data
847-- inputOffset start index for input
848-- output array for decrypted data
849-- outputOffset start index for output
850---
851local function decrypt(key, input, inputOffset, output, outputOffset)
852 -- default arguments
853 inputOffset = inputOffset or 1
854 output = output or {}
855 outputOffset = outputOffset or 1
856
857 local state = {}
858 local tmpState = {}
859
860 if (key[KEY_TYPE] ~= DECRYPTION_KEY) then
861 error("No decryption key: " .. tostring(key[KEY_TYPE]))
862 return
863 end
864
865 state = util.bytesToInts(input, inputOffset, 4)
866 addRoundKey(state, key, key[ROUNDS])
867
868 local round = key[ROUNDS] - 1
869 while (round > 2) do
870 -- do a double round to save temporary assignments
871 doInvRound(state, tmpState)
872 addRoundKey(tmpState, key, round)
873 round = round - 1
874
875 doInvRound(tmpState, state)
876 addRoundKey(state, key, round)
877 round = round - 1
878 end
879
880
881 doInvRound(state, tmpState)
882 addRoundKey(tmpState, key, round)
883 round = round - 1
884
885 doInvLastRound(tmpState, state)
886 addRoundKey(state, key, round)
887
888 util.sleepCheckIn()
889 return util.intsToBytes(state, output, outputOffset)
890end
891
892-- calculate all tables when loading this file
893calcSBox()
894calcRoundTables()
895calcInvRoundTables()
896
897return {
898 ROUNDS = ROUNDS,
899 KEY_TYPE = KEY_TYPE,
900 ENCRYPTION_KEY = ENCRYPTION_KEY,
901 DECRYPTION_KEY = DECRYPTION_KEY,
902
903 expandEncryptionKey = expandEncryptionKey,
904 expandDecryptionKey = expandDecryptionKey,
905 encrypt = encrypt,
906 decrypt = decrypt,
907}
908end)
909local buffer=_W(function(_ENV, ...)
910local function new ()
911 return {}
912end
913
914local function addString (stack, s)
915 table.insert(stack, s)
916end
917
918local function toString (stack)
919 return table.concat(stack)
920end
921
922return {
923 new = new,
924 addString = addString,
925 toString = toString,
926}
927end)
928ciphermode=_W(function(_ENV, ...)
929local public = {}
930
931--
932-- Encrypt strings
933-- key - byte array with key
934-- string - string to encrypt
935-- modefunction - function for cipher mode to use
936--
937
938local random = math.random
939function public.encryptString(key, data, modeFunction, iv)
940 if iv then
941 local ivCopy = {}
942 for i = 1, 16 do ivCopy[i] = iv[i] end
943 iv = ivCopy
944 else
945 iv = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
946 end
947
948 local keySched = aes.expandEncryptionKey(key)
949 local encryptedData = buffer.new()
950
951 for i = 1, #data/16 do
952 local offset = (i-1)*16 + 1
953 local byteData = {string.byte(data,offset,offset +15)}
954
955 iv = modeFunction(keySched, byteData, iv)
956
957 buffer.addString(encryptedData, string.char(unpack(byteData)))
958 end
959
960 return buffer.toString(encryptedData)
961end
962
963--
964-- the following 4 functions can be used as
965-- modefunction for encryptString
966--
967
968-- Electronic code book mode encrypt function
969function public.encryptECB(keySched, byteData, iv)
970 aes.encrypt(keySched, byteData, 1, byteData, 1)
971end
972
973-- Cipher block chaining mode encrypt function
974function public.encryptCBC(keySched, byteData, iv)
975 util.xorIV(byteData, iv)
976 aes.encrypt(keySched, byteData, 1, byteData, 1)
977 return byteData
978end
979
980-- Output feedback mode encrypt function
981function public.encryptOFB(keySched, byteData, iv)
982 aes.encrypt(keySched, iv, 1, iv, 1)
983 util.xorIV(byteData, iv)
984 return iv
985end
986
987-- Cipher feedback mode encrypt function
988function public.encryptCFB(keySched, byteData, iv)
989 aes.encrypt(keySched, iv, 1, iv, 1)
990 util.xorIV(byteData, iv)
991 return byteData
992end
993
994function public.encryptCTR(keySched, byteData, iv)
995 local nextIV = {}
996 for j = 1, 16 do nextIV[j] = iv[j] end
997
998 aes.encrypt(keySched, iv, 1, iv, 1)
999 util.xorIV(byteData, iv)
1000
1001 util.increment(nextIV)
1002
1003 return nextIV
1004end
1005
1006--
1007-- Decrypt strings
1008-- key - byte array with key
1009-- string - string to decrypt
1010-- modefunction - function for cipher mode to use
1011--
1012function public.decryptString(key, data, modeFunction, iv)
1013 if iv then
1014 local ivCopy = {}
1015 for i = 1, 16 do ivCopy[i] = iv[i] end
1016 iv = ivCopy
1017 else
1018 iv = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
1019 end
1020
1021 local keySched
1022 if modeFunction == public.decryptOFB or modeFunction == public.decryptCFB or modeFunction == public.decryptCTR then
1023 keySched = aes.expandEncryptionKey(key)
1024 else
1025 keySched = aes.expandDecryptionKey(key)
1026 end
1027
1028 local decryptedData = buffer.new()
1029
1030 for i = 1, #data/16 do
1031 local offset = (i-1)*16 + 1
1032 local byteData = {string.byte(data,offset,offset +15)}
1033
1034 iv = modeFunction(keySched, byteData, iv)
1035
1036 buffer.addString(decryptedData, string.char(unpack(byteData)))
1037 end
1038
1039 return buffer.toString(decryptedData)
1040end
1041
1042--
1043-- the following 4 functions can be used as
1044-- modefunction for decryptString
1045--
1046
1047-- Electronic code book mode decrypt function
1048function public.decryptECB(keySched, byteData, iv)
1049 aes.decrypt(keySched, byteData, 1, byteData, 1)
1050 return iv
1051end
1052
1053-- Cipher block chaining mode decrypt function
1054function public.decryptCBC(keySched, byteData, iv)
1055 local nextIV = {}
1056 for j = 1, 16 do nextIV[j] = byteData[j] end
1057
1058 aes.decrypt(keySched, byteData, 1, byteData, 1)
1059 util.xorIV(byteData, iv)
1060
1061 return nextIV
1062end
1063
1064-- Output feedback mode decrypt function
1065function public.decryptOFB(keySched, byteData, iv)
1066 aes.encrypt(keySched, iv, 1, iv, 1)
1067 util.xorIV(byteData, iv)
1068
1069 return iv
1070end
1071
1072-- Cipher feedback mode decrypt function
1073function public.decryptCFB(keySched, byteData, iv)
1074 local nextIV = {}
1075 for j = 1, 16 do nextIV[j] = byteData[j] end
1076
1077 aes.encrypt(keySched, iv, 1, iv, 1)
1078 util.xorIV(byteData, iv)
1079
1080 return nextIV
1081end
1082
1083public.decryptCTR = public.encryptCTR
1084
1085return public
1086end)
1087-- Simple API for encrypting strings.
1088--
1089AES128 = 16
1090AES192 = 24
1091AES256 = 32
1092
1093ECBMODE = 1
1094CBCMODE = 2
1095OFBMODE = 3
1096CFBMODE = 4
1097CTRMODE = 4
1098
1099local function pwToKey(password, keyLength, iv)
1100 local padLength = keyLength
1101 if (keyLength == AES192) then
1102 padLength = 32
1103 end
1104
1105 if (padLength > #password) then
1106 local postfix = ""
1107 for i = 1,padLength - #password do
1108 postfix = postfix .. string.char(0)
1109 end
1110 password = password .. postfix
1111 else
1112 password = string.sub(password, 1, padLength)
1113 end
1114
1115 local pwBytes = {string.byte(password,1,#password)}
1116 password = ciphermode.encryptString(pwBytes, password, ciphermode.encryptCBC, iv)
1117
1118 password = string.sub(password, 1, keyLength)
1119
1120 return {string.byte(password,1,#password)}
1121end
1122
1123--
1124-- Encrypts string data with password password.
1125-- password - the encryption key is generated from this string
1126-- data - string to encrypt (must not be too large)
1127-- keyLength - length of aes key: 128(default), 192 or 256 Bit
1128-- mode - mode of encryption: ecb, cbc(default), ofb, cfb
1129--
1130-- mode and keyLength must be the same for encryption and decryption.
1131--
1132function encrypt(password, data, keyLength, mode, iv)
1133 assert(password ~= nil, "Empty password.")
1134 assert(password ~= nil, "Empty data.")
1135
1136 local mode = mode or CBCMODE
1137 local keyLength = keyLength or AES128
1138
1139 local key = pwToKey(password, keyLength, iv)
1140
1141 local paddedData = util.padByteString(data)
1142
1143 if mode == ECBMODE then
1144 return ciphermode.encryptString(key, paddedData, ciphermode.encryptECB, iv)
1145 elseif mode == CBCMODE then
1146 return ciphermode.encryptString(key, paddedData, ciphermode.encryptCBC, iv)
1147 elseif mode == OFBMODE then
1148 return ciphermode.encryptString(key, paddedData, ciphermode.encryptOFB, iv)
1149 elseif mode == CFBMODE then
1150 return ciphermode.encryptString(key, paddedData, ciphermode.encryptCFB, iv)
1151 elseif mode == CTRMODE then
1152 return ciphermode.encryptString(key, paddedData, ciphermode.encryptCTR, iv)
1153 else
1154 error("Unknown mode", 2)
1155 end
1156end
1157
1158
1159
1160
1161function decrypt(password, data, keyLength, mode, iv)
1162 local mode = mode or CBCMODE
1163 local keyLength = keyLength or AES128
1164
1165 local key = pwToKey(password, keyLength, iv)
1166
1167 local plain
1168 if mode == ECBMODE then
1169 plain = ciphermode.decryptString(key, data, ciphermode.decryptECB, iv)
1170 elseif mode == CBCMODE then
1171 plain = ciphermode.decryptString(key, data, ciphermode.decryptCBC, iv)
1172 elseif mode == OFBMODE then
1173 plain = ciphermode.decryptString(key, data, ciphermode.decryptOFB, iv)
1174 elseif mode == CFBMODE then
1175 plain = ciphermode.decryptString(key, data, ciphermode.decryptCFB, iv)
1176 elseif mode == CTRMODE then
1177 plain = ciphermode.decryptString(key, data, ciphermode.decryptCTR, iv)
1178 else
1179 error("Unknown mode", 2)
1180 end
1181
1182 result = util.unpadByteString(plain)
1183
1184 if (result == nil) then
1185 return nil
1186 end
1187
1188 return result
1189end
1190
1191function AESWritefile(Data, Key)
1192 return pcall(writefile, encrypt(Key, Data, 256, nil, nil, nil))
1193end
1194function AESReadfile(Data, Key)
1195 return pcall(readfile, decrypt(Key, Data, 256, nil, nil, nil))
1196end
1197
1198return {
1199 Writefile = AESWritefile,
1200 Readfile = AESReadfile
1201}