算法实现按照《信息安全原理与技术》(郭亚军、宋建华、李莉、董慧慧编著)给出的过程,输入输出格式按照本书56页例3.8指定,即输入16个字符的16进制明文和密钥 (输入16个16进制char后自动处理成64位的2进制进行计算,也即DES分组大小和DES的密钥大小),输出64位2进制密文(解密时输出64位2进制明文)和对应的16位16进制密文/明文,如下图:

个人地址:http://hlyin.space/Information-Security/des/

源码丢在github上,有需要的可以下载查看,地址:https://github.com/louiehuang/DES

一、算法过程

DES原理本身不难理解,只是实现起来比较麻烦,所以这里只是大概提一下算法过程,详细过程可以参考《信息安全原理与技术》或 DES算法实例详解,讲得都比较清楚。

(1)处理密钥

  1. 输入64位密钥,经过置换选择1(56位)得到56位的实际密钥
  2. 按28位1组分成前后C和D两个部分
  3. 进行16轮循环,每轮循环中先对C和D循环左移,再将结果合并
  4. 通过置换选择2(48位)选出当前轮的48位子密钥。

(2)处理明文

  1. 输入64位明文,初始置换
  2. 按32位1组分成前后L和R两个部分
  3. 进行16轮迭代,每轮迭代中,下一轮使用的L为本轮的R,下一轮使用的R需经过如下计算得到:
    先将32位的R经过扩展置换E扩展成48位,与当前轮使用的子密钥(加密时为顺序使用子密钥,解密时为逆序使用子密钥)进行异或,将得到的48位结果按6位1组分成8组,每组使用1个S盒进行置换,每组得到4位输出,即最后得到32位的输出,将此输出结果经置换P后得到的结果与本轮的L相异或,即为下一轮的R
  4. 16轮迭代结束后,将最后得到的L和R交换,即(R,L)
  5. 逆初始置换后得到64位密文

二、算法实现

为了清晰理解DES算法的原理,希望将算法中所有的中间结果均能输出出来查看,基于这个目的,我选取的主要数据结构为char数组,不需要输出中间结果则可以使用bool类型,运算效率比char高… 嗯没管效率只是为了理解DES而已…

我按课本56页例3.8制定输入格式,即输入的明文和密钥均为16位的16进制字符串,因此为了输出中间过程,需要将输入转换成64位的2进制字符数组,char类型数组最后一位需要放’\0’,因此所有的char数组的实际大小均为算法所需大小加1,主要的数据结构如下:

输入:

  • char HexMsg[17], char HexKey[17] //明文和密钥输入为16位的16进制字符串

预处理:

  • char HexMsg[17] → char BiMsg[65] //64位的2进制明文
  • char HexKey[17] → char BiKey[65] //64位的2进制密钥

DES:
产生子密钥:

  • char realKey[57] //经置换选择1选出56位
  • char C[29], D[29] //前后2部分,各28位
  • char CDCombine[57] //循环左移后将C、D数组结合
  • char subKey[16][49] //置换选择2后产生的子密钥

初始置换:

  • char BiMsgCopy[57] //复制一份原数组,否则在期间的改变会使得替换的元素发生改变
  • char L[33], R[33] //前后2部分,各32位

16轮迭代:

  • char RCopy[29] //复制R,运算期间会改变R,而最后需要将本轮开始的R赋给下一轮的L
  • char ExtendedR[49] //扩展48位,与子密钥的异或直接修改ExtendedR
  • char group[7] //将48位的ExtendedR分层6位1组的group,对每组group按S盒查找替换,替换结果直接修改R
  • char SR[33] //置换P时复制经S盒变化后的R
  • L与R异或直接修改R,此时得到本轮的最终R,即下一轮输入的R
  • 将本轮开始时的R复制给L,即RCopy赋给L,此时得到本轮的最终L,即下一轮输入的L

32位互换:

  • char RLChange[65] //互换L16和R16位置,即(R16,L16)

逆初始置换:

  • char Cipher[65] //逆初始置换后的密文(解密时为明文)结果

三、部分代码解释

预处理时将16位16进制char数组转成64位2进制数组,在S盒变换时,需要将S盒中行列对应的16进制元素(1位)转换成2进制(4位),在这两个地方使用16进制转2进制,代码如下:

/***16进制数组转2进制数组(16元素),输入M和K时使用(64位)以及S盒变换时使用(4位)***/
char * HexToBi(char *hexArray)
{toUpper(hexArray); //小写转大写char * biArray = new char[65];int index = 0;char *p = hexArray;while(*p)//字符串不结束就循环{string temp;if(*p>='0' && *p <='9') //数字{temp = HexBiTable[*p - 48];}else if(*p>='A' && *p <='F') //A~F字符{temp = HexBiTable[*p - 65 + 10];}for(int i = 0; i < 4; i++, index++){biArray[index] = temp[i];}p++; //指针后指,准备处理下一个字母}biArray[index] = '\0';return biArray;
}

