DES算法的实现

来源:互联网 发布:python可以建网站吗 编辑:程序博客网 时间:2024/05/24 16:16

DES算法的实现

  • DES 算法概述
  1. DES 是一种典型的块加密方法:它以64位为分组长度,64 位一组的明文作为算法的输入,通过一系列复杂的操作, 输出同样64位长度的密文。
  2. DES 使用加密密钥定义变换过程,因此算法认为只有持有 加密所用的密钥的用户才能解密密文。
  3. DES 的采用64位密钥,但由于每8位中的最后1位用于奇偶 校验,实际有效密钥长度为56位。密钥可以是任意的56位 的数,且可随时改变。其中极少量的数被认为是弱密钥, 但能容易地避开它们。所有的保密性依赖于密钥。
  4. DES算法的基本过程是换位和置换。

  • DES算法实现过程

首先实现的整个流程如下图所示,把64位明文转化为64位密文所需要做的事情,经过初始置换,左右移位,16轮的循环Feistel 轮函数,然后尾置换。得到64位的密文。
设信息空间由 {0, 1} 组成的字符串构成,明文信息和经过DES 加密的密文信息是64位的分组,密钥也是64位。
1)明文: M = m1m2 … m64 , mi {0, 1}, i = 1 .. 64.
2) 密文: C = c1c2 … c64 , ci {0, 1}, i = 1 .. 64
3) 密钥: K = k1k2 … k64 , ki {0, 1}, i = 1 .. 64.
除去 k8, k16, …, k64 共8位奇偶校验位,起作用的仅为56位。

加密过程

C = Ek(M) = IP-1 · T16 ·T15 ·… · T1 · IP(M), 其中 IP 为初始置换,IP-1 是IP 的逆,T1, T2 , …, T16 是一系列的迭代变换。

解密过程

M = Dk(C) = IP-1 · T1 · T2 · … · T16 · IP (C) .

  • DES加密主要由四个部分完成
1.初始置换 IP;
2.子密钥 Ki 的获取;
3. 密码函数 f ;
4.尾置换 IP-1 ;

然而最困难的部分是在第二第三部分。

1、初始置换IP

2、子密钥 Ki 的获取

通过流程图我们可以很清晰地看到了获得Ki的整个流程。



3、密码函数Feistel 轮函数



通过表 E 进行扩展置换,将输入的 32 位数据扩展为 48 位;
将扩展后的 48 位数据与 48 位的子密钥进行异或运算;
将异或得到的 48 位数据分成 8个6 位的块,每一个块通过对应的一个 S 表产生一个 4 位的输出。其中,每个 S 表都是 4 行 16 列。具体的置换过程如下:把 6 位输入中的第 1 位和第 6 位取出来行成一个两位的二进制数 x ,作为 Si 表中的行数(0~3);把 6 位输入的中间 4 位构成另外一个二进制数 y,作为 Si 表的列数(0~15);查出 Si 表中 x 行 y 列所对应的整数,将该整数转换为一个 4 位的二进制数。
把通过 S 表置换得到的 8个4位连在一起,形成一个 32 位的数据。然后将该 32 位数据通过表 P 进行置换(称为P-置换),置换后得到一个仍然是 32 位的结果数据,这就是f(R, K)函数的输出。
用到的表过多,在附录上带上矩阵
4、尾置换 IP-1

  • c++代码
