require("zmplugin.lockbox").insecure(); local Array = require("zmplugin.lockbox.util.array"); local Bit = require("zmplugin.lockbox.util.bit"); local Math = require("math"); local AND = Bit.band; local OR = Bit.bor; local XOR = Bit.bxor; local LSHIFT = Bit.lshift; local RSHIFT = Bit.rshift; local IN_P = { 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7}; local OUT_P = { 40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31, 38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29, 36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27, 34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25}; -- add 32 to each because we do the expansion on the full LR table, not just R local EBIT = { 32 + 32, 1 + 32, 2 + 32, 3 + 32, 4 + 32, 5 + 32, 4 + 32, 5 + 32, 6 + 32, 7 + 32, 8 + 32, 9 + 32, 8 + 32, 9 + 32, 10 + 32, 11 + 32, 12 + 32, 13 + 32, 12 + 32, 13 + 32, 14 + 32, 15 + 32, 16 + 32, 17 + 32, 16 + 32, 17 + 32, 18 + 32, 19 + 32, 20 + 32, 21 + 32, 20 + 32, 21 + 32, 22 + 32, 23 + 32, 24 + 32, 25 + 32, 24 + 32, 25 + 32, 26 + 32, 27 + 32, 28 + 32, 29 + 32, 28 + 32, 29 + 32, 30 + 32, 31 + 32, 32 + 32, 1 + 32, }; local LR_SWAP = { 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}; local PC1 = { 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4}; local PC2 = { 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32}; local KS1 = { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 1, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 29}; local KS2 = KS1; local KS3 = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 1, 2, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 29, 30}; local KS4 = KS3; local KS5 = KS3; local KS6 = KS3; local KS7 = KS3; local KS8 = KS3; local KS9 = KS1; local KS10 = KS3; local KS11 = KS3; local KS12 = KS3; local KS13 = KS3; local KS14 = KS3; local KS15 = KS3; local KS16 = KS1; local SBOX1 = { 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}; local SBOX2 = { 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}; local SBOX3 = { 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}; local SBOX4 = { 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}; local SBOX5 = { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}; local SBOX6 = { 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}; local SBOX7 = { 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}; local SBOX8 = { 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}; local ROUND_P = { 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25}; local permute = Array.permute; local unpackBytes = function(bytes) local bits = {}; for _, b in pairs(bytes) do table.insert(bits, RSHIFT(AND(b, 0x80), 7)); table.insert(bits, RSHIFT(AND(b, 0x40), 6)); table.insert(bits, RSHIFT(AND(b, 0x20), 5)); table.insert(bits, RSHIFT(AND(b, 0x10), 4)); table.insert(bits, RSHIFT(AND(b, 0x08), 3)); table.insert(bits, RSHIFT(AND(b, 0x04), 2)); table.insert(bits, RSHIFT(AND(b, 0x02), 1)); table.insert(bits, AND(b, 0x01) ); end return bits; end local packBytes = function(bits) local bytes = {} for k, _ in pairs(bits) do local index = Math.floor((k - 1) / 8) + 1; local shift = 7 - Math.fmod((k - 1), 8); local bit = bits[k]; local byte = bytes[index]; if not byte then byte = 0x00; end byte = OR(byte, LSHIFT(bit, shift)); bytes[index] = byte; end return bytes; end local mix = function(LR, key) local ER = permute(LR, EBIT); for k, _ in pairs(ER) do ER[k] = XOR(ER[k], key[k]); end local FRK = {}; local S = 0x00; S = OR(S, ER[1]); S = LSHIFT(S, 1); S = OR(S, ER[6]); S = LSHIFT(S, 1); S = OR(S, ER[2]); S = LSHIFT(S, 1); S = OR(S, ER[3]); S = LSHIFT(S, 1); S = OR(S, ER[4]); S = LSHIFT(S, 1); S = OR(S, ER[5]); S = S + 1; S = SBOX1[S]; FRK[1] = RSHIFT(AND(S, 0x08), 3); FRK[2] = RSHIFT(AND(S, 0x04), 2); FRK[3] = RSHIFT(AND(S, 0x02), 1); FRK[4] = AND(S, 0x01); S = 0x00; S = OR(S, ER[1 + 6]); S = LSHIFT(S, 1); S = OR(S, ER[6 + 6]); S = LSHIFT(S, 1); S = OR(S, ER[2 + 6]); S = LSHIFT(S, 1); S = OR(S, ER[3 + 6]); S = LSHIFT(S, 1); S = OR(S, ER[4 + 6]); S = LSHIFT(S, 1); S = OR(S, ER[5 + 6]); S = S + 1; S = SBOX2[S]; FRK[5] = RSHIFT(AND(S, 0x08), 3); FRK[6] = RSHIFT(AND(S, 0x04), 2); FRK[7] = RSHIFT(AND(S, 0x02), 1); FRK[8] = AND(S, 0x01); S = 0x00; S = OR(S, ER[1 + 12]); S = LSHIFT(S, 1); S = OR(S, ER[6 + 12]); S = LSHIFT(S, 1); S = OR(S, ER[2 + 12]); S = LSHIFT(S, 1); S = OR(S, ER[3 + 12]); S = LSHIFT(S, 1); S = OR(S, ER[4 + 12]); S = LSHIFT(S, 1); S = OR(S, ER[5 + 12]); S = S + 1; S = SBOX3[S]; FRK[9] = RSHIFT(AND(S, 0x08), 3); FRK[10] = RSHIFT(AND(S, 0x04), 2); FRK[11] = RSHIFT(AND(S, 0x02), 1); FRK[12] = AND(S, 0x01); S = 0x00; S = OR(S, ER[1 + 18]); S = LSHIFT(S, 1); S = OR(S, ER[6 + 18]); S = LSHIFT(S, 1); S = OR(S, ER[2 + 18]); S = LSHIFT(S, 1); S = OR(S, ER[3 + 18]); S = LSHIFT(S, 1); S = OR(S, ER[4 + 18]); S = LSHIFT(S, 1); S = OR(S, ER[5 + 18]); S = S + 1; S = SBOX4[S]; FRK[13] = RSHIFT(AND(S, 0x08), 3); FRK[14] = RSHIFT(AND(S, 0x04), 2); FRK[15] = RSHIFT(AND(S, 0x02), 1); FRK[16] = AND(S, 0x01); S = 0x00; S = OR(S, ER[1 + 24]); S = LSHIFT(S, 1); S = OR(S, ER[6 + 24]); S = LSHIFT(S, 1); S = OR(S, ER[2 + 24]); S = LSHIFT(S, 1); S = OR(S, ER[3 + 24]); S = LSHIFT(S, 1); S = OR(S, ER[4 + 24]); S = LSHIFT(S, 1); S = OR(S, ER[5 + 24]); S = S + 1; S = SBOX5[S]; FRK[17] = RSHIFT(AND(S, 0x08), 3); FRK[18] = RSHIFT(AND(S, 0x04), 2); FRK[19] = RSHIFT(AND(S, 0x02), 1); FRK[20] = AND(S, 0x01); S = 0x00; S = OR(S, ER[1 + 30]); S = LSHIFT(S, 1); S = OR(S, ER[6 + 30]); S = LSHIFT(S, 1); S = OR(S, ER[2 + 30]); S = LSHIFT(S, 1); S = OR(S, ER[3 + 30]); S = LSHIFT(S, 1); S = OR(S, ER[4 + 30]); S = LSHIFT(S, 1); S = OR(S, ER[5 + 30]); S = S + 1; S = SBOX6[S]; FRK[21] = RSHIFT(AND(S, 0x08), 3); FRK[22] = RSHIFT(AND(S, 0x04), 2); FRK[23] = RSHIFT(AND(S, 0x02), 1); FRK[24] = AND(S, 0x01); S = 0x00; S = OR(S, ER[1 + 36]); S = LSHIFT(S, 1); S = OR(S, ER[6 + 36]); S = LSHIFT(S, 1); S = OR(S, ER[2 + 36]); S = LSHIFT(S, 1); S = OR(S, ER[3 + 36]); S = LSHIFT(S, 1); S = OR(S, ER[4 + 36]); S = LSHIFT(S, 1); S = OR(S, ER[5 + 36]); S = S + 1; S = SBOX7[S]; FRK[25] = RSHIFT(AND(S, 0x08), 3); FRK[26] = RSHIFT(AND(S, 0x04), 2); FRK[27] = RSHIFT(AND(S, 0x02), 1); FRK[28] = AND(S, 0x01); S = 0x00; S = OR(S, ER[1 + 42]); S = LSHIFT(S, 1); S = OR(S, ER[6 + 42]); S = LSHIFT(S, 1); S = OR(S, ER[2 + 42]); S = LSHIFT(S, 1); S = OR(S, ER[3 + 42]); S = LSHIFT(S, 1); S = OR(S, ER[4 + 42]); S = LSHIFT(S, 1); S = OR(S, ER[5 + 42]); S = S + 1; S = SBOX8[S]; FRK[29] = RSHIFT(AND(S, 0x08), 3); FRK[30] = RSHIFT(AND(S, 0x04), 2); FRK[31] = RSHIFT(AND(S, 0x02), 1); FRK[32] = AND(S, 0x01); FRK = permute(FRK, ROUND_P); return FRK; end local DES = {}; DES.blockSize = 8; DES.encrypt = function(keyBlock, inputBlock) local LR = unpackBytes(inputBlock); local keyBits = unpackBytes(keyBlock); local CD = permute(keyBits, PC1); --key schedule CD = permute(CD, KS1); local KEY1 = permute(CD, PC2); CD = permute(CD, KS2); local KEY2 = permute(CD, PC2); CD = permute(CD, KS3); local KEY3 = permute(CD, PC2); CD = permute(CD, KS4); local KEY4 = permute(CD, PC2); CD = permute(CD, KS5); local KEY5 = permute(CD, PC2); CD = permute(CD, KS6); local KEY6 = permute(CD, PC2); CD = permute(CD, KS7); local KEY7 = permute(CD, PC2); CD = permute(CD, KS8); local KEY8 = permute(CD, PC2); CD = permute(CD, KS9); local KEY9 = permute(CD, PC2); CD = permute(CD, KS10); local KEY10 = permute(CD, PC2); CD = permute(CD, KS11); local KEY11 = permute(CD, PC2); CD = permute(CD, KS12); local KEY12 = permute(CD, PC2); CD = permute(CD, KS13); local KEY13 = permute(CD, PC2); CD = permute(CD, KS14); local KEY14 = permute(CD, PC2); CD = permute(CD, KS15); local KEY15 = permute(CD, PC2); CD = permute(CD, KS16); local KEY16 = permute(CD, PC2); --input permutation LR = permute(LR, IN_P); --rounds local frk = mix(LR, KEY1); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end LR = permute(LR, LR_SWAP); frk = mix(LR, KEY2); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end LR = permute(LR, LR_SWAP); frk = mix(LR, KEY3); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end LR = permute(LR, LR_SWAP); frk = mix(LR, KEY4); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end LR = permute(LR, LR_SWAP); frk = mix(LR, KEY5); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end LR = permute(LR, LR_SWAP); frk = mix(LR, KEY6); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end LR = permute(LR, LR_SWAP); frk = mix(LR, KEY7); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end LR = permute(LR, LR_SWAP); frk = mix(LR, KEY8); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end LR = permute(LR, LR_SWAP); frk = mix(LR, KEY9); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end LR = permute(LR, LR_SWAP); frk = mix(LR, KEY10); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end LR = permute(LR, LR_SWAP); frk = mix(LR, KEY11); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end LR = permute(LR, LR_SWAP); frk = mix(LR, KEY12); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end LR = permute(LR, LR_SWAP); frk = mix(LR, KEY13); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end LR = permute(LR, LR_SWAP); frk = mix(LR, KEY14); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end LR = permute(LR, LR_SWAP); frk = mix(LR, KEY15); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end LR = permute(LR, LR_SWAP); frk = mix(LR, KEY16); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end --output permutation LR = permute(LR, OUT_P); local outputBlock = packBytes(LR); return outputBlock; end DES.decrypt = function(keyBlock, inputBlock) local LR = unpackBytes(inputBlock); local keyBits = unpackBytes(keyBlock); local CD = permute(keyBits, PC1); --key schedule CD = permute(CD, KS1); local KEY1 = permute(CD, PC2); CD = permute(CD, KS2); local KEY2 = permute(CD, PC2); CD = permute(CD, KS3); local KEY3 = permute(CD, PC2); CD = permute(CD, KS4); local KEY4 = permute(CD, PC2); CD = permute(CD, KS5); local KEY5 = permute(CD, PC2); CD = permute(CD, KS6); local KEY6 = permute(CD, PC2); CD = permute(CD, KS7); local KEY7 = permute(CD, PC2); CD = permute(CD, KS8); local KEY8 = permute(CD, PC2); CD = permute(CD, KS9); local KEY9 = permute(CD, PC2); CD = permute(CD, KS10); local KEY10 = permute(CD, PC2); CD = permute(CD, KS11); local KEY11 = permute(CD, PC2); CD = permute(CD, KS12); local KEY12 = permute(CD, PC2); CD = permute(CD, KS13); local KEY13 = permute(CD, PC2); CD = permute(CD, KS14); local KEY14 = permute(CD, PC2); CD = permute(CD, KS15); local KEY15 = permute(CD, PC2); CD = permute(CD, KS16); local KEY16 = permute(CD, PC2); --input permutation LR = permute(LR, IN_P); --rounds local frk = mix(LR, KEY16); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end LR = permute(LR, LR_SWAP); frk = mix(LR, KEY15); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end LR = permute(LR, LR_SWAP); frk = mix(LR, KEY14); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end LR = permute(LR, LR_SWAP); frk = mix(LR, KEY13); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end LR = permute(LR, LR_SWAP); frk = mix(LR, KEY12); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end LR = permute(LR, LR_SWAP); frk = mix(LR, KEY11); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end LR = permute(LR, LR_SWAP); frk = mix(LR, KEY10); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end LR = permute(LR, LR_SWAP); frk = mix(LR, KEY9); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end LR = permute(LR, LR_SWAP); frk = mix(LR, KEY8); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end LR = permute(LR, LR_SWAP); frk = mix(LR, KEY7); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end LR = permute(LR, LR_SWAP); frk = mix(LR, KEY6); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end LR = permute(LR, LR_SWAP); frk = mix(LR, KEY5); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end LR = permute(LR, LR_SWAP); frk = mix(LR, KEY4); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end LR = permute(LR, LR_SWAP); frk = mix(LR, KEY3); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end LR = permute(LR, LR_SWAP); frk = mix(LR, KEY2); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end LR = permute(LR, LR_SWAP); frk = mix(LR, KEY1); for k, _ in pairs(frk) do LR[k] = XOR(LR[k], frk[k]); end --output permutation LR = permute(LR, OUT_P); local outputBlock = packBytes(LR); return outputBlock; end return DES;