include "bin32.s7i";
include "bytedata.s7i";
include "cipher.s7i";
const integer: DES_KS_SIZE is 32;
const type: desSubKeyType is array [DES_KS_SIZE] bin32;
const type: desState is sub noCipherState struct
var desSubKeyType: encryptionSubKey is desSubKeyType.value;
var desSubKeyType: decryptionSubKey is desSubKeyType.value;
var string: cipherBlock is "";
end struct;
type_implements_interface(desState, cipherState);
const func integer: blockSize (DES) is 8;
const func desSubKeyType: setDesKey (in string: desKey) is func
result
var desSubKeyType: subKey is desSubKeyType.value;
local
const array integer: pc1 is [] (
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);
const array integer: pc2 is [] (
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);
const array bin32: bytebit is [] (
bin32(8#200), bin32(8#100), bin32(8#40), bin32(8#20),
bin32(8#10), bin32(8#4), bin32(8#2), bin32(8#1));
const array integer: totrot is [] (
1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28);
var array boolean: pc1m is [0 .. 55] times FALSE;
var array boolean: pcr is [0 .. 55] times FALSE;
var array bin32: ks is [0 .. 7] times bin32.value;
var integer: i is 0;
var integer: j is 0;
var integer: l is 0;
var integer: m is 0;
begin
for j range 0 to 55 do
l := pc1[succ(j)] - 1;
m := succ(l mod 8);
pc1m[j] := (bin32(desKey[succ(l >> 3)]) &
bytebit[m]) <> bin32(0);
end for;
for i range 0 to 15 do
ks := [0 .. 7] times bin32.value;
for j range 0 to 55 do
l := j + totrot[succ(i)];
if j < 28 and l < 28 or j >= 28 and l < 56 then
pcr[j] := pc1m[l];
else
pcr[j] := pc1m[l - 28];
end if;
end for;
for j range 0 to 47 do
if pcr[pc2[succ(j)] - 1] then
l := succ(j rem 6);
ks[j div 6] |:= bytebit[l] >> 2;
end if;
end for;
subKey[2*i + 1] := ks[0] << 24 |
ks[2] << 16 |
ks[4] << 8 |
ks[6];
subKey[2*i + 2] := ks[1] << 24 |
ks[3] << 16 |
ks[5] << 8 |
ks[7];
end for;
end func;
const func desSubKeyType: reverseKeyScheduleOrder (in desSubKeyType: subKey) is func
result
var desSubKeyType: reversedKey is desSubKeyType.value;
local
var integer: i is 0;
begin
for i range 1 to 32 step 2 do
reversedKey[i] := subKey[DES_KS_SIZE - i];
reversedKey[i + 1] := subKey[DES_KS_SIZE - i + 1];
end for;
end func;
const func desState: setDesKey (in string: desKey, in string: initializationVector) is func
result
var desState: state is desState.value;
begin
state.encryptionSubKey := setDesKey(desKey);
state.decryptionSubKey := reverseKeyScheduleOrder(state.encryptionSubKey);
state.cipherBlock := initializationVector;
end func;
const func cipherState: setCipherKey (DES, in string: cipherKey,
in string: initializationVector) is
return toInterface(setDesKey(cipherKey, initializationVector));
const array array bin32: spBox is [] (
[0] (bin32(16#01010400), bin32(16#00000000), bin32(16#00010000), bin32(16#01010404),
bin32(16#01010004), bin32(16#00010404), bin32(16#00000004), bin32(16#00010000),
bin32(16#00000400), bin32(16#01010400), bin32(16#01010404), bin32(16#00000400),
bin32(16#01000404), bin32(16#01010004), bin32(16#01000000), bin32(16#00000004),
bin32(16#00000404), bin32(16#01000400), bin32(16#01000400), bin32(16#00010400),
bin32(16#00010400), bin32(16#01010000), bin32(16#01010000), bin32(16#01000404),
bin32(16#00010004), bin32(16#01000004), bin32(16#01000004), bin32(16#00010004),
bin32(16#00000000), bin32(16#00000404), bin32(16#00010404), bin32(16#01000000),
bin32(16#00010000), bin32(16#01010404), bin32(16#00000004), bin32(16#01010000),
bin32(16#01010400), bin32(16#01000000), bin32(16#01000000), bin32(16#00000400),
bin32(16#01010004), bin32(16#00010000), bin32(16#00010400), bin32(16#01000004),
bin32(16#00000400), bin32(16#00000004), bin32(16#01000404), bin32(16#00010404),
bin32(16#01010404), bin32(16#00010004), bin32(16#01010000), bin32(16#01000404),
bin32(16#01000004), bin32(16#00000404), bin32(16#00010404), bin32(16#01010400),
bin32(16#00000404), bin32(16#01000400), bin32(16#01000400), bin32(16#00000000),
bin32(16#00010004), bin32(16#00010400), bin32(16#00000000), bin32(16#01010004)),
[0] (bin32(16#80108020), bin32(16#80008000), bin32(16#00008000), bin32(16#00108020),
bin32(16#00100000), bin32(16#00000020), bin32(16#80100020), bin32(16#80008020),
bin32(16#80000020), bin32(16#80108020), bin32(16#80108000), bin32(16#80000000),
bin32(16#80008000), bin32(16#00100000), bin32(16#00000020), bin32(16#80100020),
bin32(16#00108000), bin32(16#00100020), bin32(16#80008020), bin32(16#00000000),
bin32(16#80000000), bin32(16#00008000), bin32(16#00108020), bin32(16#80100000),
bin32(16#00100020), bin32(16#80000020), bin32(16#00000000), bin32(16#00108000),
bin32(16#00008020), bin32(16#80108000), bin32(16#80100000), bin32(16#00008020),
bin32(16#00000000), bin32(16#00108020), bin32(16#80100020), bin32(16#00100000),
bin32(16#80008020), bin32(16#80100000), bin32(16#80108000), bin32(16#00008000),
bin32(16#80100000), bin32(16#80008000), bin32(16#00000020), bin32(16#80108020),
bin32(16#00108020), bin32(16#00000020), bin32(16#00008000), bin32(16#80000000),
bin32(16#00008020), bin32(16#80108000), bin32(16#00100000), bin32(16#80000020),
bin32(16#00100020), bin32(16#80008020), bin32(16#80000020), bin32(16#00100020),
bin32(16#00108000), bin32(16#00000000), bin32(16#80008000), bin32(16#00008020),
bin32(16#80000000), bin32(16#80100020), bin32(16#80108020), bin32(16#00108000)),
[0] (bin32(16#00000208), bin32(16#08020200), bin32(16#00000000), bin32(16#08020008),
bin32(16#08000200), bin32(16#00000000), bin32(16#00020208), bin32(16#08000200),
bin32(16#00020008), bin32(16#08000008), bin32(16#08000008), bin32(16#00020000),
bin32(16#08020208), bin32(16#00020008), bin32(16#08020000), bin32(16#00000208),
bin32(16#08000000), bin32(16#00000008), bin32(16#08020200), bin32(16#00000200),
bin32(16#00020200), bin32(16#08020000), bin32(16#08020008), bin32(16#00020208),
bin32(16#08000208), bin32(16#00020200), bin32(16#00020000), bin32(16#08000208),
bin32(16#00000008), bin32(16#08020208), bin32(16#00000200), bin32(16#08000000),
bin32(16#08020200), bin32(16#08000000), bin32(16#00020008), bin32(16#00000208),
bin32(16#00020000), bin32(16#08020200), bin32(16#08000200), bin32(16#00000000),
bin32(16#00000200), bin32(16#00020008), bin32(16#08020208), bin32(16#08000200),
bin32(16#08000008), bin32(16#00000200), bin32(16#00000000), bin32(16#08020008),
bin32(16#08000208), bin32(16#00020000), bin32(16#08000000), bin32(16#08020208),
bin32(16#00000008), bin32(16#00020208), bin32(16#00020200), bin32(16#08000008),
bin32(16#08020000), bin32(16#08000208), bin32(16#00000208), bin32(16#08020000),
bin32(16#00020208), bin32(16#00000008), bin32(16#08020008), bin32(16#00020200)),
[0] (bin32(16#00802001), bin32(16#00002081), bin32(16#00002081), bin32(16#00000080),
bin32(16#00802080), bin32(16#00800081), bin32(16#00800001), bin32(16#00002001),
bin32(16#00000000), bin32(16#00802000), bin32(16#00802000), bin32(16#00802081),
bin32(16#00000081), bin32(16#00000000), bin32(16#00800080), bin32(16#00800001),
bin32(16#00000001), bin32(16#00002000), bin32(16#00800000), bin32(16#00802001),
bin32(16#00000080), bin32(16#00800000), bin32(16#00002001), bin32(16#00002080),
bin32(16#00800081), bin32(16#00000001), bin32(16#00002080), bin32(16#00800080),
bin32(16#00002000), bin32(16#00802080), bin32(16#00802081), bin32(16#00000081),
bin32(16#00800080), bin32(16#00800001), bin32(16#00802000), bin32(16#00802081),
bin32(16#00000081), bin32(16#00000000), bin32(16#00000000), bin32(16#00802000),
bin32(16#00002080), bin32(16#00800080), bin32(16#00800081), bin32(16#00000001),
bin32(16#00802001), bin32(16#00002081), bin32(16#00002081), bin32(16#00000080),
bin32(16#00802081), bin32(16#00000081), bin32(16#00000001), bin32(16#00002000),
bin32(16#00800001), bin32(16#00002001), bin32(16#00802080), bin32(16#00800081),
bin32(16#00002001), bin32(16#00002080), bin32(16#00800000), bin32(16#00802001),
bin32(16#00000080), bin32(16#00800000), bin32(16#00002000), bin32(16#00802080)),
[0] (bin32(16#00000100), bin32(16#02080100), bin32(16#02080000), bin32(16#42000100),
bin32(16#00080000), bin32(16#00000100), bin32(16#40000000), bin32(16#02080000),
bin32(16#40080100), bin32(16#00080000), bin32(16#02000100), bin32(16#40080100),
bin32(16#42000100), bin32(16#42080000), bin32(16#00080100), bin32(16#40000000),
bin32(16#02000000), bin32(16#40080000), bin32(16#40080000), bin32(16#00000000),
bin32(16#40000100), bin32(16#42080100), bin32(16#42080100), bin32(16#02000100),
bin32(16#42080000), bin32(16#40000100), bin32(16#00000000), bin32(16#42000000),
bin32(16#02080100), bin32(16#02000000), bin32(16#42000000), bin32(16#00080100),
bin32(16#00080000), bin32(16#42000100), bin32(16#00000100), bin32(16#02000000),
bin32(16#40000000), bin32(16#02080000), bin32(16#42000100), bin32(16#40080100),
bin32(16#02000100), bin32(16#40000000), bin32(16#42080000), bin32(16#02080100),
bin32(16#40080100), bin32(16#00000100), bin32(16#02000000), bin32(16#42080000),
bin32(16#42080100), bin32(16#00080100), bin32(16#42000000), bin32(16#42080100),
bin32(16#02080000), bin32(16#00000000), bin32(16#40080000), bin32(16#42000000),
bin32(16#00080100), bin32(16#02000100), bin32(16#40000100), bin32(16#00080000),
bin32(16#00000000), bin32(16#40080000), bin32(16#02080100), bin32(16#40000100)),
[0] (bin32(16#20000010), bin32(16#20400000), bin32(16#00004000), bin32(16#20404010),
bin32(16#20400000), bin32(16#00000010), bin32(16#20404010), bin32(16#00400000),
bin32(16#20004000), bin32(16#00404010), bin32(16#00400000), bin32(16#20000010),
bin32(16#00400010), bin32(16#20004000), bin32(16#20000000), bin32(16#00004010),
bin32(16#00000000), bin32(16#00400010), bin32(16#20004010), bin32(16#00004000),
bin32(16#00404000), bin32(16#20004010), bin32(16#00000010), bin32(16#20400010),
bin32(16#20400010), bin32(16#00000000), bin32(16#00404010), bin32(16#20404000),
bin32(16#00004010), bin32(16#00404000), bin32(16#20404000), bin32(16#20000000),
bin32(16#20004000), bin32(16#00000010), bin32(16#20400010), bin32(16#00404000),
bin32(16#20404010), bin32(16#00400000), bin32(16#00004010), bin32(16#20000010),
bin32(16#00400000), bin32(16#20004000), bin32(16#20000000), bin32(16#00004010),
bin32(16#20000010), bin32(16#20404010), bin32(16#00404000), bin32(16#20400000),
bin32(16#00404010), bin32(16#20404000), bin32(16#00000000), bin32(16#20400010),
bin32(16#00000010), bin32(16#00004000), bin32(16#20400000), bin32(16#00404010),
bin32(16#00004000), bin32(16#00400010), bin32(16#20004010), bin32(16#00000000),
bin32(16#20404000), bin32(16#20000000), bin32(16#00400010), bin32(16#20004010)),
[0] (bin32(16#00200000), bin32(16#04200002), bin32(16#04000802), bin32(16#00000000),
bin32(16#00000800), bin32(16#04000802), bin32(16#00200802), bin32(16#04200800),
bin32(16#04200802), bin32(16#00200000), bin32(16#00000000), bin32(16#04000002),
bin32(16#00000002), bin32(16#04000000), bin32(16#04200002), bin32(16#00000802),
bin32(16#04000800), bin32(16#00200802), bin32(16#00200002), bin32(16#04000800),
bin32(16#04000002), bin32(16#04200000), bin32(16#04200800), bin32(16#00200002),
bin32(16#04200000), bin32(16#00000800), bin32(16#00000802), bin32(16#04200802),
bin32(16#00200800), bin32(16#00000002), bin32(16#04000000), bin32(16#00200800),
bin32(16#04000000), bin32(16#00200800), bin32(16#00200000), bin32(16#04000802),
bin32(16#04000802), bin32(16#04200002), bin32(16#04200002), bin32(16#00000002),
bin32(16#00200002), bin32(16#04000000), bin32(16#04000800), bin32(16#00200000),
bin32(16#04200800), bin32(16#00000802), bin32(16#00200802), bin32(16#04200800),
bin32(16#00000802), bin32(16#04000002), bin32(16#04200802), bin32(16#04200000),
bin32(16#00200800), bin32(16#00000000), bin32(16#00000002), bin32(16#04200802),
bin32(16#00000000), bin32(16#00200802), bin32(16#04200000), bin32(16#00000800),
bin32(16#04000002), bin32(16#04000800), bin32(16#00000800), bin32(16#00200002)),
[0] (bin32(16#10001040), bin32(16#00001000), bin32(16#00040000), bin32(16#10041040),
bin32(16#10000000), bin32(16#10001040), bin32(16#00000040), bin32(16#10000000),
bin32(16#00040040), bin32(16#10040000), bin32(16#10041040), bin32(16#00041000),
bin32(16#10041000), bin32(16#00041040), bin32(16#00001000), bin32(16#00000040),
bin32(16#10040000), bin32(16#10000040), bin32(16#10001000), bin32(16#00001040),
bin32(16#00041000), bin32(16#00040040), bin32(16#10040040), bin32(16#10041000),
bin32(16#00001040), bin32(16#00000000), bin32(16#00000000), bin32(16#10040040),
bin32(16#10000040), bin32(16#10001000), bin32(16#00041040), bin32(16#00040000),
bin32(16#00041040), bin32(16#00040000), bin32(16#10041000), bin32(16#00001000),
bin32(16#00000040), bin32(16#10040040), bin32(16#00001000), bin32(16#00041040),
bin32(16#10001000), bin32(16#00000040), bin32(16#10000040), bin32(16#10040000),
bin32(16#10040040), bin32(16#10000000), bin32(16#00040000), bin32(16#10001040),
bin32(16#00000000), bin32(16#10041040), bin32(16#00040040), bin32(16#10000040),
bin32(16#10040000), bin32(16#10001000), bin32(16#10001040), bin32(16#00000000),
bin32(16#10041040), bin32(16#00041000), bin32(16#00041000), bin32(16#00001040),
bin32(16#00001040), bin32(16#00040040), bin32(16#10000000), bin32(16#10041000)));
const proc: initialPermutation (inout bin32: left, inout bin32: right) is func
local
var bin32: work is bin32.value;
begin
right := rotLeft(right, 4);
work := (left >< right) & bin32(16#f0f0f0f0);
left ><:= work;
right := rotRight(right >< work, 20);
work := (left >< right) & bin32(16#ffff0000);
left ><:= work;
right := rotRight(right >< work, 18);
work := (left >< right) & bin32(16#33333333);
left ><:= work;
right := rotRight(right >< work, 6);
work := (left >< right) & bin32(16#00ff00ff);
left ><:= work;
right := rotLeft(right >< work, 9);
work := (left >< right) & bin32(16#aaaaaaaa);
left := rotLeft(left >< work, 1);
right ><:= work;
end func;
const proc: finalPermutation (inout bin32: left, inout bin32: right) is func
local
var bin32: work is bin32.value;
begin
right := rotRight(right, 1);
work := (left >< right) & bin32(16#aaaaaaaa);
left := rotRight(left >< work, 9);
right ><:= work;
work := (left >< right) & bin32(16#00ff00ff);
left := rotLeft(left >< work, 6);
right ><:= work;
work := (left >< right) & bin32(16#33333333);
left := rotLeft(left >< work, 18);
right ><:= work;
work := (left >< right) & bin32(16#ffff0000);
left := rotLeft(left >< work, 20);
right ><:= work;
work := (left >< right) & bin32(16#f0f0f0f0);
left := rotRight(left >< work, 4);
right ><:= work;
end func;
const func string: processDesBlock (in desSubKeyType: subKey, in string: inData) is func
result
var string: outData is "";
local
var bin32: left is bin32.value;
var bin32: right is bin32.value;
var integer: work is 0;
var integer: idx is 0;
begin
left := bin32(bytes2Int(inData[1 fixLen 4], UNSIGNED, BE));
right := bin32(bytes2Int(inData[5 fixLen 4], UNSIGNED, BE));
initialPermutation(left, right);
for idx range 1 to 8 do
work := ord(rotRight(right, 4) >< subKey[4 * idx - 3]);
left ><:= spBox[7][ work mod 64] ><
spBox[5][(work >> 8) mod 64] ><
spBox[3][(work >> 16) mod 64] ><
spBox[1][(work >> 24) mod 64];
work := ord(right >< subKey[4 * idx - 2]);
left ><:= spBox[8][ work mod 64] ><
spBox[6][(work >> 8) mod 64] ><
spBox[4][(work >> 16) mod 64] ><
spBox[2][(work >> 24) mod 64];
work := ord(rotRight(left, 4) >< subKey[4 * idx - 1]);
right ><:= spBox[7][ work mod 64] ><
spBox[5][(work >> 8) mod 64] ><
spBox[3][(work >> 16) mod 64] ><
spBox[1][(work >> 24) mod 64];
work := ord(left >< subKey[4 * idx]);
right ><:= spBox[8][ work mod 64] ><
spBox[6][(work >> 8) mod 64] ><
spBox[4][(work >> 16) mod 64] ><
spBox[2][(work >> 24) mod 64];
end for;
finalPermutation(left, right);
outData := bytes(ord(right), UNSIGNED, BE, 4) &
bytes(ord(left), UNSIGNED, BE, 4);
end func;
const func string: encode (inout desState: state, in string: plaintext) is func
result
var string: encoded is "";
local
var integer: index is 0;
var integer: subIndex is 0;
var string: dataBlock is "";
var string: cipherBlock is "";
begin
for index range 1 to length(plaintext) step blockSize(DES) do
dataBlock := "";
for subIndex range 1 to blockSize(DES) do
dataBlock &:= chr(ord(bin32(plaintext[pred(index + subIndex)]) ><
bin32(state.cipherBlock[subIndex])));
end for;
cipherBlock := processDesBlock(state.encryptionSubKey, dataBlock);
state.cipherBlock := cipherBlock;
encoded &:= cipherBlock;
end for;
end func;
const func string: decode (inout desState: state, in string: encoded) is func
result
var string: plaintext is "";
local
var integer: index is 0;
var integer: subIndex is 0;
var string: cipherBlock is "";
var string: dataBlock is "";
var string: plainBlock is "";
begin
for index range 1 to length(encoded) step blockSize(DES) do
cipherBlock := encoded[index fixLen blockSize(DES)];
dataBlock := processDesBlock(state.decryptionSubKey, cipherBlock);
for subIndex range 1 to blockSize(DES) do
plaintext &:= chr(ord(bin32(dataBlock[subIndex]) ><
bin32(state.cipherBlock[subIndex])));
end for;
state.cipherBlock := cipherBlock;
end for;
end func;