# DES加密算法实现
**Repository Path**: Chenwzh/DES
## Basic Information
- **Project Name**: DES加密算法实现
- **Description**: DES加密算法实现(C++)
- **Primary Language**: C++
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 10
- **Forks**: 2
- **Created**: 2018-11-01
- **Last Updated**: 2023-11-06
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
## 一、算法简介
DES全称为Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法,1977年被美国国家标准局(NBS)确定为联邦信息处理标准(FIPS),并授权在非密级政府通信中使用,随后该算法在国际上广泛流传开来。
DES是基于56位密钥的对称算法,由于它使用的56位密钥过短,目前已经不被视为一种安全的加密算法。当然你也可以使用DES的派生算法3DES来进行加密,提高破解的难度。
2001年,DES被高级加密标准(AES)所取代。另外,DES已经不作为NIST的标准。
## 二、算法原理概述
### 1. 算法基本概念
明文以字节为基本单位,将明文分成每8字节一组,即64位,如果明文最后的分组不够64位,按照PKCS#5规范进行填充,如最后一组只有2字节,那么在末尾补上6个字节,每个字节取值均为06,如果刚刚分组完全,则在末尾添加8个字节,字节取值均为08。
密钥K以位为基本单位,密钥长64位,与明文分组一样长,但密钥因为存在8位奇偶校验位,实际起作用的只有56位,密钥需要加密解密双方均知道才可以进行加密解密。
### 2. 算法总体结构
以下明文、密文长均为64位,加密或解密后需手动组装起来
* 加密过程
* C = DES(M) = ${IP}^{-1}$ * W * $T_{16}$ * $T_{15} $ * ... * $T_{1}$ * $IP$ (M)
* M为64位明文,C为64位密文
* IP为初始置换
* $IP^{-1}$ 为IP的逆置换
* $T_{16}$ * $T_{15} $ * ... * $T_1$ 为16轮迭代T,由密钥得出
* W为前后置换,将64位的前32位与后32位交换位置
* 解密过程
* M = DeDES(C)= ${IP}^{-1}$ * W * $T_1$ * ... * $T_{15} $ * $T_{16}$ * $IP$ (C)
### 3. 初始置换IP
IP是64位的置换表,代码中表现为64位数组。其中第0位上的数为58,**表示为新得到的64位串的第0位是原来的第57位(注意是57位而不是58位,因为数组上的数只有1-64,并不是0-63,所以要相对应减1,后面的所有置换表均如此)**,新得到的64位串表示位$L_0$$R_0$,分别代表前32位(即低32位)和后32位(即高32位)。置换表在代码中给出。
### 4. 逆置换$IP^{-1}$
同上,置换表也在代码中给出。
### 5. 16轮T迭代
这是最复杂的一个环节
#### (1)第k轮迭代
$L_i$ = $R_{i-1}$ , $R_i$ = $L_{i-1}$ $\bigoplus$ $f$($R_{i-1}$,$k_i$),$i$ = 1, 2, ... , 16
**注:解密过程是反过来的,即i是递减使用的**
* $f$是输出32位的Feistel轮函数
* $k_i$长48位,是由密钥K生成的字密钥,共16个
#### (2)字密钥$k_i$生成
* 对K的56位非校验位进行PC-1置换,PC-1置换表共56位,得到$C_0$$D_0$,分别为前28位和后28位,$i$ = 1
* 计算$C_i$ = L$S_i$($C_{i-1}$)和$D_i$ = L$S_i$($D_{i-1}$)
* 当i为1,2,9,16时,L$S_i$(A)表示将二进制串A左移一位,否则,左移两位
* 对56位的$C_i$$D_i$进行PC-2置换,得到48位的$k_i$.PC-2置换表共48位,置换表在代码中给出
* 循环得到所有字密钥
#### (3)Feistel轮函数$f$($R_{i-1}$,$k_i$)
* 将长度位32位的串$R_{i-1}$进行E-扩展,成为48位的串E($R_{i-1}$),E-扩展所需要的置换表在代码中给出
* 将E($R_{i-1}$)和长度位48位的字密钥$k_i$做二进制的异或运算,$k_i$前面已算出
* 将上一步得到的48位结果分成8个分组,每个分组长度为6位
* 将8个分组分别经过8个不同的**S-盒**($S_1$$S_2$...$S_8$)进行6-4转换,得到8个长度为4位的分组,分组位越低使用的S-盒下标也小,此处是一一对应的,S-盒的转换规则稍后给出
* 将上一步得到的结果按顺序连接在一起得到长度为32位的串
* 将上一步的结果经过P-置换,得到新的32位串,作为$f$($R_{i-1}$,$k_i$) 的返回值。P置换表共32位,代码中给出
#### (4)S-盒转换
每个S-盒均为4行16列的矩阵,矩阵内数据为0-15,可变为二进制串0000-1111。输入的数有6bit,经过转化之后返回4bit。
例:S1为刚刚48位串的最低6位,为“1111001”,自然得使用$S_1$盒。令row = $(11)_{10}$ = 3,其中,高位1为$S_1$的最高位,低位1为$S_1$的最低位。令col = $(1100)_{10}$ = 12,这4个位为中间剩下的4个位。查找$S_1$盒,${[S_1]_{3,12}}$则为输出的四位。注意:3代表的是第4行,因为矩阵下标从0开始,同理12代表13列
8个S-盒的矩阵在代码中给出。
## 三、代码实现模块及结构
此代码支持**中英文**的加密解密,具体代码请看代码文件:data.hpp存放各个置换表,des.cpp是具体实现文件
### (1)自定义结构体代表二进制
```C++
typedef struct data64
{
bitset<64> bits;
}datas_64;
typedef struct data56
{
bitset<56> bits;
}datas_56;
//还有其他不同位数的结构体
```
### (2)声明函数模块
```C++
void init_secret_key(); //初始化密钥
void init_K_i(datas_64 secret_key);//初始化子密钥ki
string RKCS_fill(string str); //RKCS#5补齐8个字节
vector string_to_binary(string str); //将字符串转化为二进制数
string binary_to_string(vector v); //将二进制数转化为字符串
vector encryption(vector v); //所有数据的加密算法,第二个参数为密钥
vector Decrypt(vector v); //所有数据的解密算法,第二个参数为密钥
datas_64 byte_encryption(datas_64 v); //64位的加密算法
datas_64 byte_Decrypt(datas_64 v); //64位的解密算法
datas_64 IP(datas_64 v); //IP置换
datas_64 IP_inverse(datas_64 v); //IP的逆置换
datas_64 W(datas_64 v); //W操作
datas_64 T_iteration(datas_64 v, datas_48* K); //16次T迭代,注意,算法最后的左右交换输出就是W操作,在这里不写,不要重复!!
datas_64 T_iteration_inverse(datas_64 v, datas_48* K); //16次T的逆迭代,算法最后的左右交换输出就是W操作,在这里不写,不要重复!!
datas_32 Feistel(datas_32 R, datas_48 K); //Feistel轮函数
datas_48 E_extend(datas_32 v); //E-扩展
datas_32 S_box_change(datas_48 v); //s盒6-4转化,48位转位32位
//6-4转化,输入一个6位,输出一个4位,index位第index个S-BOX
datas_4 find_in_Sbox(int index, datas_6 v);
datas_32 P(datas_32 v); //Feistel轮函数中的P置换
```
### (3)main函数
```C++
int main(){
init_secret_key();
init_K_i(secret_key);
string Plaintext = "";
char c;
cout << "输入明文: ";
while((c = cin.get()) != '\n'){
Plaintext += c;
}
Plaintext = RKCS_fill(Plaintext);
vector v = string_to_binary(Plaintext);
vector data1 = encryption(v);
cout << "密文: " << binary_to_string(data1) << endl;
vector data2 = Decrypt(data1);
cout << "解密后明文: " << binary_to_string(data2) << endl;
return 0;
}
```
## 四、实验结果
* 输入随机中文

* 输入随机英文

* 中英混合
