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