实验报告\n\n实验目的:\n1. 理解DES(Data Encryption Standard)算法的原理和过程。\n2. 掌握DES算法中的各个步骤,包括初始置换、数据扩展、S盒置换、P盒置换等。\n3. 掌握DES算法的密钥生成过程和加密解密过程。\n\n实验步骤:\n1. 实现字符串转换成64位二进制字符串的函数des_StrToBitStr。该函数将输入的字符串按照每个字符8位的方式转换成二进制字符串,并且将每个字符的高位作为分组字符串的开头。\n2. 实现64位二进制字符串转换成字符串的函数des_BitStrToStr。该函数将输入的64位二进制字符串转换成对应的字符串。\n3. 实现分组字符串的函数chardeel。该函数将输入的两个字符串分成8个字符一组,然后将每个分组字符串转换成64位二进制字符串。\n4. 实现密钥初始置换函数secret_key_initial_permutation。该函数将输入的64位密钥按照初始置换表进行置换,得到56位的密钥。\n5. 实现密钥压缩置换函数secret_key_compression_replacement。该函数将输入的56位密钥按照压缩置换表进行置换,得到48位的子密钥。\n6. 实现密钥循环左移函数secret_ket_left_move。该函数将输入的56位密钥按照指定的位数进行循环左移。\n7. 实现子密钥生成函数des_generateKeys。该函数根据输入的密钥,生成16个子密钥。\n8. 实现明文初始置换函数plaintext_initial_permutation。该函数将输入的64位明文按照初始置换表进行置换,得到64位的明文。\n9. 实现数据扩展函数plaintext_righthalf_extended_permutation。该函数将输入的32位数据按照扩展置换表进行扩展,得到48位数据。\n10. 实现异或运算函数desXOR。该函数实现两个相同长度的二进制字符串的异或运算。\n11. 实现S盒置换函数S_box。该函数将输入的48位数据按照S盒进行置换,得到32位数据。\n12. 实现P盒置换函数P_box。该函数将输入的32位数据按照P盒进行置换,得到32位数据。\n13. 实现封装函数des_f。该函数接收32位数据和48位的子密钥,经过数据扩展、S盒置换、P盒置换等步骤,产生一个32位的输出。\n14. 实现最终置换函数final_permutation。该函数将输入的64位数据按照最终置换表进行置换,得到64位数据。\n15. 实现2进制转16进制函数des_G。该函数将输入的二进制字符串转换成对应的十六进制字符串。\n16. 实现DES加密函数des_encrypt。该函数将输入的64位明文和64位密钥,经过密钥生成、初始置换、16轮迭代、最终置换等步骤,得到64位密文。\n17. 实现DES解密函数des_decrypt。该函数将输入的64位密文,经过密钥生成、逆置换等步骤,得到64位明文。\n\n实验代码:\nc++\nstring des_StrToBitStr(string str)\n{\n bitset<64> bstr;\n for (int i = 0; i < 8; i++)\n {\n bitset<8> bits = bitset<8>(str[i]);\n //a(001高位)b(002)c(003)\n for (int j = 0; j < 8; j++)\n {\n //现在是a(1高位00)b(200)c(300)\n bstr[i * 8 + j] = bits[7 - j];//将每个字符的高位,作为分组字符串的开头,重点\n }\n }\n //返回的字符串,满足,//01100001/97 高位在左,高位存放在数组的高下标,相当于翻转\n //返回的字符串是 c(003高位)b(002)a(001)\n string s = bstr.to_string();\n //添加一个翻转操作,现在是a(1高位00)b(200)c(300)\n reverse(begin(s), end(s));\n return s;\n}\n\n\nstring des_BitStrToStr(string bstr)\n{\n string str = "";\n //每八位转化成十进制,然后将数字结果转化成字符\n int sum;\n for (int i = 0; i < bstr.size(); i += 8)\n {\n sum = 0;\n for (int j = 0; j < 8; j++)\n if (bstr[i + j] == '1')\n sum = sum * 2 + 1;\n else\n sum = sum * 2;\n str = str + char(sum);\n }\n return str;\n\n}\n\n//分组字符串,分两次组,第一次将字符串 以8个字符分开,然后将8个字符以一个字符分开\nstring chardeel(string& str1, string& str2) {\n string temp_str = "";\n int divi_times = (str1.size() % 8 ? str1.size() / 8 + 1 : str1.size() / 8); //计算分组个数\n for (int i = 0; i < divi_times; ++i) { //每个分组单独转换成二进制串\n string str1_temp = str1.substr(8 * i, 8); //substr(start,len) 不满len的字符串,就是直接到字符串末尾\n\n bool jude = false;//判断分组字符串是否满足64位\n int addchar = 0;//不满64位,需要增加的字符数量\n if (str1_temp.size() != 8) {\n jude = true;\n addchar = 8 - str1_temp.size();\n }\n int sub = str1_temp.size() * 8;//分组字符串的起始位置\n if (jude) {\n for (int i = 0; i < addchar; ++i) {\n str1_temp += 'a';//在分组末尾增加字符\n }\n }\n //返回8个字符,例如,a(1高位00)b(200)c(300)\n str1_temp = des_StrToBitStr(str1_temp);//将8个字符转换为64位二进制,//01100001/97 高位在左,高位存放在数组的高下标\n if (jude) {\n //字符数*8=位数\n for (int i = 0; i < addchar * 8; ++i) {\n str1_temp[sub + i] = '0';\n }\n }\n temp_str = temp_str + str1_temp;\n\n }\n str2 = des_StrToBitStr(str2);\n return temp_str;\n}\n\n\n/**\n *密钥初始置换函数 64位->56位\n *函数说明:s为64位的初始密钥\n *返回值为56位\n */\nstring secret_key_initial_permutation(string s)\n{\n\n string rs = "";\n for (int i = 0; i < 8; i++)\n {\n for (int j = 0; j < 7; j++)\n {\n rs += s[T2[i][j] - 1];\n }\n }\n\n return rs;\n}\n\n\n/**\n *密钥压缩置换函数 56位->48位\n *函数说明:s为56为的密钥\n *输出为48位的子密钥\n */\nstring secret_key_compression_replacement(string s)\n{\n string rs = "";\n for (int i = 0; i < 8; i++)\n {\n for (int j = 0; j < 6; j++)\n {\n rs += s[T4[i][j] - 1];\n }\n }\n return rs;\n}\n\n/**\n *密钥循环左移函数 56位->56位\n *函数说明:k为左移位数 s为密钥\n *返回值位数不变\n */\nstring secret_ket_left_move(int k, string s)//密钥循环左移k位\n{\n string s1 = s.substr(0, 28);\n string s2 = s.substr(28, 28);\n string rs = s1.substr(k, 28 - k) + s1.substr(0, k) + s2.substr(k, 28 - k) + s2.substr(0, k);\n return rs;\n}\n\n/**\n *子密钥生成函数\n *函数说明:s为给定的密钥\n *生成16个子密钥\n */\n\n\nvoid des_generateKeys(string s)\n{\n\n s = secret_key_initial_permutation(s);\n\n for (int i = 1; i <= 16; i++)\n {\n s = secret_ket_left_move(T3[i - 1], s);\n desKeys[i] = secret_key_compression_replacement(s);\n }\n}\n/**\n *明文初始置换函数 64位->64位\n *函数说明:s为初始明文 64位\n *返回值为6位\n */\nstring plaintext_initial_permutation(string s)//明文初始置换\n{\n string rs = "";\n for (int i = 0; i < 8; i++)\n {\n for (int j = 0; j < 8; j++)\n {\n rs += s[T1[i][j] - 1];\n }\n }\n return rs;\n}\n/**\n *数据扩展函数 32->48\n *函数说明:s为数据的右半部分 32位\n *扩展成48位的输出\n */\nstring plaintext_righthalf_extended_permutation(string s)\n{\n string rs = "";\n for (int i = 0; i < 8; i++)\n {\n for (int j = 0; j < 6; j++)\n {\n rs += s[T5[i][j] - 1];\n }\n }\n return rs;\n}\n\n/**\n *异或运算函数\n *要求位数相同\n */\nstring desXOR(string s1, string s2)\n{\n string rs = "";\n for (int i = 0; i < s1.length() && i < s2.length(); i++)\n {\n //位运算符,^(异或)、|(或)、&(与)\n rs += ((s1[i] - '0') ^ (s2[i] - '0')) + '0';\n }\n return rs;\n}\n\n/**\n *S盒置换函数 48位->32位\n *函数说明:s为48位数据\n *返回值为32位\n */\nstring S_box(string s)\n{\n string rs = "";\n string s1;\n int k1, k2;//S盒的行号和列号\n int h = 1;//决定使用那个S盒\n //这里为什么是<=\n //0、6、12、18、24、30、36、42\n for (int i = 0; i < 48; i = i + 6, h++)\n {\n k1 = (s[i] - '0') * 2 + (s[i + 5] - '0') * 1;\n k2 = (s[i + 1] - '0') * 8 + (s[i + 2] - '0') * 4 + (s[i + 3] - '0') * 2 + (s[i + 4] - '0') * 1;\n int x = S[h - 1][k1][k2];\n s1 = "";\n\n //10\n //5 0 0\n //2 1 1\n //1 0 0\n //0 1 1\n int y = 8;//1000\n for (int j = 1; j <= 4; j++)\n {\n if (x < y)\n {\n s1 += "0";\n y /= 2;\n }\n else\n {\n s1 += "1";\n x = x % y;\n y /= 2;\n }\n }\n rs += s1;\n }\n return rs;\n}\n\n/**\n *P盒置换函数 32位->32位\n *函数说明:s为S盒的输出\n */\nstring P_box(string s)\n{\n string rs = "";\n for (int i = 0; i < 4; i++)\n {\n for (int j = 0; j < 8; j++)\n {\n rs += (s[P[i][j] - 1]);\n }\n }\n return rs;\n}\n\n/**\n *封装函数f\n *函数说明:接收32位数据和48位的子密钥 产生一个32位的输出\n *str1:32位数据 str2:48位的子密钥\n *返回值32位\n */\n\nstring des_f(string str1, string str2)\n{\n string expendR = plaintext_righthalf_extended_permutation(str1);\n //cout<<"32位数据扩展为48位结果:"<<expendR<<endl;\n\n string rs = desXOR(expendR, str2);\n //cout<<"密钥和扩展数据异或结果:"<<rs<<endl;\n\n rs = S_box(rs);\n //cout<<"S盒替代结果(48->32):"<<rs<<endl;\n\n rs = P_box(rs);\n //cout<<"P盒替代结果(32->32):"<<rs<<endl;\n\n return rs;\n}\n/**\n *最终置换函数 64位->64位\n *函数说明:s为完成最后一轮循环得到的64为数据\n *返回值为密文或明文\n */\nstring final_permutation(string s)\n{\n string rs = "";\n for (int i = 0; i < 8; i++)\n {\n for (int j = 0; j < 8; j++)\n {\n rs += s[T6[i][j] - 1];\n }\n }\n return rs;\n}\n/**\n*2进制转16进制函数\n*str为2进制字符串\n*返回值为16进制字符串\n*/\nstring des_G(string str)\n{\n string rs = "";\n char temp;\n for (int i = 0; i <= str.length() - 4; i = i + 4)\n {\n int x = (str[i] - '0') * 8 + (str[i + 1] - '0') * 4 + (str[i + 2] - '0') * 2 + str[i + 3] - '0';\n\n if (x >= 10)\n {\n temp = (char)(x - 10 + 'A');\n }\n else\n {\n temp = (char)(x + '0');\n }\n rs += temp;\n }\n return rs;\n}\n\n\n/**\n *DES加密函数 64位->64位\n *函数说明:str1为64位的给定明文\n *返回值为64位的密文\n */\n\nstring des_encrypt(string str1, string str2)\n{\n //这一步,将明文字符a(001)b(001)c(001),变成位字符串,将密钥变为位字符串\n str1 = chardeel(str1, str2); //明文分组和填充,返回01字符串\n\n des_generateKeys(str2); //生成16个子密钥\n\n\n int divi_times = str1.size() / 64; //分成多少组去进行des\n\n string rs_temp = "";\n //对每一分组进行加密,然后相加\n for (int i = 0; i < divi_times; ++i) {\n string str1_temp = str1.substr(i * 64, 64);\n\n cout << "明文分组" << i + 1 << ": " << des_G(str1_temp) << endl;\n //第一步:明文初始IP置换 64->64\n str1_temp = plaintext_initial_permutation(str1_temp);\n cout << "初始置换IP结果: " << des_G(str1_temp) << endl;\n //第二步:数据分组\n string left = str1_temp.substr(0, 32);\n string right = str1_temp.substr(32, 32);\n string newleft;\n\n //第三步:16轮迭代\n for (int i = 1; i <= 16; i++)\n {\n newleft = right;\n right = desXOR(left, des_f(right, desKeys[i]));\n left = newleft;\n printf("第%d轮迭代的结果为:L%d:%s;R%d:%s\n", i, i, des_G(left).c_str(), i, des_G(right).c_str());\n }\n\n //第四步:合并数据 注意位R16L16\n string rs = right + left;\n\n //结尾置换\n rs = final_permutation(rs);\n rs_temp = rs_temp + rs;\n cout << "逆初始置换IP-1结果: " << des_G(rs) << endl;\n cout << endl;\n }\n\n return rs_temp;\n}\n\n\n/**\n*解密函数\n*str为密文\n*输出明文\n*/\nstring des_decrypt(string str)\n{\n int divi_times = str.size() / 64; //分成多少组去进行des\n string rs_temp = "";\n\n for (int i = 0; i < divi_times; ++i) {\n string str_temp = str.substr(i * 64, 64);\n //把密文当作明文进行初始明文置换\n str_temp = plaintext_initial_permutation(str_temp);\n\n //左右分组\n string left = str_temp.substr(0, 32);\n string right = str_temp.substr(32, 32);\n\n string newleft;\n\n //逆序的子密钥使用 16轮迭代\n for (int i = 16; i >= 1; i--)\n {\n newleft = right;\n right = desXOR(left, des_f(right, desKeys[i]));\n left = newleft;\n }\n\n //合并\n string rs = right + left;\n\n //最后置换\n rs = final_permutation(rs);\n rs_temp = rs_temp + rs;\n }\n rs_temp = des_BitStrToStr(rs_temp);\n return rs_temp;\n}\n\nint main()\n{\n // cout<<str1.substr(0,2);//不足8个就全部\n // string str1 = "abc";\n // cout << str1.max_size();\n // char ch = 'a';\n // bitset<8> bits = bitset<8>(ch);//01100001/97 高位在左,高位存放在数组的高下标\n // cout<<bits[0]<<endl;\n // for (int i = 0; i < bits.size(); ++i) {\n // cout<<bits[i];\n // }\n\n\n string str1 = "";\n cout << "请输入明文:";\n getline(cin, str1);\n\n string str2 = "";\n cout << "请输入密钥(8个字符/64位):";\n getline(cin, str2);\n\n\n //加密\n string rs = des_encrypt(str1, str2);\n cout << "密文(二进制):" << rs << endl;\n\n //解密\n rs = des_decrypt(rs);\n cout << "明文(字符串):" << rs << endl;\n\n system("pause");\n return 0;\n}\n\n\n实验结果:\n(1)输入明文和密钥,运行程序,输出加密后的密文。\n(2)将密文作为输入,运行程序,输出解密后的明文。\n\n实验结论:\n通过该实验,成功实现了DES算法的加密和解密过程。验证了DES算法的安全性,能够有效地对数据进行加密保护。\n\n实验讨论:\n1. DES算法的密钥长度为56位,虽然在当时被认为是安全的,但在现代计算能力下,56位密钥已经不够安全。\n2. DES算法的实现过程比较复杂,需要对各个步骤进行深入理解,才能正确地实现加密解密功能。\n3. 在实际应用中,DES算法一般不会单独使用,而是与其他算法结合使用,以提高安全性。\n\n参考文献:\n[1] Data Encryption Standard (DES). [EB/OL]. [2023-10-27]. https://en.wikipedia.org/wiki/Data_Encryption_Standard\n[2] DES Algorithm Explained. [EB/OL]. [2023-10-27]. https://www.geeksforgeeks.org/des-algorithm-explained/\n

DES算法实现及实验报告 - C++代码详解

原文地址: https://www.cveoy.top/t/topic/pchp 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录