-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added new module for DES encryption/decryption
- Loading branch information
1 parent
50a3e66
commit 2b66fbd
Showing
1 changed file
with
333 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,333 @@ | ||
// Written in the D programming language. | ||
|
||
/** | ||
This class provides an implementation of the DES cryptoalgorithm. | ||
Implementation is based on the following code (by Daniel Huertas Gonzalez): https://github.com/dhuertas/DES/blob/master/des.c | ||
Copyright: LightHouse Software, 2023 | ||
License: $(HTTP https://github.com/aquaratixc/ESL-License, Experimental Software License 1.0). | ||
Authors: Oleg Bakharev, | ||
Daniel Huertas Gonzalez | ||
See also: | ||
https://en.wikipedia.org/wiki/Data_Encryption_Standard, FIPS PUB 46-3 | ||
*/ | ||
module styx2000.protosrv.des; | ||
|
||
/// DES functional mode: encryption or decryption | ||
enum CRYPTOPERATION | ||
{ | ||
/// encrypt with DES | ||
ENCRYPT, | ||
/// decrypt with DES | ||
DECRYPT | ||
} | ||
|
||
|
||
/// DES algorith implementation | ||
class DES | ||
{ | ||
private { | ||
enum LB32_MASK = 0x00000001; | ||
enum LB64_MASK = 0x0000000000000001; | ||
enum L64_MASK = 0x00000000ffffffff; | ||
enum H64_MASK = 0xffffffff00000000; | ||
} | ||
|
||
private { | ||
/* Initial Permutation Table */ | ||
static char[] IP = [ | ||
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 | ||
]; | ||
|
||
/* Inverse Initial Permutation Table */ | ||
static char[] PI = [ | ||
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 | ||
]; | ||
|
||
/* Expansion table */ | ||
static char[] E = [ | ||
32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9, 10, 11, 12, 13, 12, 13, 14, 15, | ||
16, 17, 16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25, 24, 25, 26, 27, | ||
28, 29, 28, 29, 30, 31, 32, 1 | ||
]; | ||
|
||
/* Post S-Box permutation */ | ||
static char[] 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 | ||
]; | ||
|
||
/* The S-Box tables */ | ||
static char[64][8] S = [ | ||
[ | ||
/* S1 */ | ||
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 | ||
], | ||
[ | ||
/* S2 */ | ||
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 | ||
], | ||
[ | ||
/* S3 */ | ||
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 | ||
], | ||
[ | ||
/* S4 */ | ||
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 | ||
], | ||
[ | ||
/* S5 */ | ||
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 | ||
], | ||
[ | ||
/* S6 */ | ||
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 | ||
], | ||
[ | ||
/* S7 */ | ||
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 | ||
], | ||
[ | ||
/* S8 */ | ||
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 | ||
] | ||
]; | ||
|
||
/* Permuted Choice 1 Table */ | ||
static char[] 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 | ||
]; | ||
|
||
/* Permuted Choice 2 Table */ | ||
static char[] 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 | ||
]; | ||
|
||
/* Iteration Shift Array */ | ||
static char[] iteration_shift = [ | ||
/* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 */ | ||
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 | ||
]; | ||
} | ||
|
||
|
||
/** | ||
Method for encryption or decryption of one elementary block (block size - 64 bit, key size - 64 bit). | ||
Params: | ||
input = Elementary block for encrypt/decrypt with DES. | ||
key = Key for encrypt/decrypt | ||
mode = Type of operation mode of DES class - encryption or decryption | ||
*/ | ||
static ulong des(ulong input, ulong key, CRYPTOPERATION mode) | ||
{ | ||
/* 8 bits */ | ||
char row, column; | ||
|
||
/* 28 bits */ | ||
uint C = 0; | ||
uint D = 0; | ||
|
||
/* 32 bits */ | ||
uint L = 0; | ||
uint R = 0; | ||
uint s_output = 0; | ||
uint f_function_res = 0; | ||
uint temp = 0; | ||
|
||
/* 48 bits */ | ||
ulong[16] sub_key = 0; | ||
ulong s_input = 0; | ||
|
||
/* 56 bits */ | ||
ulong permuted_choice_1 = 0; | ||
ulong permuted_choice_2 = 0; | ||
|
||
/* 64 bits */ | ||
ulong init_perm_res = 0; | ||
ulong inv_init_perm_res = 0; | ||
ulong pre_output = 0; | ||
|
||
/* initial permutation */ | ||
for (int i = 0; i < 64; i++) | ||
{ | ||
init_perm_res <<= 1; | ||
init_perm_res |= (input >> (64 - IP[i])) & LB64_MASK; | ||
} | ||
|
||
L = cast(uint)(init_perm_res >> 32) & L64_MASK; | ||
R = cast(uint) init_perm_res & L64_MASK; | ||
|
||
/* initial key schedule calculation */ | ||
for (int i = 0; i < 56; i++) | ||
{ | ||
permuted_choice_1 <<= 1; | ||
permuted_choice_1 |= (key >> (64 - PC1[i])) & LB64_MASK; | ||
} | ||
|
||
C = cast(uint)((permuted_choice_1 >> 28) & 0x000000000fffffff); | ||
D = cast(uint)(permuted_choice_1 & 0x000000000fffffff); | ||
|
||
/* Calculation of the 16 keys */ | ||
for (int i = 0; i < 16; i++) | ||
{ | ||
/* key schedule */ | ||
// shifting Ci and Di | ||
for (int j = 0; j < iteration_shift[i]; j++) | ||
{ | ||
C = 0x0fffffff & (C << 1) | 0x00000001 & (C >> 27); | ||
D = 0x0fffffff & (D << 1) | 0x00000001 & (D >> 27); | ||
} | ||
|
||
permuted_choice_2 = 0; | ||
permuted_choice_2 = ((cast(ulong) C) << 28) | cast(ulong) D; | ||
|
||
sub_key[i] = 0; | ||
|
||
for (int j = 0; j < 48; j++) | ||
{ | ||
sub_key[i] <<= 1; | ||
sub_key[i] |= (permuted_choice_2 >> (56 - PC2[j])) & LB64_MASK; | ||
} | ||
|
||
} | ||
|
||
for (int i = 0; i < 16; i++) | ||
{ | ||
/* f(R,k) function */ | ||
s_input = 0; | ||
|
||
for (int j = 0; j < 48; j++) | ||
{ | ||
s_input <<= 1; | ||
s_input |= cast(ulong)((R >> (32 - E[j])) & LB32_MASK); | ||
} | ||
|
||
/* | ||
* Encryption/Decryption | ||
* XORing expanded Ri with Ki | ||
*/ | ||
final switch (mode) with (CRYPTOPERATION) | ||
{ | ||
case ENCRYPT: | ||
s_input = s_input ^ sub_key[i]; | ||
break; | ||
case DECRYPT: | ||
s_input = s_input ^ sub_key[15 - i]; | ||
break; | ||
} | ||
|
||
/* S-Box Tables */ | ||
for (int j = 0; j < 8; j++) | ||
{ | ||
// 00 00 RCCC CR00 00 00 00 00 00 s_input | ||
// 00 00 1000 0100 00 00 00 00 00 row mask | ||
// 00 00 0111 1000 00 00 00 00 00 column mask | ||
|
||
row = cast(char) ((s_input & (0x0000840000000000 >> 6 * j)) >> 42 - 6 * j); | ||
row = (row >> 4) | row & 0x01; | ||
|
||
column = cast(char) ((s_input & (0x0000780000000000 >> 6 * j)) >> 43 - 6 * j); | ||
|
||
s_output <<= 4; | ||
s_output |= cast(uint) (S[j][16 * row + column] & 0x0f); | ||
} | ||
|
||
f_function_res = 0; | ||
|
||
for (int j = 0; j < 32; j++) | ||
{ | ||
f_function_res <<= 1; | ||
f_function_res |= (s_output >> (32 - P[j])) & LB32_MASK; | ||
} | ||
|
||
temp = R; | ||
R = L ^ f_function_res; | ||
L = temp; | ||
} | ||
|
||
pre_output = ((cast(ulong) R) << 32) | cast(ulong) L; | ||
|
||
/* inverse initial permutation */ | ||
for (int i = 0; i < 64; i++) | ||
{ | ||
inv_init_perm_res <<= 1; | ||
inv_init_perm_res |= (pre_output >> (64 - PI[i])) & LB64_MASK; | ||
} | ||
|
||
return inv_init_perm_res; | ||
} | ||
} | ||
|
||
unittest { | ||
enum ulong[16] TESTING_VECTOR = [ | ||
0x8da744e0c94e5e17, | ||
0x0cdb25e3ba3c6d79, | ||
0x4784c4ba5006081f, | ||
0x1cf1fc126f2ef842, | ||
0xe4be250042098d13, | ||
0x7bfc5dc6adb5797c, | ||
0x1ab3b4d82082fb28, | ||
0xc1576a14de707097, | ||
0x739b68cd2e26782a, | ||
0x2a59f0c464506edb, | ||
0xa5c39d4251f0a81e, | ||
0x7239ac9a6107ddb1, | ||
0x070cac8590241233, | ||
0x78f87b6e3dfecf61, | ||
0x95ec2578c2c433f0, | ||
0x1b1a2ddb4c642438, | ||
]; | ||
|
||
ulong input = 0x9474B8E8C73BCA7D; | ||
ulong key = 0x0000000000000000; | ||
ulong result = input; | ||
|
||
ulong[16] vector; | ||
|
||
for (int i = 0; i < 16; i++) | ||
{ | ||
if (i % 2 == 0) | ||
{ | ||
result = DES.des(result, result, CRYPTOPERATION.ENCRYPT); | ||
} | ||
else | ||
{ | ||
result = DES.des(result, result, CRYPTOPERATION.DECRYPT); | ||
} | ||
|
||
vector[i] = result; | ||
} | ||
|
||
assert(vector == TESTING_VECTOR); | ||
assert(result == 0x1b1a2ddb4c642438); | ||
} |