#include<iostream>#include<vector>#include<bitset>#include<fstream>using namespace std;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 };// 结尾置换表  int IP_1[] = { 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 };/*------------------下面是生成密钥所用表-----------------*/// 密钥置换表,将64位密钥变成56位  int PC_1[] = { 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位子密钥  int PC_2[] = { 14, 17, 11, 24,  1,  5,3, 28, 15,  6, 21, 10,23, 19, 12,  4, 26,  8,16,  7, 27, 20, 13,  2,41, 52, 31, 37, 47, 55,30, 40, 51, 45, 33, 48,44, 49, 39, 56, 34, 53,46, 42, 50, 36, 29, 32 };// 每轮左移的位数  int shiftBits[] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };/*------------------下面是密码函数 f 所用表-----------------*/// 扩展置换表,将 32位 扩展至 48位  int E[] = { 32,  1,  2,  3,  4,  5,4,  5,  6,  7,  8,  9,8,  9, 10, 11, 12, 13,12, 13, 14, 15, 16, 17,16, 17, 18, 19, 20, 21,20, 21, 22, 23, 24, 25,24, 25, 26, 27, 28, 29,28, 29, 30, 31, 32,  1 };// S盒,每个S盒是4x16的置换表,6位 -> 4位  int S_BOX[8][4][16] = {{{ 14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7 },{ 0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8 },{ 4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0 },{ 15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13 }},{{ 15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10 },{ 3,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5 },{ 0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15 },{ 13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9 }},{{ 10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8 },{ 13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1 },{ 13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7 },{ 1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12 }},{{ 7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15 },{ 13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9 },{ 10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4 },{ 3,15,0,6,10,1,13,8,9,4,5,11,12,7,2,14 }},{{ 2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9 },{ 14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6 },{ 4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14 },{ 11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3 }},{{ 12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11 },{ 10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8 },{ 9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6 },{ 4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13 }},{{ 4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1 },{ 13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6 },{ 1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2 },{ 6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12 }},{{ 13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7 },{ 1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2 },{ 7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8 },{ 2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11 }}};// P置换,32位 -> 32位  int P[] = { 16,  7, 20, 21,29, 12, 28, 17,1, 15, 23, 26,5, 18, 31, 10,2,  8, 24, 14,32, 27,  3,  9,19, 13, 30,  6,22, 11,  4, 25 };bitset<48> K[16];///////////////////////////////////////bitset<32> Feistel(bitset<32> R, bitset<48> k) {bitset<48> expandR;for (int i = 0; i<48; ++i)expandR[47 - i] = R[32 - E[i]];expandR = expandR ^ k;bitset<32> res;int x = 0;for (int i = 0; i < 48; i = i + 6) {int row = expandR[47 - i] * 2 + expandR[47 - i - 5];int col = expandR[47 - i - 1] * 8 + expandR[47 - i - 2] * 4 + expandR[47 - i - 3] * 2 + expandR[47 - i - 4];int num = S_BOX[i / 6][row][col];bitset<4> binary(num);res[31 - x] = binary[3];res[31 - x - 1] = binary[2];res[31 - x - 2] = binary[1];res[31 - x - 3] = binary[0];x += 4;}bitset<32> tmp = res;for (int i = 0; i<32; ++i)res[31 - i] = tmp[32 - P[i]];   //modifiedreturn res;}bitset<28> leftshift(bitset<28> k, int shift) {bitset<28> tmp = k;for (int i = 27; i >= 0; --i){if (i - shift<0)k[i] = tmp[i - shift + 28];elsek[i] = tmp[i - shift];}return k;}void getK(bitset<64> key) {bitset<56> tmp;bitset<48> compressKey;bitset<28> left, right;for (int i = 0; i < 56; i++) {tmp[55 - i] = key[64 - PC_1[i]];}for (int i = 0; i < 16; i++) {for (int j = 0; j < 28; j++) right[j] = tmp[j];for (int j = 28; j < 56; j++) left[j - 28] = tmp[j];left = leftshift(left, shiftBits[i]);right = leftshift(right, shiftBits[i]);bitset<56> realKey;for (int j = 0; j < 28; j++) {realKey[j] = right[j];realKey[j + 28] = left[j];}for (int j = 0; j < 48; j++) {compressKey[47-j] = realKey[56 - PC_2[j]];}K[i] = compressKey;}}bitset<64> charToBitset(const char s[8]){bitset<64> bits;for (int i = 0; i<8; ++i)for (int j = 0; j<8; ++j)bits[i * 8 + j] = ((s[i] >> j) & 1);return bits;}bitset<64> encrypt(bitset<64> plain) {  //加密bitset<64> currentBits, real;bitset<32> left, right, nextLeft;for (int i = 0; i<64; ++i)        //初始置换IPcurrentBits[63 - i] = plain[64 - IP[i]];for (int i = 0; i < 32; ++i) {//获取左半和右半right[i] = currentBits[i];left[i] = currentBits[i + 32];}for (int i = 0; i<16; ++i){nextLeft = right;right = left ^ Feistel(right, K[i]);left = nextLeft;}for (int i = 0; i < 32; i++) {   //左右互换real[i+32] = right[i];real[i] = left[i];}currentBits = real;for (int i = 0; i<64; ++i)real[63 - i] = currentBits[64 - IP_1[i]];// 返回密文  return real;}bitset<64> decrypt(bitset<64> cipher)   //解密{bitset<64> plain;bitset<64> currentBits;bitset<32> left;bitset<32> right;bitset<32> newLeft;for (int i = 0; i<64; ++i)currentBits[63 - i] = cipher[64 - IP[i]];for (int i = 32; i<64; ++i)left[i - 32] = currentBits[i];for (int i = 0; i<32; ++i)right[i] = currentBits[i];for (int round = 0; round<16; ++round){newLeft = right;right = left ^ Feistel(right, K[15 - round]);left = newLeft;}for (int i = 0; i<32; ++i)plain[i] = left[i];for (int i = 32; i<64; ++i)plain[i] = right[i - 32];currentBits = plain;for (int i = 0; i<64; ++i)plain[63 - i] = currentBits[64 - IP_1[i]];return plain;}int main() {string s = "superman";string k = "12345678";bitset<64> plain = charToBitset(s.c_str()), key;cout << "初始密钥:      ";cout << plain << endl;key = charToBitset(k.c_str());getK(key);bitset<64> cipher = encrypt(plain);cout << "加密后的密钥:  ";cout << cipher << endl;bitset<64> temp = decrypt(cipher);cout << "解密之后的密钥:";cout << temp << endl;system("pause");}//int main() {//string s = "romantic";//string k = "12345678";//bitset<64> plain = charToBitset(s.c_str()), key;//key = charToBitset(k.c_str());//// 生成16个子密钥  //getK(key);//// 密文写入 a.txt  //bitset<64> cipher = encrypt(plain);//fstream file1;//file1.open("H://a.txt", ios::binary | ios::out);//file1.write((char*)&cipher, sizeof(cipher));//file1.close();//// 读文件 a.txt  //bitset<64> temp;//file1.open("H://a.txt", ios::binary | ios::in);//file1.read((char*)&temp, sizeof(temp));//file1.close();////// 解密,并写入文件 b.txt  //bitset<64> temp_plain = decrypt(temp);//file1.open("H://b.txt", ios::binary | ios::out);//file1.write((char*)&temp_plain, sizeof(temp_plain));//file1.close();////return 0;//}

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 房产证办出来房产局不给证怎么办 单位全员竞聘老员工没岗位怎么办 快件被快递公司签收了没给送怎么办 总公司跑路了分公司代理法人怎么办 大使馆领的结婚证现在离婚怎么办 日本签证照片被使馆贴错了怎么办 在菲律宾护照和签证丢了怎么办 新疆工地上班老板不肯发工资怎么办 德国大使馆签证如果拒签了怎么办 护照在大使馆办签证期间出国怎么办 法院两次判决不准离婚我该怎么办? 法院判决不准离婚妻子不回来怎么办 被告人在不调解的情况下怎么办 知道弟兄的孩子是别人的怎么办? 办居住证的回执单丢了怎么办 领取居住证的回执单丢了怎么办 北京居住证网上申报信息填错怎么办 买家退回来的货有问题怎么办 居转户过程中生的小孩户口怎么办 人才引进申请上海户口被拒怎么办 网络购高铁票身份证没有验证怎么办 高速遇到很浓的团雾怎么办 对于大巴不按座位坐的人该怎么办 火车上遇到占座不让的人怎么办 滁州婴儿打疫苗的绿本子怎么办 检查四维说宝宝嘴巴显示不清怎么办 携程订票付款成功一直没出票怎么办 手机微信支付密码忘了怎么办 存入卡里的钱却说余额不足怎么办 买高铁票身份证未通过审核怎么办 网上订演出票不配送了怎么办 百度糯米订的演出票不配送了怎么办 高铁误点改签后的车次没票了怎么办 高铁晚点没赶上下班车怎么办 上班期间单位没给交养老保险怎么办 一键启动车钥匙遥控失灵怎么办 已经订购的火车票误了火车怎么办 飞机去程取消分开买的返程怎么办 订完学生票发现使用次数过了怎么办 坐火车买学生票没带学生证怎么办 买了学生票学生证磁条没了怎么办