DES算法实现:加密与解密实验报告
DES算法实现:加密与解密实验报告
一、实验目的
本实验的目的是通过实现DES(Data Encryption Standard)算法,加密和解密给定的明文和密钥。
二、实验原理
DES算法是一种对称加密算法,其主要原理如下:
- 初始置换IP:将明文的64位按照一定规则进行置换。
- 密钥初始置换:将密钥的64位按照一定规则进行置换,生成56位的密钥。
- 生成16个子密钥:根据初始密钥,通过循环左移和压缩置换生成16个子密钥。
- 数据分组:将64位明文分为左右两个32位的数据。
- 16轮迭代加密:根据16个子密钥,对数据进行16轮的迭代加密,每轮包括数据扩展、异或运算、S盒置换和P盒置换。
- 合并数据:将左右两个32位的数据合并成64位。
- 逆初始置换IP-1:将加密后的64位按照逆初始置换规则进行置换,得到最终的密文。
三、代码实现
string des_StrToBitStr(string str)
{
bitset<64> bstr;
for (int i = 0; i < 8; i++)
{
bitset<8> bits = bitset<8>(str[i]);
//a(001高位)b(002)c(003)
for (int j = 0; j < 8; j++)
{
//现在是a(1高位00)b(200)c(300)
bstr[i * 8 + j] = bits[7 - j];//将每个字符的高位,作为分组字符串的开头,重点
}
}
//返回的字符串,满足,//01100001/97 高位在左,高位存放在数组的高下标,相当于翻转
//返回的字符串是 c(003高位)b(002)a(001)
string s = bstr.to_string();
//添加一个翻转操作,现在是a(1高位00)b(200)c(300)
reverse(begin(s), end(s));
return s;
}
string des_BitStrToStr(string bstr)
{
string str = '';
//每八位转化成十进制,然后将数字结果转化成字符
int sum;
for (int i = 0; i < bstr.size(); i += 8)
{
sum = 0;
for (int j = 0; j < 8; j++)
if (bstr[i + j] == '1')
sum = sum * 2 + 1;
else
sum = sum * 2;
str = str + char(sum);
}
return str;
}
//分组字符串,分两次组,第一次将字符串 以8个字符分开,然后将8个字符以一个字符分开
string chardeel(string& str1, string& str2) {
string temp_str = '';
int divi_times = (str1.size() % 8 ? str1.size() / 8 + 1 : str1.size() / 8); //计算分组个数
for (int i = 0; i < divi_times; ++i) { //每个分组单独转换成二进制串
string str1_temp = str1.substr(8 * i, 8); //substr(start,len) 不满len的字符串,就是直接到字符串末尾
bool jude = false;//判断分组字符串是否满足64位
int addchar = 0;//不满64位,需要增加的字符数量
if (str1_temp.size() != 8) {
jude = true;
addchar = 8 - str1_temp.size();
}
int sub = str1_temp.size() * 8;//分组字符串的起始位置
if (jude) {
for (int i = 0; i < addchar; ++i) {
str1_temp += 'a';//在分组末尾增加字符
}
}
//返回8个字符,例如,a(1高位00)b(200)c(300)
str1_temp = des_StrToBitStr(str1_temp);//将8个字符转换为64位二进制,//01100001/97 高位在左,高位存放在数组的高下标
if (jude) {
//字符数*8=位数
for (int i = 0; i < addchar * 8; ++i) {
str1_temp[sub + i] = '0';
}
}
temp_str = temp_str + str1_temp;
}
str2 = des_StrToBitStr(str2);
return temp_str;
}
/**
*密钥初始置换函数 64位->56位
*函数说明:s为64位的初始密钥
*返回值为56位
*/
string secret_key_initial_permutation(string s)
{
string rs = '';
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 7; j++)
{
rs += s[T2[i][j] - 1];
}
}
return rs;
}
/**
*密钥压缩置换函数 56位->48位
*函数说明:s为56为的密钥
*输出为48位的子密钥
*/
string secret_key_compression_replacement(string s)
{
string rs = '';
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 6; j++)
{
rs += s[T4[i][j] - 1];
}
}
return rs;
}
/**
*密钥循环左移函数 56位->56位
*函数说明:k为左移位数 s为密钥
*返回值位数不变
*/
string secret_ket_left_move(int k, string s)//密钥循环左移k位
{
string s1 = s.substr(0, 28);
string s2 = s.substr(28, 28);
string rs = s1.substr(k, 28 - k) + s1.substr(0, k) + s2.substr(k, 28 - k) + s2.substr(0, k);
return rs;
}
/**
*子密钥生成函数
*函数说明:s为给定的密钥
*生成16个子密钥
*/
void des_generateKeys(string s)
{
s = secret_key_initial_permutation(s);
for (int i = 1; i <= 16; i++)
{
s = secret_ket_left_move(T3[i - 1], s);
desKeys[i] = secret_key_compression_replacement(s);
}
}
/**
*明文初始置换函数 64位->64位
*函数说明:s为初始明文 64位
*返回值为6位
*/
string plaintext_initial_permutation(string s)//明文初始置换
{
string rs = '';
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
rs += s[T1[i][j] - 1];
}
}
return rs;
}
/**
*数据扩展函数 32->48
*函数说明:s为数据的右半部分 32位
*扩展成48位的输出
*/
string plaintext_righthalf_extended_permutation(string s)
{
string rs = '';
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 6; j++)
{
rs += s[T5[i][j] - 1];
}
}
return rs;
}
/**
*异或运算函数
*要求位数相同
*/
string desXOR(string s1, string s2)
{
string rs = '';
for (int i = 0; i < s1.length() && i < s2.length(); i++)
{
//位运算符,^(异或)、|(或)、&(与)
rs += ((s1[i] - '0') ^ (s2[i] - '0')) + '0';
}
return rs;
}
/**
*S盒置换函数 48位->32位
*函数说明:s为48位数据
*返回值为32位
*/
string S_box(string s)
{
string rs = '';
string s1;
int k1, k2;//S盒的行号和列号
int h = 1;//决定使用那个S盒
//这里为什么是<=
//0、6、12、18、24、30、36、42
for (int i = 0; i < 48; i = i + 6, h++)
{
k1 = (s[i] - '0') * 2 + (s[i + 5] - '0') * 1;
k2 = (s[i + 1] - '0') * 8 + (s[i + 2] - '0') * 4 + (s[i + 3] - '0') * 2 + (s[i + 4] - '0') * 1;
int x = S[h - 1][k1][k2];
s1 = '';
//10
//5 0 0
//2 1 1
//1 0 0
//0 1 1
int y = 8;//1000
for (int j = 1; j <= 4; j++)
{
if (x < y)
{
s1 += '0';
y /= 2;
}
else
{
s1 += '1';
x = x % y;
y /= 2;
}
}
rs += s1;
}
return rs;
}
/**
*P盒置换函数 32位->32位
*函数说明:s为S盒的输出
*/
string P_box(string s)
{
string rs = '';
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 8; j++)
{
rs += (s[P[i][j] - 1]);
}
}
return rs;
}
/**
*封装函数f
*函数说明:接收32位数据和48位的子密钥 产生一个32位的输出
*str1:32位数据 str2:48位的子密钥
*返回值32位
*/
string des_f(string str1, string str2)
{
string expendR = plaintext_righthalf_extended_permutation(str1);
//cout<<'32位数据扩展为48位结果:'<<expendR<<endl;
string rs = desXOR(expendR, str2);
//cout<<'密钥和扩展数据异或结果:'<<rs<<endl;
rs = S_box(rs);
//cout<<'S盒替代结果(48->32):'<<rs<<endl;
rs = P_box(rs);
//cout<<'P盒替代结果(32->32):'<<rs<<endl;
return rs;
}
/**
*最终置换函数 64位->64位
*函数说明:s为完成最后一轮循环得到的64为数据
*返回值为密文或明文
*/
string final_permutation(string s)
{
string rs = '';
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
rs += s[T6[i][j] - 1];
}
}
return rs;
}
/**
*2进制转16进制函数
*str为2进制字符串
*返回值为16进制字符串
*/
string des_G(string str)
{
string rs = '';
char temp;
for (int i = 0; i <= str.length() - 4; i = i + 4)
{
int x = (str[i] - '0') * 8 + (str[i + 1] - '0') * 4 + (str[i + 2] - '0') * 2 + str[i + 3] - '0';
if (x >= 10)
{
temp = (char)(x - 10 + 'A');
}
else
{
temp = (char)(x + '0');
}
rs += temp;
}
return rs;
}
/**
*DES加密函数 64位->64位
*函数说明:str1为64位的给定明文
*返回值为64位的密文
*/
string des_encrypt(string str1, string str2)
{
//这一步,将明文字符a(001)b(001)c(001),变成位字符串,将密钥变为位字符串
str1 = chardeel(str1, str2); //明文分组和填充,返回01字符串
des_generateKeys(str2); //生成16个子密钥
int divi_times = str1.size() / 64; //分成多少组去进行des
string rs_temp = '';
//对每一分组进行加密,然后相加
for (int i = 0; i < divi_times; ++i) {
string str1_temp = str1.substr(i * 64, 64);
cout << '明文分组' << i + 1 << ': ' << des_G(str1_temp) << endl;
//第一步:明文初始IP置换 64->64
str1_temp = plaintext_initial_permutation(str1_temp);
cout << '初始置换IP结果: ' << des_G(str1_temp) << endl;
//第二步:数据分组
string left = str1_temp.substr(0, 32);
string right = str1_temp.substr(32, 32);
string newleft;
//第三步:16轮迭代
for (int i = 1; i <= 16; i++)
{
newleft = right;
right = desXOR(left, des_f(right, desKeys[i]));
left = newleft;
printf('第%d轮迭代的结果为:L%d:%s;R%d:%s
', i, i, des_G(left).c_str(), i, des_G(right).c_str());
}
//第四步:合并数据 注意位R16L16
string rs = right + left;
//结尾置换
rs = final_permutation(rs);
rs_temp = rs_temp + rs;
cout << '逆初始置换IP-1结果: ' << des_G(rs) << endl;
cout << endl;
}
return rs_temp;
}
/**
*解密函数
*str为密文
*输出明文
*/
string des_decrypt(string str)
{
int divi_times = str.size() / 64; //分成多少组去进行des
string rs_temp = '';
for (int i = 0; i < divi_times; ++i) {
string str_temp = str.substr(i * 64, 64);
//把密文当作明文进行初始明文置换
str_temp = plaintext_initial_permutation(str_temp);
//左右分组
string left = str_temp.substr(0, 32);
string right = str_temp.substr(32, 32);
string newleft;
//逆序的子密钥使用 16轮迭代
for (int i = 16; i >= 1; i--)
{
newleft = right;
right = desXOR(left, des_f(right, desKeys[i]));
left = newleft;
}
//合并
string rs = right + left;
//最后置换
rs = final_permutation(rs);
rs_temp = rs_temp + rs;
}
rs_temp = des_BitStrToStr(rs_temp);
return rs_temp;
}
int main()
{
// cout<<str1.substr(0,2);//不足8个就全部
// string str1 = 'abc';
// cout << str1.max_size();
// char ch = 'a';
// bitset<8> bits = bitset<8>(ch);//01100001/97 高位在左,高位存放在数组的高下标
// cout<<bits[0]<<endl;
// for (int i = 0; i < bits.size(); ++i) {
// cout<<bits[i];
// }
string str1 = '';
cout << '请输入明文:';
getline(cin, str1);
string str2 = '';
cout << '请输入密钥(8个字符/64位):';
getline(cin, str2);
//加密
string rs = des_encrypt(str1, str2);
cout << '密文(二进制):' << rs << endl;
//解密
rs = des_decrypt(rs);
cout << '明文(字符串):' << rs << endl;
system('pause');
return 0;
}
四、实验步骤
- 编写代码,实现DES算法的加密和解密函数。
- 运行代码,输入明文和密钥,进行加密操作。
- 使用加密后的密文,进行解密操作,验证解密后的明文是否与原明文一致。
五、实验结果
本实验成功地实现了DES算法的加密和解密功能。对给定的明文和密钥进行加密,并使用解密函数进行解密,解密后的明文与原明文一致,验证了算法的正确性。
六、实验总结
本实验通过实现DES算法,加深了对对称加密算法的理解,并掌握了DES算法的实现方法。实验过程中,需要仔细理解DES算法的原理,并根据原理编写代码实现加密和解密函数。此外,需要进行充分的测试,确保算法的正确性。
七、实验思考
- DES算法的安全性如何?
- DES算法的应用场景有哪些?
- DES算法与其他对称加密算法相比,有哪些优缺点?
- DES算法的未来发展趋势如何?
原文地址: https://www.cveoy.top/t/topic/pchK 著作权归作者所有。请勿转载和采集!