考虑到这里的需求是16进制char数组转2进制char数组,而不是16进制整型转2进制,因此相比于类型转换后辗转相除,采用的是查表HexBiTable替换更为有效。

产生子密钥:
置换选择1:

    char * realKey = new char[57]; realKey[56] = '\0'; //56位有效密钥    /**置换选择1,64位中选择56位得到实际使用的56位密钥**/for(int i = 0; i < 56; i++){int index = PC1Table[i] - 1; //-1后才是在数组中的实际下标 realKey[i] = BiKey[index];}//cout<<realKey<<endl;

通过查表PC1Table,即置换选择1,得到应替换元素的位置,需要减1得到在数组中的下标,for循环56次,得到56位的置换选择后的56位密钥,每次置换选择在原64位密钥BiKey中查找。

循环左移:
循环左移n位,通过3次逆序使时间复杂度降为O(n),如循环左移2位10010011,则先逆序前2位得到01,再逆序后所有位得到110010,此时即为01110010,最后逆序所有位,得到01001110,即为最终结果。

/***循环左移n位,复杂度0(n),通过三次逆序实现***/
void LeftShift(char * arr, int n)
{Reverse(arr, 0, n - 1); //逆序前n位Reverse(arr, n, 28 - 1); //逆序后所有位Reverse(arr, 0, 28 - 1); //逆序所有位
}/***逆序排列***/
void Reverse(char *arr, int begin, int end)
{char temp;for( ; begin < end; begin++, end--){temp = arr[end];arr[end] = arr[begin];arr[begin] = temp;}
}

在对明文的处理中的置换基本类同与置换选择1的实现,得到48位的扩展R后进行S盒变换,实现为将扩展R分成8组,每组6位,进行8轮的循环,每个循环中对1个组使用S盒变换,循环中先获取当前轮进行变换的6位输入group,如下:

char group[7]; group[6] = '\0'; //1组for(int i = 0; i < 6; i++){group[i] = ExtendedR[s * 6 + i]; //6位1组}

得到group后需据此获取在S盒中的行和列下标用来获取S盒对应的元素值,这里以group=”010001”为例,行即为01,列为1000,需要将2进制转成10进制以得到下标,为方便计算,将行表示为0001,这样仍通过查表HexBiTable来获取,这里仅仅就只是为了方便,其实并不好… 此时line=”0001”,column=”1000”,查表值0001对应的下标为1,1000对应的下标为8,所以在S盒中行下标x=1,列下标y=8,查S[i][x][y]得到对应的元素,以S1为例,即i=0,此时元素值为10,最后需要将整型的10转成4位的2进制数组,得到1010,代码如下:

//16进制字符串转10进制整型//如一组为010001,则line="0001", colum="1000",则x=1, y=8int x, y; //x为在S盒中的行下标,y为列下标char *line = new char[5]; line[4] = '\0';char *column = new char[5]; column[4] = '\0';line[0] = '0'; line[1] = '0'; line[2] = group[0]; line[3] = group[5]; //01即为00 01column[0] = group[1]; column[1] = group[2]; column[2] = group[3]; column[3] = group[4];//通过HexBiTable找到2进制对应的10进制(数组下标)bool xflag = true, yflag = true; for(int i = 0; i < 16; i++){xflag = true; yflag = true; //找行和列,比对HexBiTable[i]和column,若相等,则column所对应的列下标即为i(间接的2进制转10进制)for(int j = 0; j < 4; j++){if(line[j] != HexBiTable[i][j]) //不相等xflag = false; if(column[j] != HexBiTable[i][j]) //不相等yflag = false; }if(xflag == true){x = i;}if(yflag == true){y = i;}}//cout<<x<<", "<<y<<endl;int target = SBox[s][x][y]; //获取S盒对应行列的元素//target换成2进制char数组char *biTarget = new char[5];for(int i = 3, index = 0; i >= 0; i--, index++){  if(target & (1 << i))  biTarget[index] =  '1';  else  biTarget[index] =  '0';  }biTarget[4] = '\0';//cout<<biTarget<<endl;

至此得到此轮的4位输出,按其修改R对应位置,8轮S盒变化后即得到32位的输出结果。

四、运行结果:

(1)不输出中间结果:

中间结果:
(2)16个子密钥:

(3)16轮L和R

(4)其他
其他各个步骤的结果输出语句均在代码中,去掉注释即可输出查看。

