DES算法详细介绍我就不展开了,但是简略的过程如上。同样,有需要的读者适当考虑读全英文文献[1],或者利用各个社区进行系统的学习。
#include <stdio.h> |
#include <stdlib.h> |
typedef unsigned char Byte; |
typedef unsigned long long Bytes; |
// 为Bytes定义Permutate函数 |
Bytes PermutateBytes(Bytes a, const int b[], int m, int n) { |
Bytes c = 0; |
for (int i = 0; i < n; i++) { |
c = (c << 1) | ((a >> (m - b[i] - 1)) & 1); |
} |
return c; |
} |
// 为Byte定义Permutate函数 |
Byte PermutateByte(Byte a, const Byte b[], int m, int n) { |
Byte c = 0; |
for (int i = 0; i < n; i++) { |
c = (c << 1) | ((a >> (m - b[i] - 1)) & 1); |
} |
return c; |
} |
// 交换两个Bytes类型的值 |
void swap(Bytes *a, Bytes *b) { |
Bytes temp = *a; |
*a = *b; |
*b = temp; |
} |
Bytes IP(Bytes a) { |
static int ip[64] = { |
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, |
56, 48, 40, 32, 24, 16, 8, 0, |
58, 50, 42, 34, 26, 18, 10, 2, |
60, 52, 44, 36, 28, 20, 12, 4, |
62, 54, 46, 38, 30, 22, 14, 6 |
}; |
return PermutateBytes(a, ip, 64, 64); |
} |
Bytes FP(Bytes a) { |
static int fp[64] = { |
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, |
32, 0, 40, 8, 48, 16, 56, 24 |
}; |
return PermutateBytes(a, fp, 64, 64); |
} |
Bytes PC1(Bytes key) { |
static int pc1_l[28] = { |
56, 48, 40, 32, 24, 16, 8, 0, |
57, 49, 41, 33, 25, 17, 9, 1, |
58, 50, 42, 34, 26, 18, 10, 2, |
59, 51, 43, 35 |
}; |
static int pc1_r[28] = { |
62, 54, 46, 38, 30, 22, 14, 6, |
61, 53, 45, 37, 29, 21, 13, 5, |
60, 52, 44, 36, 28, 20, 12, 4, |
27, 19, 11, 3 |
}; |
return (PermutateBytes(key, pc1_l, 64, 28) << 28) | PermutateBytes(key, pc1_r, 64, 28); |
} |
Bytes PC2(Bytes key) { |
static int pc2[48] = { |
13, 16, 10, 23, 0, 4, 2, 27, |
14, 5, 20, 9, 22, 18, 11, 3, |
25, 7, 15, 6, 26, 19, 12, 1, |
40, 51, 30, 36, 46, 54, 29, 39, |
50, 44, 32, 47, 43, 48, 38, 55, |
33, 52, 45, 41, 49, 35, 28, 31 |
}; |
return PermutateBytes(key, pc2, 56, 48); |
} |
Bytes Rotate(Bytes a, int n) { |
for (int i = 0; i < n; i++) |
a = (a << 1 | (a >> 27 & 1)) & ((1 << 28) - 1); |
return a; |
} |
void Keygen(Bytes key, Bytes keys[]) { |
key = PC1(key); |
Bytes l = key >> 28; |
Bytes r = key ^ (l << 28); |
int offset[16] = { |
1, 1, 2, 2, 2, 2, 2, 2, |
1, 2, 2, 2, 2, 2, 2, 1 |
}; |
for (int i = 0; i < 16; i++) { |
l = Rotate(l, offset[i]); |
r = Rotate(r, offset[i]); |
keys[i] = PC2((l << 28) | r); |
} |
} |
Bytes S(Bytes a) { |
static Byte s_box[8][64] = { |
{ |
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 |
}, { |
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 |
}, { |
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 |
}, { |
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 |
}, { |
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 |
}, { |
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 |
}, { |
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 |
}, { |
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 |
} |
}; |
Bytes res = 0; |
static Byte p[6] = {0, 5, 1, 2, 3, 4}; |
for (int i = 0; i < 8; i++) { |
Byte b = (a >> ((7 - i) * 6)) & ((1 << 6) - 1); |
b = PermutateByte(b, p, 6, 6); |
res = (res << 4) | s_box[i][b]; |
} |
return res; |
} |
Bytes P(Bytes a) { |
static int p[32] = { |
15, 6, 19, 20, 28, 11, 27, 16, |
0, 14, 22, 25, 4, 17, 30, 9, |
1, 7, 23, 13, 31, 26, 2, 8, |
18, 12, 29, 5, 21, 10, 3, 24 |
}; |
return PermutateBytes(a, p, 32, 32); |
} |
Bytes Expand(Bytes a) { |
static int e[48] = { |
31, 0, 1, 2, 3, 4, 3, 4, |
5, 6, 7, 8, 7, 8, 9, 10, |
11, 12, 11, 12, 13, 14, 15, 16, |
15, 16, 17, 18, 19, 20, 19, 20, |
21, 22, 23, 24, 23, 24, 25, 26, |
27, 28, 27, 28, 29, 30, 31, 0 |
}; |
return PermutateBytes(a, e, 32, 48); |
} |
Bytes Round(Bytes a, Bytes subkey) { |
Bytes t = Expand(a) ^ subkey; |
t = S(t); |
t = P(t); |
return t; |
} |
Bytes Feistel(Bytes a, Bytes subkey) { |
Bytes l = a >> 32; |
Bytes r = a ^ (l << 32); |
return (r << 32) | (l ^ Round(r, subkey)); |
} |
Bytes DES(Bytes m, Bytes key, int decrypt, int round) { |
Bytes keys[16] = {0}; |
Keygen(key, keys); |
if (decrypt) { |
for (int i = 0; i < 8; i++) |
swap(&keys[i], &keys[15 - i]); |
} |
Bytes c = IP(m); |
for (int i = 0; i < round; i++) |
c = Feistel(c, keys[i]); |
Bytes l = c >> 32; |
Bytes r = c ^ (l << 32); |
return FP((r << 32) | l); |
} |
Bytes Encrypt(Bytes m, int round) { |
return DES(m, 0xcafababedeadbeafULL, 0, round); |
} |
void test() { |
printf("Test rotate: "); |
if (Rotate(167772165, 2) == 134217750) { |
printf("OK.\n"); |
} else { |
printf("GG!\n"); |
} |
printf("Test IP: "); |
if (IP(81985529216486895ULL) == 14699974583363760298ULL) { |
printf("OK.\n"); |
} else { |
printf("GG!\n"); |
} |
printf("Test PC1: "); |
if (PC1(1383827165325090801ULL) == 67779029043144591ULL) { |
printf("OK.\n"); |
} else { |
printf("GG!\n"); |
} |
printf("Test keygen: "); |
Bytes keys[16] = {0}; |
Keygen(1383827165325090801ULL, keys); |
if (keys[15] == 223465186400245ULL) { |
printf("OK.\n"); |
} else { |
printf("GG!\n"); |
} |
printf("Test S box: "); |
if (S(178261171038007ULL) == 3725222752ULL) { |
printf("OK.\n"); |
} else { |
printf("GG!\n"); |
} |
printf("Test round: "); |
if (Round(3707429454ULL, 141493528337059ULL) == 3207079049ULL) { |
printf("OK.\n"); |
} else { |
printf("GG!\n"); |
} |
} |
int main() { |
test(); |
Bytes m = 0x0123456789ABCDEF; |
Bytes k = 0x133457799BBCDFF1; |
// 生成轮密钥 |
Bytes round_keys[16]; |
Keygen(k, round_keys); |
// 执行加密过程并输出每一轮的加密结果和轮密钥 |
Bytes d = m; |
printf("Round 0 - Input: %016llx\n", d); |
for (int i = 0; i < 16; i++) { |
d = DES(d, round_keys[i], 0, i + 1); |
printf("Round %d - Output: %016llx, Round Key: %016llx\n", i + 1, d, round_keys[i]); |
} |
Bytes c = DES(m, k, 0, 16); |
printf("%016llx\n", c); |
printf("%016llx\n", DES(c, k, 1, 16)); |
return 0; |
} |
简单转换为Python了,但是本质上还是C语言的思维在发挥作用。
