DES加密总结

二木 王者

DES加密

总览图

Untitled

关于密钥生成

Untitled

Untitled

总体的流程就是 进行置换1→分组→ 根据轮数进行循环左移→压缩置换(将56比特的数据转换为48比特)→得到密钥(k1) →将未进行的压缩转置的密钥进行循环左移——>压缩转置→…………….一直循环16轮生成我们的k1 — k16的密钥

**初始密钥,置换选择1(PC1)—>轮密钥生成(**接下来,根据中间密钥生成 16 个子密钥,每个子密钥都是 48 位长。,涉及到循环移位和置换选择2(PC2)操作)—>置换选择2(PC2)→密钥

初始密钥,置换选择1(PC1)

首先我们的密钥是64bit的,但是在运算的时候要将每个字节的最后一位做奇偶校验,使用在进行置换一的时候,实际用到的是56bit的数据

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int initial_key[56] = {
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
};

// 生成56位的中间密钥,48位有效位
void generate_middle_key(int *initial_key, int *middle_key) {
for (int i = 0; i < 48; i++) {
middle_key[i] = initial_key[i];
}
}

轮密钥生成

循环移位

之后就是进行分组分为c与d两个组,两个组分别有28个字节,之后便会进行循环左移,具体的左移位数会因轮数的改变而改变,如下

Untitled

这样之后,得到的c,d两个组c,d合并起来的56字节,继续循环位移下去,生成下一个56字节组,这样一直循环16轮

置换选择2

将上面每一轮生成的56字节组,进行压缩置换,变成48字节的数据,就是根据pc2盒,取其特殊的位,重新组成48字节组

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
int PC2[] = {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};

// 压缩置换函数
void compress_permutation(char *key, char *compressed_key) {
for (int i = 0; i < 48; i++) {
compressed_key[i] = key[PC2[i]];
}
compressed_key[48] = '\0'; // 添加字符串结束符

这样将16轮的数据都转置压缩一遍,就变成了我们k1—k16的密钥

数据加密

Untitled

Untitled

明文初始操作

首先会将我们的明文以64比特为一组进行分组,每8字节为一组进行加密,一般我们输入的都是字符串,因此会将我们的字节位存储转换位比特位存储,便于操作就将我们的一0,1,作为数组进行存储

一道题的初始部分:

Untitled

IP置换操作

所谓Ip置换操作,就是按照规则将我们的数据重新排序

Untitled

这样的规则就是通过使用一个特定的S盒,有着我们特定的位,会将我们原来64比特数据按照这个位进行打乱。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 初始置换表
int 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};

// 初始置换函数
void initial_permutation(char *block, char *permuted_block) {
for (int i = 0; i < 64; i++) {
permuted_block[i] = block[IP[i] - 1];
}
permuted_block[64] = '\0'; // 添加字符串结束符
}

这样进行置换之后,会将我们的数据分为前32字节L与后32字节R两个组,之后便会进入16轮的迭代操作

16轮的循环迭代操作

对于我们R组

首先会将我们的R组进行保存,后面在轮换会用到

E扩展(将32字节扩展为48字节)

Untitled

将我们32字节的数据,以4个字节为一组,一共为8个组,E扩展就是在4字节的前后各加一位,加的规则就是将前一组的最后一位加在第一位,将后一组的第一位加在最后一位(第一组和最后一组是联通的)

举个例子:

0111 0110 1001

中间的一组0110进行E扩展之后,得到的数据就是101101

异或密钥

得到的48比特数据会与我们前计算出来的key进行异或

s盒转置压缩

Untitled

具体的s盒的压缩规则就如图一样,会将我们异或后的48比特数据拆解,将首尾数据两个合并起来转换位十进制数据,以此作为行数,之后会将我们中间的四位数据转换位十进制数据,作为列数,以此通过行数与列数,去S盒寻找指定的数据,然后再将数据转换位四位的二进制数据,这样就将我们的数据从48位变成了32位的数据

我们的S盒是一个3D的数据盒子

Untitled

p置换

所谓p置换很简单,就是对于一个P盒,将我们的32位数据,在p盒中进行查表,将数据进行替换

Untitled

R组L组异或

之后便会进行R组与L组的异或,异或的结果作为我们下一轮加密的R组,此时对于前面我们保存的R组,将其作为下一轮的L组

于是进行16轮

ip-1逆置换

16轮加密之后,会将我们的L组与R组合并在一起重新变成64位的数据。

初始置换 IP 的逆操作,用于将加密后的数据重新排列回加密前的顺序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 // IP-1 逆置换表
int ip_inverse_table[64] = {
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
};

for (int i = 0; i < 64; i++) {
output[i] = input[ip_inverse_table[i] - 1];
}
output[64] = '\0'; // 添加字符串结束符
}

完成加密

至此就完成了我们的一组的加密,后面就是将我们其他组的数据执行同样的加密即可

参考:

推荐看一看b站这个up讲的DES讲得非常透彻

【DES加密算法|密码学|信息安全】https://www.bilibili.com/video/BV1KQ4y127AT?vd_source=846c33f9f29e2cfb066d13b25ccac283

DES加密算法实现 - 知乎 (zhihu.com)

 评论