DES加密算法实现

点击获取完整源代码

一、算法简介

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) = I P 1 {IP}^{-1} * W * T 16 T_{16} * T 15 T_{15} * … * T 1 T_{1} * I P IP (M)
      • M为64位明文,C为64位密文
      • IP为初始置换
      • I P 1 IP^{-1} 为IP的逆置换
      • T 16 T_{16} * $T_{15} $ * … * T 1 T_1 为16轮迭代T,由密钥得出
      • W为前后置换,将64位的前32位与后32位交换位置
  • 解密过程
    • M = DeDES(C)= I P 1 {IP}^{-1} * W * T 1 T_1 * … * T 15 T_{15} * T 16 T_{16} * I P IP (C)

3. 初始置换IP

IP是64位的置换表,代码中表现为64位数组。其中第0位上的数为58,表示为新得到的64位串的第0位是原来的第57位(注意是57位而不是58位,因为数组上的数只有1-64,并不是0-63,所以要相对应减1,后面的所有置换表均如此),新得到的64位串表示位 L 0 L_0 R 0 R_0 ,分别代表前32位(即低32位)和后32位(即高32位)。置换表在代码中给出。

4. 逆置换 I P 1 IP^{-1}

同上,置换表也在代码中给出。

5. 16轮T迭代

这是最复杂的一个环节

(1)第k轮迭代

L i L_i = R i 1 R_{i-1} , R i R_i = L i 1 L_{i-1} \bigoplus f f ( R i 1 R_{i-1} , k i k_i ), i i = 1, 2, … , 16

注:解密过程是反过来的,即i是递减使用的

  • f f 是输出32位的Feistel轮函数
  • k i k_i 长48位,是由密钥K生成的字密钥,共16个

(2)字密钥 k i k_i 生成

  • 对K的56位非校验位进行PC-1置换,PC-1置换表共56位,得到 C 0 C_0 D 0 D_0 ,分别为前28位和后28位, i i = 1
  • 计算 C i C_i = L S i S_i ( C i 1 C_{i-1} )和 D i D_i = L S i S_i ( D i 1 D_{i-1} )
    • 当i为1,2,9,16时,L S i S_i (A)表示将二进制串A左移一位,否则,左移两位
  • 对56位的 C i C_i D i D_i 进行PC-2置换,得到48位的 k i k_i .PC-2置换表共48位,置换表在代码中给出
  • 循环得到所有字密钥

(3)Feistel轮函数 f f ( R i 1 R_{i-1} , k i k_i )

  • 将长度位32位的串 R i 1 R_{i-1} 进行E-扩展,成为48位的串E( R i 1 R_{i-1} ),E-扩展所需要的置换表在代码中给出
  • 将E( R i 1 R_{i-1} )和长度位48位的字密钥 k i k_i 做二进制的异或运算, k i k_i 前面已算出
  • 将上一步得到的48位结果分成8个分组,每个分组长度为6位
  • 将8个分组分别经过8个不同的S-盒 S 1 S_1 S 2 S_2 S 8 S_8 )进行6-4转换,得到8个长度为4位的分组,分组位越低使用的S-盒下标也小,此处是一一对应的,S-盒的转换规则稍后给出
  • 将上一步得到的结果按顺序连接在一起得到长度为32位的串
  • 将上一步的结果经过P-置换,得到新的32位串,作为 f f ( R i 1 R_{i-1} , k i k_i ) 的返回值。P置换表共32位,代码中给出

(4)S-盒转换

每个S-盒均为4行16列的矩阵,矩阵内数据为0-15,可变为二进制串0000-1111。输入的数有6bit,经过转化之后返回4bit。

例:S1为刚刚48位串的最低6位,为“1111001”,自然得使用 S 1 S_1 盒。令row = ( 11 ) 10 (11)_{10} = 3,其中,高位1为 S 1 S_1 的最高位,低位1为 S 1 S_1 的最低位。令col = ( 1100 ) 10 (1100)_{10} = 12,这4个位为中间剩下的4个位。查找 S 1 S_1 盒, [ S 1 ] 3 , 12 {[S_1]_{3,12}} 则为输出的四位。注意:3代表的是第4行,因为矩阵下标从0开始,同理12代表13列

8个S-盒的矩阵在代码中给出。

三、代码实现模块及结构

此代码支持中英文的加密解密,具体代码请看代码文件:data.hpp存放各个置换表,des.cpp是具体实现文件

(1)自定义结构体代表二进制

typedef struct data64
{
	bitset<64> bits;
}datas_64;


typedef struct data56
{
	bitset<56> bits;
}datas_56;
//还有其他不同位数的结构体

(2)声明函数模块

void init_secret_key(); //初始化密钥
void init_K_i(datas_64 secret_key);//初始化子密钥ki
string RKCS_fill(string str);  //RKCS#5补齐8个字节
vector<datas_64> string_to_binary(string str);  //将字符串转化为二进制数
string binary_to_string(vector<datas_64> v);  //将二进制数转化为字符串
vector<datas_64> encryption(vector<datas_64> v); //所有数据的加密算法,第二个参数为密钥
vector<datas_64> Decrypt(vector<datas_64> 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函数

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<datas_64> v = string_to_binary(Plaintext);
	vector<datas_64> data1 = encryption(v);
	cout << "密文:  " << binary_to_string(data1) << endl;
	vector<datas_64> data2 = Decrypt(data1);
	cout << "解密后明文:  " << binary_to_string(data2) << endl;
	

	return 0;
}

四、实验结果

  • 输入随机中文

    在这里插入图片描述

  • 输入随机英文
    在这里插入图片描述

  • 中英混合
    在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/chenxz_/article/details/83627120