DES算法原理C++模拟实现相关推荐

  1. DES算法原理及其实现

    DES算法复杂难懂,但是易于实现.它只对小的位组进行简单的逻辑运算,用硬件和软件实现起来都比较有效. 描述: 分组加密算法, 64位一组: 对称算法: 密钥长度56位:基于加密的两个技术(混乱和扩散的 ...

  2. DES算法原理完整版

    1.所需参数 key:8个字节共64位的工作密钥 data:8个字节共64位的需要被加密或被解密的数据 mode:DES工作方式,加密或者解密 2.初始置换 DES算法使用64位的密钥key将64位的 ...

  3. DES加密算法原理及代码实现

    目录 一.简要描述 二.名词解释 数据填充 分组加密 算法特点 置换 三.加密运算 1.加密运算流程图 2.初始置换 ​ 3.生成子秘钥 PC-1置换 ​ PC-2置换 4.迭代的过程(f函数) f函 ...

  4. DES算法实现(C++版)

    文章目录 一.DES算法原理 二.相关说明 1.初始置换IP 2.子密钥 Ki 的获取 3.密码函数 f 4.尾置换IP-1 三.DES算法具体实现(C++) 一.DES算法原理 DES算法是一种最通 ...

  5. DES算法详解及实现(C语言)

    其他现代密码学算法详解及实现见专栏合集~ DES算法原理 加密过程 (i)算法结构 概述:将明文分为64位的分组,首先对64位码做初始IP置换,再进行16论迭代变换,其中包括ESP三种运算,最后进行逆 ...

  6. DES加密算法原理简介

    简化版流程 3.1 数据加密标准DES DES算法将明文按64位分组,使用的密钥长度为64位(实际参与加密的有56位). 密钥的第8.16.24.-.64位作为校验位,不参与加密 DES的加密思想是对 ...

  7. DES加解密算法原理详解与实现

    [DES密码编写] 1. Equipment (1) operating system version :WIN 10 (2) CPU instruction set: x 64 (3) softwa ...

  8. RC4算法原理、Java实现RC4加密算法、DES AES RC4算法比较

    DES AES RC4算法比较 根据密钥类型的不同,加密算法分为对称和非对称两种.对称加密系统是指加密和解密均采用同一把密钥. 对称加密算法是最常用的加密算法,优势在于算法公开,计算量小,加密效率高. ...

  9. 做diff_Vue3.0时代你必须了解的:diff算法原理和优化

    关注前端公众号 [前端每日一博] 前言 面试官: 你知道 Vue3.0 Object.difineProperty和vue3.0的proxy的区别吗? 你知道 Vue3.0 diff算法原理和它有什么 ...

最新文章

  1. 证明实对称正定矩阵A的Gauss-Seidel法必定收敛(完整过程)
  2. JMM如何解决顺序一致性问题-JMM层面的内存屏障
  3. python 多线程就这么简单(续)
  4. sao java_Java开发中的几种对象的说明(PO,VO,DTO,BO,POJO,DAO,SAO等)
  5. GPS模块运用: GPS轨迹记录
  6. SG90舵机驱动,有代码
  7. 小米 红米【AC2100】一键刷BREED【30秒刷完】小白脑残专用 无需工具TELNET + 检查坏块
  8. ios键盘done中文_iOS键盘事件实现、控制
  9. status计算机语言,status 在c语言中的用法?请高手指教、、、、谢谢
  10. 资阳与“华为”携手共建资阳天府云计算中心
  11. 作用域和作用域链的理解
  12. 国科大学习资料--人工智能原理与算法-第十次作业解析(学长整理)
  13. OPENCV入门教程十一:dilate图像膨胀
  14. Docker 部署 FreeIPA 服务
  15. 计算机二级C语言考试地点,最新计算机二级《C语言》重要考点
  16. Linux系统调用详解(实现机制分析)--linux内核剖析(六)
  17. 电影《在云端》经典对白翻译
  18. OBD车载诊断系统、移动管家车联网汽车OBD诊断系统车辆信息管理硬件
  19. 查看mysql数据库sid_查看数据库sid
  20. 帝国CMS开发主播/直播视频网站源码+WAP/可封装APP运营

热门文章

  1. 中国移动研发出大容量SIM卡
  2. linux中文件类型说明及文件权限
  3. 产业数字化博弈,网易能否继续守正出奇?
  4. 研究生的压力与心理健康-雨课堂期末2022
  5. 为什么需要htons(), ntohl(), ntohs(),htons() 函数
  6. 您需要为千禧一代用户构建应用程序
  7. ffmpeg m3u8 转 MP4
  8. Haproxy加持KeepAlived+进程自动检测
  9. Csrf再识及初识Json劫持
  10. 基于决策树的隐形眼镜类型预测