DES加密算法设计(含程序)
- 格式:doc
- 大小:484.26 KB
- 文档页数:20
des加密原理及流程以DES加密原理及流程为标题,本文将详细介绍DES加密算法的原理和加密流程。
DES(Data Encryption Standard)是一种对称加密算法,由IBM 公司于1977年开发。
DES算法是一种分组密码,每个分组64位,密钥长度为56位。
它使用相同的密钥来进行加密和解密操作,因此也被称为对称加密算法。
DES加密算法的原理基于Feistel网络结构。
其主要包括初始置换、16轮的Feistel运算、逆初始置换和密钥生成四个步骤。
首先是初始置换。
明文会经过一个初始置换IP,将64位明文按照固定的规则重新排列,得到L0和R0,每个部分32位。
接下来是16轮的Feistel运算。
每一轮中,将右半部分Rn-1经过扩展置换(E盒),得到48位的扩展结果。
然后将扩展结果与子密钥Kn进行异或运算,得到的结果再经过S盒代替置换,得到32位结果。
最后,通过P盒置换得到Rn。
在Feistel运算中,Ln等于Rn-1,而Rn等于Ln-1异或f(Rn-1, Kn),其中f是一个复杂的函数。
这样,经过16轮的Feistel运算后,得到的L16和R16即为加密的结果。
然后是逆初始置换。
将L16和R16合并,经过逆初始置换IP-1,得到最终的加密结果。
最后是密钥生成。
DES算法使用56位的密钥,其中8位为奇偶校验位。
首先,将64位密钥经过初始置换PC-1,得到56位的密钥。
然后,将56位密钥分为两个28位的部分,分别进行左移位操作,得到C0和D0。
接下来,根据循环左移的规则,生成16个子密钥Ki。
具体地,每轮循环左移的位数由密钥位数表规定,然后将Cn 和Dn合并,经过PC-2置换,得到子密钥Ki。
DES加密算法的流程可以总结为:初始置换、16轮的Feistel运算、逆初始置换和密钥生成。
通过这些步骤,可以将明文加密为密文。
DES加密算法在信息安全领域得到广泛应用。
然而,由于DES密钥长度较短,易受到暴力破解等攻击手段的威胁,因此在实际应用中,常常采用更加安全的加密算法,如AES(Advanced Encryption Standard)来替代DES。
DES加密算法与解密(带流程图)一、DES加密及解密算法程序源代码:#include <iostream>using namespace std;const static char IP_Table[] = { //IP_Table置换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};const static char Final_Table[] = { //最终置换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};const static char S_Box[8][64] = {//s_box/* S1 */{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},/* S2 */{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,14, 5, 2, 8, 4,3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14},/* S5 */{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},/* S6 */{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},/* S7 */{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},/* S8 */{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}const static char Rar_Table[] = { //压缩置换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};const static char Exp_Table[] = { //扩展置换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, 1const static char P_Table[]={ //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};const static char KeyRar_Table[]={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};//设置全局变量,16轮密钥bool key[16][48]={{0}};void ByteToBit(bool *Out,char *In,int bits) //字节到位转换函数{int i;for(i=0;i<bits;i++)Out[i]=(In[i/8]>>(i%8))&1;}void BitToByte(char *Out,bool *In,int bits)//位到字节转换函数{int i;for(i=0;i<bits/8;i++)Out[i]=0;for(i=0;i<bits;i++)Out[i/8]|=In[i]<<(i%8);}void Xor(bool *InA,const bool *InB,int length) //按位异或for(int i=0;i<length;i++)InA[i]^=InB[i];}void keyfc(char *In) //密钥生成函数{int i,j=0,mov,k,m;bool* key0 = new bool[56];bool* keyin = new bool[64];bool temp;ByteToBit(keyin,In,64); //字节到位的转换for(i=0;i<56;i++) //密钥压缩为56位key0[i]=keyin[KeyRar_Table[i]-1];for(i=0;i<16;i++) //16轮密钥产生{if(i==0||i==1||i==8||i==15)mov=1;elsemov=2;for(k=0;k<mov;k++) //分左右两块循环左移{for(m=0;m<8;m++){temp=key0[m*7];for(j=m*7;j<m*7+7;j++)key0[j]=key0[j+1];key0[m*7+6]=temp;}temp=key0[0];for(m=0;m<27;m++)key0[m]=key0[m+1];key0[27]=temp;temp=key0[28];for(m=28;m<55;m++)key0[m]=key0[m+1];key0[55]=temp;}for(j=0;j<48;j++) //压缩置换并储存key[i][j]=key0[Rar_Table[j]-1];}delete[] key0;delete[] keyin;}void DES(char Out[8],char In[8],bool Type)//加密核心程序,Type=0时加密,反之解密{bool* MW = new bool[64];bool* tmp = new bool[32];bool* PMW = new bool[64];bool* kzmw = new bool[48];bool* keytem = new bool[48];bool* ss = new bool[32];int hang,lie,i;ByteToBit(PMW,In,64);for(int j=0;j<64;j++){MW[j]=PMW[IP_Table[j]-1]; //初始置换}bool *Li=&MW[0],*Ri=&MW[32];for(i=0;i<48;i++) //右明文扩展置换kzmw[i]=Ri[Exp_Table[i]-1];if(Type==0) //DES加密过程{for(int lun=0;lun<16;lun++){for(i=0;i<32;i++)ss[i]=Ri[i];for(i=0;i<48;i++) //右明文扩展置换kzmw[i]=Ri[Exp_Table[i]-1];for(i=0;i<48;i++)keytem[i]=key[lun][i];Xor(kzmw,keytem,48);/*S盒置换*/for(i=0;i<8;i++)hang=kzmw[i*6]*2+kzmw[i*6+5];lie=kzmw[i*6+1]*8+kzmw[i*6+2]*4+kzmw[i*6+3] *2+kzmw[i*6+4];tmp[i*4+3]=S_Box[i][(hang+1)*16+lie]%2;tmp[i*4+2]=(S_Box[i][(hang+1)*16+lie]/2)%2 ;tmp[i*4+1]=(S_Box[i][(hang+1)*16+lie]/4)%2 ;tmp[i*4]=(S_Box[i][(hang+1)*16+lie]/8)%2;}for(i=0;i<32;i++) //P置换Ri[i]=tmp[P_Table[i]-1];Xor(Ri,Li,32); //异或for(i=0;i<32;i++) //交换左右明文Li[i]=ss[i];}}for(i=0;i<32;i++){tmp[i]=Li[i];Li[i]=Ri[i];Ri[i]=tmp[i];}for(i=0;i<64;i++)PMW[i]=MW[Final_Table[i]-1];BitToByte(Out,PMW,64); //位到字节的转换}else //DES解密过程{for(int lun=15;lun>=0;lun--){for(i=0;i<32;i++)ss[i]=Ri[i];for(i=0;i<48;i++) //右明文扩展置换kzmw[i]=Ri[Exp_Table[i]-1];for(i=0;i<48;i++)keytem[i]=key[lun][i];Xor(kzmw,keytem,48);/*S盒置换*/for(i=0;i<8;i++){hang=kzmw[i*6]*2+kzmw[i*6+5];lie=kzmw[i*6+1]*8+kzmw[i*6+2]*4+kzmw[i*6+3] *2+kzmw[i*6+4];tmp[i*4+3]=S_Box[i][(hang+1)*16+lie]%2;tmp[i*4+2]=(S_Box[i][(hang+1)*16+lie]/2)%2 ;tmp[i*4+1]=(S_Box[i][(hang+1)*16+lie]/4)%2 ;tmp[i*4]=(S_Box[i][(hang+1)*16+lie]/8)%2; }for(i=0;i<32;i++) //P置换Ri[i]=tmp[P_Table[i]-1];Xor(Ri,Li,32); //异或for(i=0;i<32;i++) //交换左右明文{Li[i]=ss[i];}}for(i=0;i<32;i++){tmp[i]=Li[i];Li[i]=Ri[i];Ri[i]=tmp[i];}for(i=0;i<64;i++)PMW[i]=MW[Final_Table[i]-1]; BitToByte(Out,PMW,64); //位到字节的转换}delete[] MW;delete[] tmp;delete[] PMW;delete[] kzmw;delete[] keytem;delete[] ss;}bool RunDes(char *Out, char *In, int datalength, char *Key, bool Type) //加密运行函数,判断输入以及对输入文本8字节分割{if( !( Out && In && Key && (datalength=(datalength+7)&0xfffffff8) ) ) return false;keyfc(Key);for(int i=0,j=datalength%8; i<j; ++i,Out+=8,In+=8)DES(Out, In, Type);return true;}int main(){char* Ki = new char[8];char Enter[]="This is the test of DES!"; char* Print = new char[200];int len = sizeof(Enter);int i_mf;cout << "请输入密钥(8位):" <<"\n"; for(i_mf=0;i_mf<8;i_mf++)cin >> Ki[i_mf];cout << "\n";RunDes(Print,Enter,len,Ki,0);//加密cout << "----加密前----" << "\n";for(i_mf=0;i_mf<len;i_mf++)cout << Enter[i_mf];cout << "\n\n";cout << "----加密后----" << "\n";for(i_mf=0;i_mf<len;i_mf++)cout<<Print[i_mf];cout << "\n\n";//此处进行不同密钥输入测试cout << "请输入密钥(8位):" <<"\n"; for(i_mf=0;i_mf<8;i_mf++)cin >> Ki[i_mf];cout << "\n";RunDes(Enter,Print,len,Ki,1);//解密cout << "----解密后----" << "\n";for(i_mf=0;i_mf<len;i_mf++)cout << Enter[i_mf];cout << endl;delete[] Ki;delete[] Print;return 0;}二、程序编译、运行结果图:三、程序总体框架图:读取待加密文本输入密钥DES 加密显示加密后文本再次输入密钥DES 解密显示解密后文本显示错误解密信息密钥错误密钥正确四、程序实现流程图:Enter = 待加密文本分割Enter ,8字节为一段,不足补加,段数为N 初始化:*Print ,i=0,j=0文本第i 段,转为二进制64位初始置换(IP_Table )文本段分为左右两部分左部分(32位)右部分(32)输入8字节密钥转为二进制64位密钥压缩KeyRar_Table (56位)形成16轮密钥合并形成子密钥(48位)S 置换(S_Box )P 置换(P_Table )左右交换,j++最终置换(Final_Table )J<16扩展置换(Exp_Table )i<N异或异或NoYes存入*Print ,i++DES 加密过程结束,输出Print YesNoDES 解密过程为以上逆过程。
DES算法原理完整版1.所需参数key:8个字节共64位的⼯作密钥data:8个字节共64位的需要被加密或被解密的数据 mode:DES⼯作⽅式,加密或者解密2.初始置换DES算法使⽤64位的密钥key将64位的明⽂输⼊块变为64位的密⽂输出块,并把输出块分为L0、R0两部分,每部分均为32位。
初始置换规则如下:注意:这⾥的数字表⽰的是原数据的位置,不是数据158,50,42,34,26,18,10,2,260,52,44,36,28,20,12,4,362,54,46,38,30,22,14,6,464,56,48,40,32,24,16,8,557,49,41,33,25,17, 9,1,659,51,43,35,27,19,11,3,761,53,45,37,29,21,13,5,863,55,47,39,31,23,15,7,即将输⼊的64位明⽂的第1位置换到第40位,第2位置换到第8位,第3位置换到第48位。
以此类推,最后⼀位是原来的第7位。
置换规则是规定的。
L0(Left)是置换后的数据的前32位,R0(Right)是置换后的数据的后32位。
例如:64位输⼊块是D1~D64,则经过初始置换后是D58,D50...D7。
则L0=D58,D50,D12...D8;R0=D57,D49,D41 (7)该置换过程是在64位秘钥的控制下。
3.加密处理--迭代过程经过初始置换后,进⾏16轮完全相同的运算,在运算过程中数据与秘钥结合。
函数f的输出经过⼀个异或运算,和左半部分结合形成新的右半部分,原来的右半部分成为新的左半部分。
每轮迭代的过程可以表⽰如下:Ln = R(n - 1);Rn = L(n - 1)⊕f(Rn-1,kn-1)⊕:异或运算Kn是向第N层输⼊的48位的秘钥,f是以Rn-1和Kn为变量的输出32位的函数3.1函数f函数f由四步运算构成:秘钥置换(Kn的⽣成,n=0~16);扩展置换;S-盒代替;P-盒置换。
DES算法及其程序实现一.D ES算法概述①DES算法为密码体制中的对称密码体制,又被成为美国数据加密标准,是1972年美国IBM公司研制的对称密码体制加密算法。
明文按64位进行分组,密钥长64位,密钥事实上是56位参与DES运算(第8、16、24、32、40、48、56、64位是校验位,使得每个密钥都有奇数个1)分组后的明文组和56位的密钥按位替代或交换的方法形成密文组的加密方法。
②DES算法的特点:分组比较短、密钥太短、密码生命周期短、运算速度较慢。
③DES算法把64位的明文输入块变为64位的密文输出块,它所使用的密钥也是64位,整个算法的主流程图如下:二.D ES算法的编程实现#include <iostream>#include <fstream>using namespace std;const static char ip[] = { //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};const static char fp[] = { //最终置换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};const static char sbox[8][64] = { //s_box/* S1 */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,/* S2 */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,/* S3 */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,/* S4 */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,/* S5 */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,/* S6 */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,/* S7 */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,/* S8 */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 };const static char rar[] = { //压缩置换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};const static char ei[] = { //扩展置换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, 1const static char Pzh[]={ //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};const static char Keyrar[]={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};bool key[16][48]={0},/*rekey[16][48],*/char key_in[8];void ByteToBit(bool *Out,char *In,int bits) //字节到位的转换{int i;for(i=0;i<bits;i++)Out[i]=(In[i/8]>>(i%8))&1;}void BitToByte(char *Out,bool *In,int bits) //位到字节转换{for(int i=0;i<bits/8;i++)Out[i]=0;for(i=0;i<bits;i++)Out[i/8]|=In[i]<<(i%8); //"|="组合了位操作符和赋值操作符的功能}void Xor(bool *InA,const bool *InB,int len) //按位异或{for(int i=0;i<len;i++)InA[i]^=InB[i];}void keyfc(char *In) //获取密钥函数{int i,j=0,mov,k;bool key0[56],temp,keyin[64];ByteToBit(keyin,In,64); //字节到位的转换for(i=0;i<56;i++) //密钥压缩为56位key0[i]=keyin[Keyrar[i]-1];for(i=0;i<16;i++) //16轮密钥产生{if(i==0||i==1||i==8||i==15)mov=1;elsemov=2;for(k=0;k<mov;k++) //分左右两块循环左移{for(int m=0;m<8;m++){temp=key0[m*7];for(j=m*7;j<m*7+7;j++)key0[j]=key0[j+1];key0[m*7+6]=temp;}temp=key0[0];for(m=0;m<27;m++)key0[m]=key0[m+1];key0[27]=temp;temp=key0[28];for(m=28;m<55;m++)key0[m]=key0[m+1];key0[55]=temp;}for(j=0;j<48;j++) //压缩置换并储存key[i][j]=key0[rar[j]-1];}}void DES(char Out[8],char In[8],bool MS)//加密核心程序,ms=0时加密,反之解密{bool MW[64],tmp[32],PMW[64]; //注意指针bool kzmw[48],keytem[48],ss[32];int hang,lie;ByteToBit(PMW,In,64);for(int j=0;j<64;j++){MW[j]=PMW[ip[j]-1]; //初始置换}bool *Li=&MW[0],*Ri=&MW[32];for(int i=0;i<48;i++) //右明文扩展置换kzmw[i]=Ri[ei[i]-1]; //注意指针if(MS==0) //DES加密过程{for(int lun=0;lun<16;lun++){for(i=0;i<32;i++)ss[i]=Ri[i];for(i=0;i<48;i++) //右明文扩展置换kzmw[i]=Ri[ei[i]-1]; //注意指针for(i=0;i<48;i++)keytem[i]=key[lun][i]; //轮密钥Xor(kzmw,keytem,48);/*S盒置换*/for(i=0;i<8;i++){hang=kzmw[i*6]*2+kzmw[i*6+5];lie =kzmw[i*6+1]*8+kzmw[i*6+2]*4+kzmw[i*6+3]*2+kzmw[i*6+4];tmp[i*4+3]=sbox[i][(hang+1)*16+lie]%2;tmp[i*4+2]=(sbox[i][(hang+1)*16+lie]/2)%2;tmp[i*4+1]=(sbox[i][(hang+1)*16+lie]/4)%2;tmp[i*4]=(sbox[i][(hang+1)*16+lie]/8)%2;}for(int i=0;i<32;i++) //P置换Ri[i]=tmp[Pzh[i]-1];Xor(Ri,Li,32); //异或for(i=0;i<32;i++) //交换左右明文{Li[i]=ss[i];}}for(i=0;i<32;i++){tmp[i]=Li[i];Li[i]=Ri[i];Ri[i]=tmp[i];}for(i=0;i<64;i++)PMW[i]=MW[fp[i]-1];BitToByte(Out,PMW,64); //位到字节的转换}else //DES解密过程{for(int lun=15;lun>=0;lun--){for(i=0;i<32;i++)ss[i]=Ri[i];for(int i=0;i<48;i++) //右明文扩展置换kzmw[i]=Ri[ei[i]-1]; //注意指针for(i=0;i<48;i++)keytem[i]=key[lun][i]; //轮密钥Xor(kzmw,keytem,48);/*S盒置换*/for(i=0;i<8;i++){hang=kzmw[i*6]*2+kzmw[i*6+5];lie =kzmw[i*6+1]*8+kzmw[i*6+2]*4+kzmw[i*6+3]*2+kzmw[i*6+4];tmp[i*4+3]=sbox[i][(hang+1)*16+lie]%2;tmp[i*4+2]=(sbox[i][(hang+1)*16+lie]/2)%2;tmp[i*4+1]=(sbox[i][(hang+1)*16+lie]/4)%2;tmp[i*4]=(sbox[i][(hang+1)*16+lie]/8)%2;}for(i=0;i<32;i++) //P置换Ri[i]=tmp[Pzh[i]-1];Xor(Ri,Li,32); //异或for(i=0;i<32;i++) //交换左右明文{Li[i]=ss[i];}}for(i=0;i<32;i++){tmp[i]=Li[i];Li[i]=Ri[i];Ri[i]=tmp[i];}for(i=0;i<64;i++)PMW[i]=MW[fp[i]-1];BitToByte(Out,PMW,64); //位到字节的转换}}void main(){char Ki[8],jm[8],final[8];int i0;cout<<"请输入密钥(8字节):"<<endl;for(i0=0;i0<8;i0++)cin>>Ki[i0];keyfc(Ki);cout<<"请输入明文:"<<endl;for(i0=0;i0<8;i0++)cin>>jm[i0];DES(final,jm,0);cout<<"加密后:"<<endl;//加密for(i0=0;i0<8;i0++)cout<<final[i0];cout<<endl;cout<<"解密后:"<<endl;DES(jm,final,1); //解密for(i0=0;i0<8;i0++)cout<<jm[i0];cout<<endl;}三.实例描述1.加密字母,运行结果如下:2.加密汉字,运行结果如下:。
DES加密算法详解- -对加密解密一直挺喜欢的,可还是没有怎么好好学习过,希望这是一个好的开始。
在网上搜了一下关于DES的说明,发现有些杂乱,所以还是有必要整合一下。
写了一点代码,还没有完成,不过,还不能编译通过,^_^刚看了一下,发现还是说得够模糊的,有机会再整理一下。
昏倒,一直运行不对,今天才仔细查出来,原来问题是出在Des_Data_P(const _b32& input, _b32 output),我的output用了传值调用,失败呀。
应该是Des_Data_P(const _b32& input, _b32 & output)DES算法的入口参数有三个:Key, Data, ModeKey 为64bit密钥,Data为64bit数据,Mode为加密还是解密。
DES算法的过程:1. 对输入的密钥进行变换。
用户的64bit密钥,其中第8,16,24,32,40,48,56,64位是校验位,使得每个密钥都有奇数个1。
所以密钥事实上是56位。
对这56位密钥进行如下表的换位。
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,表的意思是第57位移到第1位,第49位移到第2位,...... 以此类推。
变换后得到56b it数据,将它分成两部分,C[0][28], D[0][28]。
2. 计算16个子密钥,计算方法C[i][28] D[i][28]为对前一个C[i-1][28], D[i-1][28]做循环左移操作。
DES加解密算法的实例DES(Data Encryption Standard)是一种对称密钥加密算法,由IBM于1977年开发。
它是最早广泛使用且被接受的加密算法之一,被用于许多领域,如金融、电子商务和电子邮件等。
DES算法的基本操作单元是64位的数据块,它使用一个56位的密钥对数据进行加密和解密。
下面将对DES算法的加密和解密过程进行详细说明。
1.密钥生成:DES算法使用的密钥是56位的,由8个字节构成。
然而,为了增强安全性和抵抗暴力破解,通常将密钥扩展为64位,即每个字节的最高位被视为奇偶校验位。
密钥生成过程将密钥扩展到64位,并生成16个子密钥。
2.初始置换(IP置换):加密过程开始前,明文数据块会被进行初始置换。
这个初始置换步骤的目的是打乱明文的比特位,使其在加密过程中更难以分析。
3. 轮函数(Feistel函数):DES算法使用了16个相同的轮函数,每个轮函数包含以下步骤:a.扩展置换(E-置换):将32位的数据扩展为48位。
b.异或操作:将扩展得到的48位数据与一个子密钥进行异或操作。
c.S-盒替换:将异或结果分为8个6位的子块,每个子块经过一个6×4的S盒代替变换。
d.P-置换:将S盒代替变换后的结果进行置换操作。
e.得到一个32位的数据。
4.加解密:加密和解密过程中,轮函数通过迭代应用于数据块。
在加密过程中,子密钥按照顺序应用于轮函数;而在解密过程中,子密钥的应用次序与加密过程相反。
DES算法采用了16轮迭代,每轮迭代后,加解密都会进行部分结果的异或操作。
5.逆初始置换(IP-1置换):在加密或解密过程的最后,最终得到的数据块需要进行逆初始置换。
这个逆初始置换的目的是撤销初始置换操作,使得结果与初始的明文或密文一致。
DES算法的实例:1.加密过程:c.将64位的密钥扩展为56位并生成子密钥。
e.经过逆初始置换,得到最终加密的密文。
2.解密过程:a.经过逆初始置换,得到初始的密文数据块。
des加密算法des加密算法是⼀种对称加密算法,通常要求8字节对齐,如果不满⾜8字节,则补全到8字节的整数倍,通常的做法是缺⼏补⼏,⽐如21字节的内容,则需要补三个3./********************************************************** des.h* ⽤户使⽤des算法头⽂件**********************************************************/#ifndef _OPENDESS_H_#define _OPENDESS_H_#ifdef __cplusplusextern "C" {#endif//ab\0defg//⽤户使⽤的函数int DesEnc(unsigned char *pInData,int nInDataLen,unsigned char *pOutData,int *pOutDataLen);//⽤户使⽤函数des解密int DesDec(unsigned char *pInData,int nInDataLen,unsigned char *pOutData,int *pOutDataLen);#ifdef __cplusplus}#endif#endif/******************************************************** des.c* common des......*******************************************************/#include <stdlib.h>#include <string.h>#include <stdio.h>#include "des.h"/*********************************************************data type definition for Des;**********************************************************/#define EN0 0#define DE1 1#define DES_KEYBYTES 128#define DES_KEYLONGS 32#define DES_BLOCKLEN 8typedef struct {unsigned char ek[DES_KEYBYTES];int ekLen;unsigned char dk[DES_KEYBYTES];int dkLen;unsigned char CbcCtx[DES_BLOCKLEN];} DES_CTX;typedef struct {unsigned char ek1[DES_KEYBYTES];int ek1Len;unsigned char dk1[DES_KEYBYTES];int dk1Len;unsigned char ek2[DES_KEYBYTES];int ek2Len;unsigned char dk2[DES_KEYBYTES];int dk2Len;unsigned char CbcCtx[DES_BLOCKLEN];//int IsFirstBlock;} DES3_CTX;static unsigned char pc1[56] = {56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 };static unsigned char pc2[48] = {13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 };static unsigned short bytebit[8] = {0200,0100,040,020,010,04,02,01 };static unsigned char totrot[16] = {1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28}; static unsigned long bigbyte[24] = {0x800000L, 0x400000L, 0x200000L, 0x100000L,0x80000L, 0x40000L, 0x20000L, 0x10000L,0x8000L, 0x4000L, 0x2000L, 0x1000L,0x800L, 0x400L, 0x200L, 0x100L,0x80L, 0x40L, 0x20L, 0x10L,0x8L, 0x4L, 0x2L, 0x1L };//insert digitsstatic unsigned long SP1[64] ={0x01010400l,0x00000000l,0x00010000l,0x01010404l,0x01010004l,0x00010404l,0x00000004l,0x00010000l,0x00000400l,0x01010400l,0x01010404l,0x00000400l,0x01000404l,0x01010004l,0x01000000l,0x00000004l,0x00000404l,0x01000400l,0x01000400l,0x00010400l,0x00010400l,0x01010000l,0x01010000l,0x01000404l,0x00010004l,0x01000004l,0x01000004l,0x00010004l,0x00000000l,0x00000404l,0x00010404l,0x01000000l,0x00010000l,0x01010404l,0x00000004l,0x01010000l,0x01010400l,0x01000000l,0x01000000l,0x00000400l,0x01010004l,0x00010000l,0x00010400l,0x01000004l,0x00000400l,0x00000004l,0x01000404l,0x00010404l,0x01010404l,0x00010004l,0x01010000l,0x01000404l,0x01000004l,0x00000404l,0x00010404l,0x01010400l,0x00000404l,0x01000400l,0x01000400l,0x00000000l,0x00010004l,0x00010400l,0x00000000l,0x01010004l };static unsigned long SP2[64]={0x80108020l,0x80008000l,0x00008000l,0x00108020l,0x00100000l,0x00000020l,0x80100020l,0x80008020l,0x80000020l,0x80108020l,0x80108000l,0x80000000l,0x80008000l,0x00100000l,0x00000020l,0x80100020l,0x00108000l,0x00100020l,0x80008020l,0x00000000l,0x80000000l,0x00008000l,0x00108020l,0x80100000l,0x00100020l,0x80000020l,0x00000000l,0x00108000l,0x00008020l,0x80108000l,0x80100000l,0x00008020l,0x00000000l,0x00108020l,0x80100020l,0x00100000l,0x80008020l,0x80100000l,0x80108000l,0x00008000l,0x80100000l,0x80008000l,0x00000020l,0x80108020l,0x00108020l,0x00000020l,0x00008000l,0x80000000l,0x00008020l,0x80108000l,0x00100000l,0x80000020l, 0x00100020l,0x80008020l,0x80000020l,0x00100020l, 0x00108000l,0x00000000l,0x80008000l,0x00008020l, 0x80000000l,0x80100020l,0x80108020l,0x00108000l }; static unsigned long SP3[64]={0x00000208l,0x08020200l,0x00000000l,0x08020008l, 0x08000200l,0x00000000l,0x00020208l,0x08000200l, 0x00020008l,0x08000008l,0x08000008l,0x00020000l, 0x08020208l,0x00020008l,0x08020000l,0x00000208l, 0x08000000l,0x00000008l,0x08020200l,0x00000200l, 0x00020200l,0x08020000l,0x08020008l,0x00020208l, 0x08000208l,0x00020200l,0x00020000l,0x08000208l, 0x00000008l,0x08020208l,0x00000200l,0x08000000l, 0x08020200l,0x08000000l,0x00020008l,0x00000208l, 0x00020000l,0x08020200l,0x08000200l,0x00000000l, 0x00000200l,0x00020008l,0x08020208l,0x08000200l, 0x08000008l,0x00000200l,0x00000000l,0x08020008l, 0x08000208l,0x00020000l,0x08000000l,0x08020208l, 0x00000008l,0x00020208l,0x00020200l,0x08000008l, 0x08020000l,0x08000208l,0x00000208l,0x08020000l, 0x00020208l,0x00000008l,0x08020008l,0x00020200l }; static unsigned long SP4[64]={0x00802001l,0x00002081l,0x00002081l,0x00000080l, 0x00802080l,0x00800081l,0x00800001l,0x00002001l, 0x00000000l,0x00802000l,0x00802000l,0x00802081l, 0x00000081l,0x00000000l,0x00800080l,0x00800001l, 0x00000001l,0x00002000l,0x00800000l,0x00802001l, 0x00000080l,0x00800000l,0x00002001l,0x00002080l, 0x00800081l,0x00000001l,0x00002080l,0x00800080l, 0x00002000l,0x00802080l,0x00802081l,0x00000081l, 0x00800080l,0x00800001l,0x00802000l,0x00802081l, 0x00000081l,0x00000000l,0x00000000l,0x00802000l, 0x00002080l,0x00800080l,0x00800081l,0x00000001l, 0x00802001l,0x00002081l,0x00002081l,0x00000080l, 0x00802081l,0x00000081l,0x00000001l,0x00002000l, 0x00800001l,0x00002001l,0x00802080l,0x00800081l, 0x00002001l,0x00002080l,0x00800000l,0x00802001l, 0x00000080l,0x00800000l,0x00002000l,0x00802080l }; static unsigned long SP5[64]={0x00000100l,0x02080100l,0x02080000l,0x42000100l, 0x00080000l,0x00000100l,0x40000000l,0x02080000l, 0x40080100l,0x00080000l,0x02000100l,0x40080100l, 0x42000100l,0x42080000l,0x00080100l,0x40000000l, 0x02000000l,0x40080000l,0x40080000l,0x00000000l, 0x40000100l,0x42080100l,0x42080100l,0x02000100l, 0x42080000l,0x40000100l,0x00000000l,0x42000000l, 0x02080100l,0x02000000l,0x42000000l,0x00080100l, 0x00080000l,0x42000100l,0x00000100l,0x02000000l, 0x40000000l,0x02080000l,0x42000100l,0x40080100l, 0x02000100l,0x40000000l,0x42080000l,0x02080100l, 0x40080100l,0x00000100l,0x20000000l,0x42080000l, 0x42080100l,0x00080100l,0x42000000l,0x42080100l, 0x02080000l,0x02000100l,0x40000100l,0x00080000l, 0x00080100l,0x02000100l,0x40000100l,0x00080000l, 0x00000000l,0x40080000l,0x02080100l,0x40000100l }; static unsigned long SP6[64]={0x20000010l,0x20400000l,0x00004000l,0x20404010l, 0x20400000l,0x00000010l,0x20404010l,0x00400000l, 0x20004000l,0x00404010l,0x00400000l,0x20000010l, 0x00400010l,0x20004000l,0x20000000l,0x00004010l,0x00000000l,0x00400010l,0x20004010l,0x00004000l,0x00404000l,0x20004010l,0x00000010l,0x20400010l,0x20400010l,0x00000000l,0x00404010l,0x20404000l,0x00004010l,0x00404000l,0x20404000l,0x20000000l,0x20004000l,0x00000010l,0x20400010l,0x00404000l,0x20404010l,0x00400000l,0x00004010l,0x20000010l,0x00400000l,0x20004000l,0x20000000l,0x00004010l,0x20000010l,0x20404010l,0x00404000l,0x20400000l,0x00404010l,0x20404000l,0x00000000l,0x20400010l,0x00000010l,0x00004000l,0x20400000l,0x00404010l,0x00004000l,0x00400010l,0x20004010l,0x00000000l,0x20404000l,0x20000000l,0x00400010l,0x20004010l };static unsigned long SP7[64] = {0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L,0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L,0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L,0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L,0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L,0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L,0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L,0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L,0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L,0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L,0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L,0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L,0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L,0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L,0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L,0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L };static unsigned long SP8[64] = {0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L,0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L,0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L,0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L,0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L,0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L,0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L,0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L,0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L,0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L,0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L,0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L,0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L,0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L,0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L,0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L };void deskey(unsigned char *key,short edf, unsigned long *kn);void cookey(register unsigned long *raw1, unsigned long *dough);//void cpkey(register unsigned long *into);//void usekey(register unsigned long *from);//void des(unsigned char *inblock,unsigned char *outblock);void scrunch(register unsigned char *outof, register unsigned long *into); void unscrun(register unsigned long *outof, register unsigned char *into); void desfunc(register unsigned long *block,register unsigned long *keys); /***************** DES Function *****************/unsigned long OPENCOMM_DesExpandEncKey(unsigned char *pbDesKey,unsigned long ulDesKeyLen,unsigned char *pbDesEncKey,unsigned long *ulDesEncKeyLen);unsigned long OPENCOMM_DesExpandDecKey(unsigned char *pbDesKey,unsigned long ulDesKeyLen,unsigned char *pbDesDecKey,unsigned long *ulDesDecKeyLen);unsigned long OPENCOMM_DesEncRaw(unsigned char *pbDesEncKey,unsigned long ulDesEncKeyLen,unsigned char *pbInData,unsigned long ulInDataLen,unsigned char *pbOutData,unsigned long *ulOutDataLen);unsigned long OPENCOMM_DesDecRaw(unsigned char *pbDesDecKey,unsigned long ulDesDecKeyLen,unsigned char *pbInData,unsigned long ulInDataLen,unsigned char *pbOutData,unsigned long *ulOutDataLen);int myic_DESDecrypt(unsigned char *pDesKey,int nDesKeyLen,unsigned char *pInData,int nInDataLen,unsigned char *pOutData,int *pOutDataLen);int myic_DESEncrypt(unsigned char *pDesKey,int nDesKeyLen,unsigned char *pInData,int nInDataLen,unsigned char *pOutData,int *pOutDataLen);void deskey(unsigned char *key,short edf, unsigned long *kn){register int i, j, l, m, n;unsigned long pc1m[56],pcr[56];for ( j = 0; j < 56; j++ ){l = pc1[j];m = l & 07;pc1m[j] = (((unsigned long) key[l >> 3] & (unsigned long)bytebit[m] ) ? 1:0); }for ( i = 0;i < 16; i++){if ( edf == DE1 ) m = (15 - i) << 1;else m = i << 1;n = m + 1;kn[m] = kn[n] = 0L;for ( j = 0; j < 28; j++ ){l = j + totrot[i];if ( l < 28 ) pcr[j] = pc1m[l];else pcr[j] = pc1m[l-28];}for (j = 28; j < 56; j++ ){l = j + totrot[i];if ( l < 56 ) pcr[j] = pc1m[l];else pcr[j] = pc1m[l-28];}for ( j = 0; j < 24; j++ ){if ( pcr[pc2[j]] ) kn[m] |= bigbyte[j];if ( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j];}}return;}void cookey(register unsigned long *raw1, unsigned long *dough){register unsigned long *cook,*raw0;register int i;cook = dough;for ( i = 0; i < 16; i++, raw1++ ) {raw0 = raw1++;*cook = (*raw0 & 0x00fc0000L) << 6;*cook |= (*raw0 & 0x00000fc0L) << 10;*cook |= (*raw1 & 0x00fc0000L) >> 10;*cook++ |= (*raw1 & 0x00000fc0L) >> 6;*cook = (*raw0 & 0x0003f000L) << 12;*cook |= (*raw0 & 0x0000003fL) << 16;*cook |= (*raw1 & 0x0003f000L) >> 4;*cook++ |= (*raw1 & 0x0000003fL);}return;}void scrunch(register unsigned char *outof, register unsigned long *into) {*into = (*outof++ & 0xffL) << 24;*into |= (*outof++ & 0xffL) << 16;*into |= (*outof++ & 0xffL) << 8;*into++ |= (*outof++ & 0xffL);*into = (*outof++ & 0xffL) << 24;*into |= (*outof++ & 0xffL) << 16;*into |= (*outof++ & 0xffL) << 8;*into++ |= (*outof & 0xffL);return;}void unscrun(register unsigned long *outof, register unsigned char *into) {*into++ = (unsigned char)((*outof >> 24) & 0xffL);*into++ = (unsigned char)((*outof >> 16) & 0xffL);*into++ = (unsigned char)((*outof >> 8) & 0xffL);*into++ = (unsigned char)( *outof++ & 0xffL);*into++ = (unsigned char)((*outof >> 24) & 0xffL);*into++ = (unsigned char)((*outof >> 16) & 0xffL);*into++ = (unsigned char)((*outof >> 8) & 0xffL);*into = (unsigned char)( *outof & 0xffL);return;}void desfunc(register unsigned long *block,register unsigned long *keys) {register unsigned long fval, work, right, leftt;register int round;leftt = block[0];right = block[1];work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;right ^= work;leftt ^= (work << 4);work = ((leftt >> 16) ^ right) & 0x0000ffffL;right ^= work;leftt ^= (work << 16);work = ((right >> 2) ^ leftt) & 0x33333333L;leftt ^= work;right ^= (work << 2);work = ((right >> 8) ^ leftt) & 0x00ff00ffL;leftt ^= work;right ^= (work << 8);right = ((right << 1) | ((right >>31) & 1L)) & 0xffffffffL;work = (leftt ^ right) & 0xaaaaaaaaL;leftt ^= work;right ^= work;leftt = ((leftt << 1) | ((leftt >> 31)&1L)) & 0xffffffffL;for (round = 0; round < 8; round++) {work = (right << 28) | (right >> 4);work ^= *keys++;fval = SP7[ work & 0x3fL];fval |= SP5[(work >> 8) & 0x3fL];fval |= SP3[(work >> 16) & 0x3fL];fval |= SP1[(work >> 24) & 0x3fL];work = right ^ *keys++;fval |= SP8[ work & 0x3fL];fval |= SP6[(work >> 8) & 0x3fL];fval |= SP4[(work >> 16) & 0x3fL];fval |= SP2[(work >> 24) & 0x3fL];leftt ^= fval;work = (leftt << 28) | (leftt >> 4);work ^= *keys++;fval = SP7[ work & 0x3fL];fval |= SP5[(work >> 8) & 0x3fL];fval |= SP3[(work >> 16) & 0x3fL];fval |= SP1[(work >> 24) & 0x3fL];work = leftt ^ *keys++;fval |= SP8[ work & 0x3fL];fval |= SP6[(work >> 8) & 0x3fL];fval |= SP4[(work >> 16) & 0x3fL];fval |= SP2[(work >> 24) & 0x3fL];right ^= fval;}right = (right << 31) | (right >> 1);work = (leftt ^ right) & 0xaaaaaaaaL;leftt ^= work;right ^= work;leftt = (leftt << 31) | (leftt >> 1);work = ((leftt >> 8) ^ right) & 0x00ff00ffL;right ^= work;leftt ^= (work << 8);work = ((leftt >> 2) ^ right) & 0x33333333L;right ^= work;leftt ^= (work << 2);work = ((right >> 16) ^ leftt) & 0x0000ffffL;leftt ^= work;right ^= (work << 16);work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;leftt ^= work;right ^= (work << 4);*block++ = right;*block = leftt;return;}/*****************************************************************OPENCOMM_DesExpandEncKey : Expand Des Enc Key 扩展des加密密钥Return value:0 : Successother : failedParameters:pbDesKey : 扩展前的DES密钥(8字节) inputulDesKeyLen : 扩展前的DES密钥长度 inputpbDesEncKey : 扩展后的DES加密密钥(128字节) output*ulDesEncKeyLen : 扩展后的DES加密密钥长度 output*****************************************************************/unsigned long OPENCOMM_DesExpandEncKey(unsigned char *pbDesKey,unsigned long ulDesKeyLen,unsigned char *pbDesEncKey,unsigned long *ulDesEncKeyLen){unsigned long kn[32], dough[32];if (ulDesKeyLen != 8)return 0xEE20;deskey(pbDesKey, EN0, kn);cookey(kn, dough);*ulDesEncKeyLen = DES_KEYBYTES; //32 long = 128 bytesmemcpy(pbDesEncKey, dough, *ulDesEncKeyLen);return 0;}/*****************************************************************OPENCOMM_DesExpandDecKey : Expand Des Dec Key 扩展des解密密钥Return value:0 : Successother : failedParameters:pbDesKey : 扩展前的DES密钥(8字节) inputulDesKeyLen : 扩展前的DES密钥长度 inputpbDesDecKey : 扩展后的DES解密密钥(128字节) output*ulDesDecKeyLen : 扩展后的DES解密密钥长度 output*****************************************************************/unsigned long OPENCOMM_DesExpandDecKey(unsigned char *pbDesKey,unsigned long ulDesKeyLen,unsigned char *pbDesDecKey,unsigned long *ulDesDecKeyLen){unsigned long kn[32], dough[32];if (ulDesKeyLen != 8)return 0xEE20;deskey(pbDesKey, DE1, kn);cookey(kn, dough);*ulDesDecKeyLen = DES_KEYBYTES; //32 long = 128 bytesmemcpy(pbDesDecKey, dough, *ulDesDecKeyLen);return 0;}/****************************************************************OPENCOMM_DesEncRaw : Des算法加密⼩整块明⽂8字节Return value:0 : Successother : failedParameters:pbDesEncKey : DES加密密钥 inputulDesEncKeyLen : DES加密密钥长度 inputpbInData : 待加密的明⽂ inputulInDataLen : 待加密的明⽂长度 inputpbOutData : 加密后的密⽂ output*ulOutDataLen : 加密后的密⽂长度 output*****************************************************************/unsigned long OPENCOMM_DesEncRaw(unsigned char *pbDesEncKey,unsigned long ulDesEncKeyLen,unsigned char *pbInData,unsigned long ulInDataLen,unsigned char *pbOutData,unsigned long *ulOutDataLen){unsigned long work[2], ek[DES_KEYLONGS];unsigned char cp[DES_BLOCKLEN];if (ulInDataLen != DES_BLOCKLEN)return 0xEE20;if (ulDesEncKeyLen != DES_KEYBYTES)return 0xEE20;memcpy(cp, pbInData, DES_BLOCKLEN);scrunch(cp,work); // 8 bytes -> 2 longmemcpy(ek, pbDesEncKey, ulDesEncKeyLen);desfunc(work,ek);unscrun(work,cp); // 2 long -> 8 bytesmemcpy(pbOutData, cp, DES_BLOCKLEN);*ulOutDataLen = DES_BLOCKLEN;return 0;}/***************************************************************** OPENCOMM_DesDecRaw : Des算法解密⼩整块密⽂8字节Return value:0 : Successother : failedParameters:pbDesDecKey : DES解密密钥 input ulDesDecKeyLen : DES解密密钥长度 inputpbInData : 待解密的密⽂ inputulInDataLen : 待解密的密⽂长度 inputpbOutData : 解密后的明⽂ output*ulOutDataLen : 解密后的明⽂长度 output*****************************************************************/ unsigned long OPENCOMM_DesDecRaw(unsigned char *pbDesDecKey,unsigned long ulDesDecKeyLen,unsigned char *pbInData,unsigned long ulInDataLen,unsigned char *pbOutData,unsigned long *ulOutDataLen){unsigned long work[2], dk[DES_KEYLONGS];unsigned char cp[DES_BLOCKLEN];if (ulInDataLen != DES_BLOCKLEN)return 0xEE20;if (ulDesDecKeyLen != DES_KEYBYTES)return 0xEE20;memcpy(cp, pbInData, DES_BLOCKLEN);scrunch(cp,work); // 8 bytes -> 2 longmemcpy(dk, pbDesDecKey, ulDesDecKeyLen);desfunc(work,dk);unscrun(work,cp); // 2 long -> 8 bytesmemcpy(pbOutData, cp, DES_BLOCKLEN);// des_enc(pbDesEncKey, pbInData, pbOutData);*ulOutDataLen = DES_BLOCKLEN;return 0;}/********************* DES *********************/int myic_DESEncrypt(unsigned char *pDesKey,int nDesKeyLen,unsigned char *pInData,int nInDataLen,unsigned char *pOutData,int *pOutDataLen){unsigned char DesKeyBuf[32];unsigned char DesEncKeyBuf[128];int EncKeyLen, KeyLen = 0;int retval = 0, loops, i;if(nInDataLen%8 != 0)return 0xEE20;if(nDesKeyLen != 8)return 0xEE20;KeyLen = nDesKeyLen;memcpy(DesKeyBuf, pDesKey, nDesKeyLen);retval = OPENCOMM_DesExpandEncKey(DesKeyBuf, KeyLen, DesEncKeyBuf, (unsigned long *)&EncKeyLen);if(retval != 0)return retval;loops = nInDataLen/8;for(i = 0; i < loops; i++){retval = OPENCOMM_DesEncRaw(DesEncKeyBuf, EncKeyLen, pInData + i*8, 8, pOutData + i*8, (unsigned long *)pOutDataLen);if(retval != 0)return retval;}*pOutDataLen = nInDataLen;return retval;}int myic_DESDecrypt(unsigned char *pDesKey,int nDesKeyLen,unsigned char *pInData,int nInDataLen,unsigned char *pOutData,int *pOutDataLen){unsigned char DesKeyBuf[32];unsigned char DesDecKeyBuf[128];int DecKeyLen, KeyLen = 0;int retval = 0, loops, i;if(nInDataLen%8 != 0)return 0xEE20;if(nDesKeyLen != 8)return 0xEE20;KeyLen = nDesKeyLen;memcpy(DesKeyBuf, pDesKey, nDesKeyLen);retval = OPENCOMM_DesExpandDecKey(DesKeyBuf, KeyLen, DesDecKeyBuf, (unsigned long *)&DecKeyLen);if(retval != 0)return retval;loops = nInDataLen/8;for(i = 0; i < loops; i++){retval = OPENCOMM_DesDecRaw(DesDecKeyBuf, DecKeyLen, pInData + i*8,8, pOutData + i*8, (unsigned long *)pOutDataLen);if(retval != 0)return retval;}*pOutDataLen = nInDataLen;return retval;}//对称明⽂数据打padingvoid CW_dataPadAdd(int tag, unsigned char *date, unsigned int dateLen,unsigned char **padDate, unsigned int *padDateLen){int i, padLen;unsigned char *pTmp = NULL;pTmp = (unsigned char *)malloc(dateLen+24);if (pTmp == NULL){*padDate = NULL;return ;}memset(pTmp, 0, dateLen+24);memcpy(pTmp, date, dateLen);if (tag == 0){padLen = 8 - dateLen % 8;for (i=0; i<padLen; i++){pTmp[dateLen+i] = (char)padLen;}*padDateLen = dateLen + padLen;}else{padLen = 16 - dateLen % 16;for (i=0; i<padLen; i++){pTmp[dateLen+i] = (char)padLen;}}*padDateLen = dateLen + padLen;*padDate = pTmp;}#define USER_PASSWORD_KEY "abcd1234"//数据加密int DesEnc(unsigned char *pInData,int nInDataLen,unsigned char *pOutData,int *pOutDataLen){int rv;unsigned char *padDate = NULL;unsigned int padDateLen = 0;CW_dataPadAdd(0, pInData, (unsigned int )nInDataLen, &padDate, &padDateLen);rv = myic_DESEncrypt((unsigned char *)USER_PASSWORD_KEY, strlen(USER_PASSWORD_KEY), padDate, (int)padDateLen, pOutData, pOutDataLen);if (rv != 0){if (padDate != NULL){free(padDate);}return rv;}if (padDate != NULL){free(padDate);}return 0;}//数据加密int DesEnc_raw(unsigned char *pInData,int nInDataLen,unsigned char *pOutData,int *pOutDataLen){int rv;unsigned char *padDate = NULL;unsigned int padDateLen = 0;rv = myic_DESEncrypt((unsigned char *)USER_PASSWORD_KEY, strlen(USER_PASSWORD_KEY), pInData, (int)nInDataLen, pOutData, pOutDataLen);if (rv != 0){return rv;}return 0;}//解密分配内存错误#define ERR_MALLOC 20//密码长度不是8的整数倍, 不合法#define ERR_FILECONT 20//⽤户使⽤函数des解密int DesDec(unsigned char *pInData,int nInDataLen,unsigned char *pOutData,int *pOutDataLen){int rv;char padChar;unsigned char *tmpPlain = NULL;tmpPlain = (unsigned char *)malloc(nInDataLen+24);if (tmpPlain == NULL){return ERR_MALLOC;}memset(tmpPlain, 0, nInDataLen+24);//解密rv = myic_DESDecrypt((unsigned char *)USER_PASSWORD_KEY, strlen(USER_PASSWORD_KEY), pInData, nInDataLen, tmpPlain, pOutDataLen);if (rv != 0){if (tmpPlain != NULL) free(tmpPlain);return rv;}//去padingpadChar = tmpPlain[*pOutDataLen - 1];if ( (int)padChar<=0 || (int)padChar>8) //异常处理{if (tmpPlain) free(tmpPlain);return ERR_FILECONT;}*pOutDataLen = *pOutDataLen - (int)padChar;//memset(tmpPlain + *pOutDataLen, 0, (int)padChar);memcpy(pOutData, tmpPlain, *pOutDataLen);if (tmpPlain) free(tmpPlain);return 0;}//⽤户使⽤函数des解密int DesDec_raw(unsigned char *pInData,int nInDataLen,unsigned char *pOutData,int *pOutDataLen){int rv;//char padChar;//unsigned char *tmpPlain = NULL;/*tmpPlain = (unsigned char *)malloc(nInDataLen+24);if (tmpPlain == NULL){return ERR_MALLOC;}memset(tmpPlain, 0, nInDataLen+24);*///解密rv = myic_DESDecrypt((unsigned char *)USER_PASSWORD_KEY, strlen(USER_PASSWORD_KEY), pInData, nInDataLen, pOutData, pOutDataLen);if (rv != 0){//if (tmpPlain != NULL) free(tmpPlain);return rv;}/*//去padingpadChar = tmpPlain[*pOutDataLen - 1];if ( (int)padChar<=0 || (int)padChar>8) //异常处理{if (tmpPlain) free(tmpPlain);return ERR_FILECONT;}*pOutDataLen = *pOutDataLen - (int)padChar;//memset(tmpPlain + *pOutDataLen, 0, (int)padChar);memcpy(pOutData, tmpPlain, *pOutDataLen);if (tmpPlain) free(tmpPlain);*/return 0;}。
DES对称加密算法详解和c++代码实现(带样例和详细的中间数据)特点:1.DES是对称性加密算法,即加密和解密是对称的,⽤的是同⼀个密钥2.DES只处理⼆进制数据,所以需要将明⽂转换成为2进制数据3.DES每次处理64位的数据,所以应该将明⽂切割成64位的分组,当最后⼀组数据不⾜64位的时候,⾼位补04.DES使⽤64位的密钥,但因为密钥中的每8位会被忽略,所以有效的密钥长度是56位,从⽽产⽣16个48位的⼦密钥(变换过程后⾯会说明)5.每64位数据⼀个块,是DES的永恒组织⽅式具体样例分析:(仅以⼀组64位数据为例分析加密过程)明⽂M是:8787878787878787密钥K是:0E329232EA6D0D73上⾯的信息都是16进制的,转换为2进制明⽂M是:0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111密钥K是:00010011 00110100 01010111 01111001 10011011 10111100 11011111 11110001第⼀步:根据密钥⽣成16个⼦密钥1.根据密钥初始置换表将64位的密钥转化为58位的密钥57 49 41 33 25 17 91 58 50 42 34 26 1810 2 59 51 43 35 2719 11 3 60 52 44 3663 55 47 39 31 23 157 62 54 46 38 30 2214 6 61 53 45 37 2921 13 5 28 20 12 4由于上表中第⼀个元素为57,这将使原秘钥的第57位变换为新秘钥K+的第1位。
同理,原秘钥的第49位变换为新秘钥的第2位……原秘钥的第4位变换为新秘钥的最后⼀位。
注意原秘钥中只有56位会进⼊新秘钥,上表也只有56个元素。
原密钥K:00010011 00110100 01010111 01111001 10011011 10111100 11011111 11110001新密钥K:1111000 0110011 0010101 0101111 0101010 1011001 1001111 00011112.将新密钥拆分成C0和D0,每组都有28位⽐如新密钥C0:1111000 0110011 0010101 0101111D0:0101010 1011001 1001111 00011113.根据密钥轮次左移表,左移特定的位数1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 161 12 2 2 2 2 2 1 2 2 2 2 2 2 1⽐如第⼀轮是左移1位,第⼆轮也是左移1位,第三轮是左移两位所以C1:1110000110011001010101011111D1:1010101011001100111100011110下⾯给出C1,D1到C16,D16的数据:C1 = 1110000110011001010101011111D1 = 1010101011001100111100011110C2 = 1100001100110010101010111111D2 = 0101010110011001111000111101C3 = 0000110011001010101011111111D3 = 0101011001100111100011110101C4 = 0011001100101010101111111100D4 = 0101100110011110001111010101C5 = 1100110010101010111111110000D5 = 0110011001111000111101010101C6 = 0011001010101011111111000011D6 = 1001100111100011110101010101C7 = 1100101010101111111100001100D7 = 0110011110001111010101010110C8 = 0010101010111111110000110011D8 = 1001111000111101010101011001C9 = 0101010101111111100001100110D9 = 0011110001111010101010110011C10 = 0101010111111110000110011001D10 = 1111000111101010101011001100C11 = 0101011111111000011001100101D11 = 1100011110101010101100110011C12 = 0101111111100001100110010101D12 = 0001111010101010110011001111C13 = 0111111110000110011001010101D13 = 0111101010101011001100111100C14 = 1111111000011001100101010101D14 = 1110101010101100110011110001C15 = 1111100001100110010101010111D15 = 1010101010110011001111000111C16 = 1111000011001100101010101111D16 = 0101010101100110011110001111需要记住的是:每⼀对Cn 和 Dn都是由前⼀对Cn-1 和 Dn-1移位⽽来!4.得到Cn,Dn后合并CnDn,然后根据密钥压缩置换表将56位密钥压缩成48位的⼦密钥密钥压缩置换表:14 17 11 24 1 53 28 15 6 21 1023 19 12 4 26 816 7 27 20 13 241 52 31 37 47 5530 40 51 45 33 4844 49 39 56 34 5346 42 50 36 29 32每对⼦秘钥有56位,但PC-2仅仅使⽤其中的48位。
程序设计文档(一)设计原理:本次作业是完成DES加密算法的。
DES加密算法是用64位明文和64位密钥进行相关的运算得到。
具体的实现步骤为:1)将输入的明文字符转为64位的二进制代码2)将输入的密钥字符转为64位的二进制代码3)将64位明文二进制进行位变换4)将变换后的明文二进制分为左右两个32数组5)将32位右数组扩展为48位数组6)将64位密钥进行除奇偶转换变成56位数组7)将56位数组等分为ab两个数组8)将a,b两个数组分别进行移位9)将移位后的ab两个数组进行合并成56位数组10)将合并后的56位数组变换成48位数组11)在第10步生成的48位数组和第5步生成的48位进行异或得到新的48位数组12)新的48位数组进行s盒变换后得到32位数组13)将32位数组进行变换得到新的32位数组14)新的32位数组和明文的左数组进行异或得到新的右数组,原来的右数组变成新的左数组15)回到第5步一共迭代16次16)最后将右左数组合并成64位数组17)64位数组进行变换得到新的64位数组18)将64位数组变换成8个字符这次作业要求用类的思想来解决,不过我没有很好的把加密算法抽象成类的概念,只是把整个大的加密算法当成一个类,每次加密都是一个类,所有的子函数都作为算法类的公有函数。
或许可以把明文抽象成一个类,密文又抽象成一个类,把他们共有的函数作为这个类的公有函数;又或许把几个函数作为一个类的公有函数,但是这样只是采用了类的形式而已并非很好的运用类的思想。
本次作业采取的是第一个把整个大的加密算法当为一个类的方法。
(二)设计工作流程(三)程序代码#include<iostream>#include<string>using namespace std;class wangxianDES{public:void sr(char a[8]);//将输入的字符转入shur字符数组里去void mwerjinzhi();//明文进行二进制转换,并放入mingwen[64]数组里void merjinzhi();//密钥进行二进制转换,并放入miyue[64]数组里 void bmingwen();//64位初始明文进行移位变换,并放入mingwenbianhuan[64]数组里void fenmingwen();//变换后的明文分为r和l两个32位数组,放入mingwenr[32]和mingwenl[32]void kuozhan();//r数组由32位扩展到48位,放到mingwenrk[48] void cjo();//64位密钥除去奇偶位变成56位,放到miyuecjo[56] void df();//将56位密钥等分成a和b两个28位的数组,放到miyuea[28]和miyueb[28]void ayw(int n);//a数组进行移位void byw(int n);//b数组进行移位void hb();//将移位后的a和b数组合并,放到miyuehb[56]void bh();//合并后将56位数组变换成48位数组,放到miyuehbh[48] void tyh();//将扩展后的r数组和合并后的48位数组进行异或运算,放到yh[48]void s();//对48位数据进行s盒变换,得到32位数据放到sbh[32] void sh();//sbh[32]的数据再变换放到szbh[32]里void zyh();//将szbh[32]和mingwenl[32]异或放到mingwenr[32]里void zhb();//最后将mingwenr[32]和mingwenl[32]合并到zh[64]里void zzz();//zh[64]再变换放到aaa[64]里int aaa[64];private:char shur[8];//定义了所需要的数组,具体用途上边函数注释里提到int bhs[8], mingwen[64],mingwenbianhuan[64],mingwenl[32],mingwenr[32],mingwenrk[48],miyue[64],miyuecjo[56],miyuea[28],miyueb[28],miyueyw[16],mi yuehb[56],miyuehbh[48],yh[48],sbh[32],szbh[32],zhong[32],zh[64];};int mwbhjz[64]={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};//明文变换所用到的变换矩阵intmwrkzjz[48]={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};//mingwenr[32]扩展所用到的变换矩阵int mycjojz[56]= {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};//密钥除奇偶位用到的变换矩阵int myyw[16]={1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1};//密钥移位用到的矩阵int myhbhzj[48]= {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 sbhjz[32]= {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};//密钥合并后变换用到的矩阵int zhjz[64]={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位变换的矩阵int B[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};//s盒变换的矩阵int C[4][16]= {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};//s盒变换的矩阵int D[4][16]= {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};//s盒变换的矩阵int E[4][16]= {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};//s盒变换的矩阵int F[4][16]= {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};//s盒变换的矩阵int G[4][16]= {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};//s盒变换的矩阵int H[4][16]= {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,//s盒变换的矩阵6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12};int I[4][16]= {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};//s盒变换的矩阵void wangxianDES::sr(char a[8]){ int i;for (i=0;i<8;i++)shur[i]=a[i];cout<<"将输入的字符转入shur字符数组里去"<<endl;}void wangxianDES::mwerjinzhi(){ int a=8,i,j;for(j=0;j<8;j++){ for(i=8;i>0;i--){mingwen[i+a-1]=shur[j]%2;shur[j]=shur[j]/2;}a=a+8;}cout<<"明文进行二进制转换,并放入mingwen[64]数组里"<<endl;} void wangxianDES::merjinzhi(){ int a=8;int i,j;for(j=0;j<8;j++){ for(i=8;i>0;i--){miyue[i+a-1]=shur[j]%2;shur[j]=shur[j]/2;}a=a+8;}cout<<"密钥进行二进制转换,并放入miyue[64]数组里"<<endl; } void wangxianDES::bmingwen(){ int i;for(i=0;i<64;i++)mingwenbianhuan[i]=mingwen[mwbhjz[i]-1];cout<<"64位初始明文进行移位变换,并放入mingwenbianhuan[64]数组里"<<endl;}void wangxianDES::fenmingwen(){ int i;for(i=0;i<32;i++)mingwenl[i]=mingwenbianhuan[i];for(i=0;i<32;i++)mingwenr[i]=mingwenbianhuan[i+32];cout<<"变换后的明文分为r和l两个32位数组,放入mingwenr[32]和mingwenl[32]"<<endl;}void wangxianDES::kuozhan(){ int i;for(i=0;i<48;i++)mingwenrk[i]=mingwenr[mwrkzjz[i]-1];cout<<"r数组由32位扩展到48位,放到mingwenrk[48]"<<endl;} void wangxianDES::cjo(){ int i;for(i=0;i<56;i++)miyuecjo[i]=miyue[mycjojz[i]-1];cout<<"64位密钥除去奇偶位变成56位,放到miyuecjo[56]"<<endl;}void wangxianDES::df(){ int i;for(i=0;i<28;i++)miyuea[i]=miyuecjo[i];for(i=0;i<28;i++)miyueb[i]=miyuecjo[i+28];cout<<"将56位密钥等分成a和b两个28位的数组,放到miyuea[28]和miyueb[28]"<<endl;}void wangxianDES::ayw(int n){ int a,i;a=myyw[n];if(a==1){int b;b=miyuea[0];for(i=0;i<27;i++)miyuea[i]=miyuea[i+1];miyuea[28]=b;}else{int b,c;b=miyuea[0];c=miyuea[1];for(i=0;i<26;i++)miyuea[i]=miyuea[i+2];miyuea[26]=b;miyuea[27]=c;}cout<<"a数组进行移位"<<endl;}void wangxianDES::byw(int n){ int a,i;a=myyw[n];if(a==1){int b;b=miyueb[0];for(i=0;i<27;i++)miyueb[i]=miyueb[i+1];miyueb[28]=b;}else{int b,c;b=miyueb[0];c=miyueb[1];for(i=0;i<26;i++)miyueb[i]=miyueb[i+2];miyueb[26]=b;miyueb[27]=c;}cout<<"b数组进行移位"<<endl;}void wangxianDES::hb(){ int i;for(i=0;i<28;i++)miyuehb[i]=miyuea[i];for(i=0;i<28;i++)miyuehb[i+28]=miyueb[i];cout<<"将移位后的a和b数组合并,放到miyuehb[56]"<<endl;} void wangxianDES::bh(){ int i;for(i=0;i<48;i++)miyuehbh[i]=miyuehb[myhbhzj[i]-1];cout<<"合并后将56位数组变换成48位数组,放到miyuehbh[48]"<<endl;}void wangxianDES::tyh(){ int i;for(i=0;i<48;i++){if(miyuehbh[i]==mingwenrk[i])yh[i]=0;else yh[i]=1;}cout<<"将扩展后的r数组和合并后的48位数组进行异或运算,放到yh[48]"<<endl;}void wangxianDES::s(){ int a,b;a=yh[0]*2+yh[5];b=yh[1]*8+yh[2]*4+yh[3]*2+yh[4];bhs[0]=B[a][b];a=yh[6]*2+yh[11];b=yh[7]*8+yh[8]*4+yh[9]*2+yh[10];bhs[1]=C[a][b];a=yh[12]*2+yh[17];b=yh[13]*8+yh[14]*4+yh[15]*2+yh[16];bhs[2]=D[a][b];a=yh[18]*2+yh[23];b=yh[19]*8+yh[20]*4+yh[21]*2+yh[22];bhs[3]=E[a][b];a=yh[24]*2+yh[29];b=yh[25]*8+yh[26]*4+yh[27]*2+yh[28];bhs[4]=F[a][b];a=yh[30]*2+yh[35];b=yh[31]*8+yh[32]*4+yh[33]*2+yh[34];bhs[5]=G[a][b];a=yh[36]*2+yh[41];b=yh[37]*8+yh[38]*4+yh[39]*2+yh[40];bhs[6]=H[a][b];a=yh[42]*2+yh[47];b=yh[43]*8+yh[44]*4+yh[45]*2+yh[46];bhs[7]=I[a][b];int k=8,i,j;for(j=0;j<8;j++){ for(i=4;i>0;i--){sbh[i+k-1]=bhs[j]%2;bhs[j]=bhs[j]/2;}k=k+8;}cout<<"对48位数据进行s盒变换,得到32位数据放到sbh[32]"<<endl;}void wangxianDES::sh(){ int i;for(i=1;i<32;i++)szbh[i]=sbh[sbhjz[i]-1];cout<<"sbh[32]的数据再变换放到szbh[32]里"<<endl;}void wangxianDES::zyh(){ int i;for(i=1;i<32;i++){ zhong[i]=mingwenr[i];if(szbh[i]==mingwenl[i])mingwenr[i]=0;else mingwenr[i]=1;mingwenl[i]=zhong[i];}cout<<"将szbh[32]和mingwenl[32]异或放到mingwenr[32]里,原来mingwenr里的转到mingwenl里"<<endl;}void wangxianDES::zhb(){ int i;for(i=0;i<32;i++)zh[i]=mingwenr[i];for(i=0;i<32;i++)zh[i+32]=mingwenl[i];cout<<"最后将mingwenr[32]和mingwenl[32]合并到zh[64]里"<<endl;}void wangxianDES::zzz(){ int i;for(i=0;i<64;i++)aaa[i]=zh[zhjz[i]-1];cout<<"zh[64]再变换放到aaa[64]里"<<endl;}void main(){ wangxianDES A;char shuru[8],shuchu[8];int p;int w, y;cout<<"输入明文(小于9个字符)"<<endl;cin>>shuru;A.sr(shuru);A.mwerjinzhi();cout<<"输入密钥(8个字符)"<<endl;cin>>shuru;A.sr(shuru);A.merjinzhi();A.bmingwen();A.fenmingwen();A.cjo();A.df();for(p=0;p<16;p++){ A.ayw(p);A.byw(p);A.hb();A.bh();A.kuozhan();A.tyh();A.s();A.sh();A.zyh();}A.zhb();A.zzz();cout<<"加密后的密文二进制"<<endl;for(y=0;y<64;y++){cout<<A.aaa[y]<<" ";p=y+1;if(p%8==0)cout<<endl;}cout<<endl;w=0;cout<<"加密后的8位密文"<<endl;for(p=0;p<8;p++){(char)shuchu[p]=A.aaa[7+w]+A.aaa[6+w]*2+A.aaa[5+w]*4+A.aaa[4+w ]*8+A.aaa[3+w]*16+A.aaa[2+w]*32+A.aaa[1+w]*64+A.aaa[0+w]*128;cout<<shuchu[p];w=w+8;}}(四)运行结果(五)设计总结本次作业是按照自己的思路和想法来完成的,最后得到加密后的密文。
信息安全概论·课程设计DES加密的C语言实现目录摘要....................................................... 错误!未定义书签。
Abstract ................................................... 错误!未定义书签。
关键词..................................................... 错误!未定义书签。
1.算法描述................................................ 错误!未定义书签。
1.1加/解密算法的一般原理............................... 错误!未定义书签。
1.2加/解密机制的应用................................... 错误!未定义书签。
2.S盒设计................................................ 错误!未定义书签。
3.DES程序实例与分析...................................... 错误!未定义书签。
4.DES实例运行结果........................................ 错误!未定义书签。
5.结语.................................................... 错误!未定义书签。
6.参考文献................................................. 错误!未定义书签。
信息安全概论·课程设计DES加密的C语言实现C language achieve DES algorithm摘要DES算法是一种数据加密算法,自从1977年公布以来,一直是国际上的商用保密通信和计算机通信的最常用的加密标准。
des密码算法程序c语言一、概述DES(数据加密标准)是一种常用的对称加密算法,它采用64位的密钥,对数据进行加密和解密。
本程序使用C语言实现DES算法,包括密钥生成、数据加密和解密等操作。
二、算法实现1.密钥生成:使用初始置换算法IP(56位)将明文转化为56位的分组,再将该分组经过一系列的逻辑函数F进行6轮处理,最终生成一个56位的密文。
其中密钥包括56位数据位和8位奇偶校验位。
2.数据加密:将需要加密的数据转化为56位的分组,再经过DES 算法处理,得到密文。
3.数据解密:将密文经过DES算法处理,还原成原始明文。
三、程序代码```c#include<stdio.h>#include<string.h>#include<stdlib.h>#include<time.h>//DES算法参数定义#defineITERATIONS6//加密轮数#defineKEY_LENGTH8//密钥长度,单位为字节#defineBLOCK_SIZE8//数据分组长度,单位为字节#definePADDINGPKCS7Padding//填充方式#defineMAX_INPUT_LENGTH(BLOCK_SIZE*2)//数据输入的最大长度//初始置换函数voidinit_permutation(unsignedcharinput[BLOCK_SIZE]){inti;for(i=0;i<BLOCK_SIZE;i++){input[i]=i;}}//逻辑函数F的定义voidlogic_function(unsignedcharinput[BLOCK_SIZE],unsigned charoutput[BLOCK_SIZE]){inti;for(i=0;i<BLOCK_SIZE;i++){output[i]=input[(i+1)%BLOCK_SIZE]^input[i]^(i+1)/BLOCK_SI ZE;}}//DES算法主函数voiddes_encrypt(unsignedchar*input,unsignedchar*output){ unsignedcharkey[KEY_LENGTH];//密钥数组unsignedchariv[BLOCK_SIZE];//初始置换的输入数组unsignedcharciphertext[MAX_INPUT_LENGTH];//密文数组unsignedcharpadding[BLOCK_SIZE];//填充数组unsignedintlength=strlen((char*)input);//数据长度(以字节为单位)unsignedintpadding_length=(length+BLOCK_SIZE-1)%BLOCK_SIZE;//需要填充的字节数unsignedintround=0;//加密轮数计数器unsignedintj=0;//数据指针,用于循环读取数据和填充数据intkey_offset=((1<<(32-KEY_LENGTH))-1)<<(32-(ITERATIONS*BLOCK_SIZE));//密钥索引值,用于生成密钥数组和填充数组的初始值unsignedintk=0;//DES算法中每个轮次的密钥索引值,用于生成每个轮次的密钥数组和填充数组的值unsignedintkplus1=(k+1)%((1<<(32-BLOCK_SIZE))-1);//DES算法中每个轮次的密钥索引值加一后的值,用于下一个轮次的密钥生成charseed[32];//使用MD5作为初始种子值生成随机数序列chartmp[MAX_INPUT_LENGTH];//临时变量数组,用于数据交换和中间计算结果存储等操作time_tt;//时间戳变量,用于生成随机数序列的种子值srand((unsignedint)time(&t));//设置随机数种子值,确保每次运行生成的随机数序列不同init_permutation(iv);//初始置换操作,将输入数据转化为56位分组(需要重复填充时)或一个随机的分组(不需要重复填充时)memcpy(key,key_offset,sizeof(key));//将初始化的密钥数组复制到相应的位置上,以便于接下来的轮次生成不同的密钥值memcpy(padding,seed,sizeof(seed));//将种子值复制到填充数组中,以便于接下来的轮次生成不同的随机数序列值for(round=0;round<ITERATIONS;round++){//进行加密轮次操作,每轮包括。
DES加密算法的JAVA实现DES是一种对称加密算法,它将明文划分为64位的数据块,并对每个数据块进行一系列的转换和替代操作,最终生成密文。
在Java中,可以使用javax.crypto包提供的API来实现DES加密算法。
首先,需要导入javax.crypto包和java.security包。
```javaimport javax.crypto.Cipher;import javax.crypto.spec.SecretKeySpec;import java.security.Key;``````javapublic class DESUtilprivate static final String ALGORITHM = "DES";public static Key generateKey(byte[] keyData) throws Exceptionreturn new SecretKeySpec(keyData, ALGORITHM);}```接下来,我们需要编写加密和解密的方法。
```javapublic class DESUtil//...public static byte[] encrypt(byte[] data, Key key) throws ExceptionCipher cipher = Cipher.getInstance(ALGORITHM);cipher.init(Cipher.ENCRYPT_MODE, key);return cipher.doFinal(data);}public static byte[] decrypt(byte[] encryptedData, Key key) throws ExceptionCipher cipher = Cipher.getInstance(ALGORITHM);cipher.init(Cipher.DECRYPT_MODE, key);return cipher.doFinal(encryptedData);}```在上述代码中,encrypt方法用于将明文数据加密成密文,decrypt 方法用于将密文数据解密成明文。
des加密算法例题详解DES加密算法例题详解什么是DES加密算法?DES(Data Encryption Standard)是一种对称加密算法,由美国联邦政府于1977年确定为非机密政府通信的标准。
DES是一种块密码,以64位为块长度,使用56位的密钥对数据进行加密和解密。
DES加密算法的流程1.首先,将输入数据分组为64位的块。
2.然后,根据规定的密钥生成16个48位的子密钥。
3.接下来,使用生成的子密钥对数据进行16轮的加密和解密操作。
4.最后,将加密或解密后的数据进行合并,得到最终的结果。
DES加密算法的例题下面通过一个例题来详细解释DES加密算法的过程。
假设输入数据为:“Hello World!”,密钥为:“SecretKey”。
1. 数据分组将输入数据“Hello World!” 分组为 64 位块:•第一个块:“Hello Wo”)•第二个块:“rld!”)2. 生成子密钥根据密钥“SecretKey”,使用DES算法生成 16 个 48 位的子密钥。
3. 加密操作对每个数据块进行 16 轮的加密操作。
•第一轮加密:–输入数据块:““(”Hello Wo”)–扩展置换(E-Box):–密钥:“SubKey1”–异或运算:–S 盒代替:–P 盒置换:–交换左右:–加密结果:“11”•第二轮加密:–输入数据块:““(”rld!“)–扩展置换(E-Box):–密钥:“SubKey2”–异或运算:–S 盒代替:–P 盒置换:–交换左右:–加密结果:“10”…4. 合并结果将加密后的数据块进行合并,得到最终的加密结果。
•加密结果:“”总结DES加密算法是一种经典的对称加密算法,通过对输入数据进行分组、生成子密钥、多轮加密操作和结果合并,实现数据的加密和解密。
它在信息安全领域有着广泛的应用,但由于密钥长度较短,已被认为不够安全。
DES加密算法的安全性问题尽管DES加密算法在过去是被广泛采用的标准算法,但是它的密钥长度较短,只有56位,容易受到穷举攻击。
des算法的产生过程及具体计算步骤# DES算法的运作原理DES(Data Encryption Standard)是一种对称加密算法,用于保护数据的机密性和完整性。
该算法由IBM的Horst Feistel设计,于1977年成为美国联邦信息处理标准(FIPS)。
## 工作原理DES算法采用分组密码的方式对数据进行加密和解密,每组数据长度为64位。
整个算法涉及到初始置换、16轮迭代以及逆初始置换三个主要步骤。
### 初始置换初始置换是DES算法的第一步,它将原始64位输入数据按照一个预定义的顺序进行重新排列。
这个置换的目的是为了增加算法的复杂性,增加输入数据与输出数据之间的关联性。
### 轮函数DES算法中的核心是轮函数,它接收32位的输入并产生32位的输出。
轮函数包括四个主要的步骤:扩展置换、S盒置换、P盒置换和密钥混淆。
- 扩展置换:将输入32位数据扩展为48位,以增加数据的混淆性和分散性。
- S盒置换:将48位数据分成8个6位的块,并通过8个不同的S盒(Substitution Box)进行替换。
S盒是一种非线性的变换,用于混淆数据。
- P盒置换:对32位数据进行重新排列,以增加加密后数据的扩散性和随机性。
- 密钥混淆:将48位数据与加密轮次对应的轮密钥进行异或操作,以混淆数据。
### 循环结构DES算法包含16轮迭代,每轮迭代都使用不同的子密钥进行加密和解密。
每一轮的具体操作包括将输入数据分为左右两个32位的块,并进行相应的置换、轮函数变换和轮密钥的更新。
### 逆初始置换DES算法的最后一步是逆初始置换,它与初始置换类似,将最后一轮的输出按照逆序排列,得到最终的加密(或解密)结果。
## 算法安全性DES算法在提出时是一种相对较安全的加密算法,但随着计算机计算能力的增强,它的弱点和局限性逐渐显露出来。
如今,DES算法已经不再被推荐使用,因为它的56位密钥长度过短,易受到暴力破解攻击。
为了提高数据的安全性,后续的加密标准例如AES(Advanced Encryption Standard)已经取代了DES算法。
摘要随着计算机的应用和网络技术的不断发展,网络间的通讯量不断的加大,人们的个人信息、网络间的文件传递、电子商务等方面都需要大力的保护,文件加密技术也就随之产生。
文件的加密主要是由加密算法实现,加密算法有多种,常见的有RSA、DES、MD5等。
本程序设计对文件的加密使用的是DES加密算法。
DES是分块加密的。
DES用软件进行解码需要用很长时间,而用硬件解码速度非常快,1977年,人们估计要耗资两千万美元才能建成一个专门计算机用于DES的解密,而且需要12个小时的破解才能得到结果。
所以,当时DES被认为是一种十分强壮的加密方法。
但今天,只需二十万美元就可以制造一台破译DES的特殊的计算机,所以现在 DES 对要求“强壮”加密的场合已经不再适用了。
Java语言具有简单、安全、可移植、面向对象、健壮、多线程、体系结构中立、解释执行、高性能、分布式和动态等主要特点。
利用Java语言中秘密密钥工厂对DES算法的支持,使程序实现文件加密、解密两大功能更简单。
本程序设计所采用的就是DES算法。
同时利用Java的GUI编程,生成文本对话框,对文件的路径进行选择、提供密钥框、加密和解密按钮。
使用本程序可以对txt,word等多种文件进行加密解密,使用便捷实用,功能完善,满足了用户对文件安全性的需求。
关键词:JA V A ,DES,加密,解密。
目录1题目分析 (1)1.1课程设计的要求和内容 (1)1.2 DES算法描述 (1)2概要设计 (3)2.1抽象数据类型的定义 (3)2.1.1 程序所需要引入的包 (3)2.1.2 其他定义 (3)2.2主程序流程图 (4)2.3各程序模块之间的层次(调用)关系 (4)3详细设计 (6)3.1 窗体的设计与实现 (6)3.2文件导入模块 (8)4测试分析与结果 (9)4.1. 测试结果 (9)4.1.1运行程序 (9)4.1.2加密 (9)4.1.3解密 (11)总结 (13)参考文献 (14)附录 (15)1题目分析1.1课程设计的要求和内容基本要求:1.利用某种加密算法对指定的文本文件进行加密(应判断其是否已经加密,若已加密则结束该步骤,否则提示输入加密口令,对文件进行加密);2.加密解密方法:本设计采用DES加密算法。
des加密解密算法以及python代码实现DES加密解密算法是一种对称加密算法,它将明文分成固定长度的块,然后使用一个密钥进行加密和解密。
在Python中,我们可以使用pycryptodome库来实现DES加密解密算法。
首先,我们需要安装pycryptodome库。
可以使用以下命令在终端或命令提示符中安装:```shellpip install pycryptodome```接下来,我们可以使用以下代码实现DES加密和解密:```pythonfrom Crypto.Cipher import DESimport binascii# 定义密钥和明文key = b'abcdefgh'plaintext = b'Hello, world!'# 创建DES对象并设置密钥des = DES.new(key, DES.MODE_ECB)# 加密明文ciphertext = des.encrypt(plaintext)print('加密后的密文:', binascii.hexlify(ciphertext))# 解密密文decrypted_plaintext = des.decrypt(ciphertext)print('解密后的明文:', decrypted_plaintext)```在上面的代码中,我们首先定义了密钥和明文。
然后,我们创建了一个DES对象并设置了密钥。
接下来,我们使用DES对象的encrypt 方法对明文进行加密,得到密文。
最后,我们使用DES对象的decrypt 方法对密文进行解密,得到解密后的明文。
需要注意的是,上面的代码只是一种简单的实现方式,实际上DES算法的实现过程要比这复杂得多。
此外,DES算法已经被认为是不安全的,因为它使用的密钥长度只有56位,容易被暴力破解。
在实际应用中,建议使用更安全的加密算法,如AES算法。
DES加密算法详细过程DES(Data Encryption Standard)是一种对称加密算法,采用了64位加密块和56位密钥。
下面将详细介绍DES加密算法的过程。
1. 初始置换(Initial Permutation IP):首先,将明文划分为64位的分组,并根据初始置换矩阵IP对分组进行重排。
该矩阵定义了分组中每一位的位置。
2.密钥生成将56位的密钥进行置换选择(Permutation Choice 1,PC-1),根据预定义的置换矩阵将密钥的各个位重新组合,得到56位的置换密钥C0和D0。
接下来,通过循环左移操作(circular left shift)将置换密钥分为两个28位的子密钥C1和D1、左移的位数根据循环左移表格确定。
然后,对C1和D1重复循环左移操作,得到16个子密钥Ci和Di,其中i表示循环次数。
每次循环左移的位数由循环左移表格指定。
最后,通过置换选择2(Permutation Choice 2,PC-2)将Ci和Di 重新置换,得到16个48位的子密钥Ki,即轮密钥。
3.加密过程对明文分组进行初始置换得到L0和R0,分别为32位。
进入16轮加密过程,每轮的操作如下:- 用Ri-1和轮密钥Ki进行扩展置换(Expansion Permutation),将32位扩展为48位。
-将扩展后的结果与轮密钥Ki进行异或操作,得到48位的结果。
-将异或结果分为8个6位的子分组。
- 对每一个子分组进行S盒替代(Substitution Boxes),将6位的输入转换为4位的输出。
-将替代结果连接起来,得到32位的结果。
- 将32位的结果经过P盒置换(Permutation Box)进行重排。
-将P盒置换后的结果与Li-1进行异或操作,得到Ri。
-将Ri和Li-1交换,作为下一轮的输入。
经过16轮的加密过程后,得到R16和L16、将它们连接起来得到64位的分组。
然后,根据初始置换矩阵的逆矩阵IP-1对分组进行逆置换,得到密文。
DES加密算法分析[摘要]DES数据加密算法是使用最广的分组加密算法,它作为最著名的保密密钥或对称密钥加密算法,在计算机密码学及计算机数据通信的发展过程中起了重要作用。
本次学年论文是主要是学习介绍DES对称密钥数据加密算法,并用c++实现。
DES算法具有较高的安全性,为我们进行一般的计算机数据传输活动提供了安全保障。
[关键词] 加密与解密,DES算法,S-盒引言密码学是伴随着战争发展起来的一门科学,其历史可以追溯到古代,并且还有过辉煌的经历。
但成为一门学科则是近20年来受计算机科学蓬勃发展的刺激结果。
今天在计算机被广泛应用的信息时代,信息本身就是时间,就是财富。
如何保护信息的安全(即密码学的应用)已不再局限于军事、政治和外交,而是扩大到商务、金融和社会的各个领域。
特别是在网络化的今天,大量敏感信息(如考试成绩、个人简历、体检结果、实验数据等)常常要通过互联网进行交换。
(现代电子商务也是以互联网为基础的。
)由于互联网的开放性,任何人都可以自由地接入互联网,使得有些不诚实者就有可能采用各种非法手段进行破坏。
因此人们十分关心在网络上交换信息的安全性。
普遍认为密码学方法是解决信息安全保护的一个最有效和可行的方法。
有效是指密码能做到使信息不被非法窃取,不被篡改或破坏,可行是说它需要付出的代价是可以接受的。
密码是形成一门新的学科是在20世纪70年代。
它的理论基础之一应该首推1949年Shannon的一篇文章“保密系统的通信理论”,该文章用信息论的观点对信息保密问题作了全面的阐述。
这篇文章过了30年后才显示出它的价值。
1976年,Diffie和Hellman发表了论文《密码学的新方向》,提出了公钥密码体制的新思想,这一思想引发了科技界对研究密码学的极大兴趣,大量密码学论文开始公开发表,改变了过去只是少数人关起门来研究密码学的状况。
同时为了适应计算机通信和电子商务迅速发展的需要,密码学的研究领域逐渐从消息加密扩大到数字签名、消息认证、身份识别、抗欺骗协议等新课题[1]。
美国国家标准局(NBS)1973年开始研究除国防部外的其它部门的计算机系统的数据加密标准,并批准用于非机密单位及商业上的保密通信。
于1973年5月15日和1974年8月27日先后两次向公众发出了征求加密算法的公告。
1977年1月,美国政府颁布:采用IBM公司1971年设计出的一个加密算法作为非机密数据的正式数据加密标准(DES : Data Encryption Standard)。
DES广泛应用于商用数据加密,算法完全公开,这在密码学史上是一个创举[2]。
在密码学的发展过程中,DES算法起了非常重要的作用。
本次学年论文介绍的就是分组加密技术中最典型的加密算法——DES算法。
1概述1.1加密与解密加密技术是基于密码学原理来实现计算机、网络乃至一切信息系统安全的理论与技术基础。
简单的说,加密的基本意思是改变信息的排列形式,使得只有合法的接受才能读懂,任何他人即使截取了该加密信息也无法使用现有的手段来解读。
解密是我们将密文转换成能够直接阅读的文字(即明文)的过程称为解密,它是加密的反向处理,但解密者必须利用相同类型的加密设备和密钥对密文进行解密。
1.2 单钥密码系统密码学中有两种重要类型的密码系统,单钥(私钥)和双钥(公钥)密码系统。
在单钥密码系统中,明文的加密和密文的解密是用同样的密钥。
直到1976年Diffie、Hellman引入公钥(双钥)密码学之前,所有的密码都是单钥系统,因此单钥系统也称为传统密码系统。
传统密码系统广泛地用在今天的世界上,有两种单钥密码体制:流密码和分组密码[3]。
流密码是利用密钥k产生一个密钥流z=z0z1…,并使用如下规则对明文串x=x0x1x2…加密:y=y0y1y2…=E z0(x0)E z1(x1)E z2(x2)…。
密钥流由密钥流发生器f产生:z i=f(k,σi),这里σi是加密器中的记忆元件(存储器)在时刻i的状态,f是由密钥k和σi产生的函数[3]。
而分组密码就是将明文消息序列:m 1,m2,…,mk,…划分为等长的消息组(m1,m2,…m),(m1+n,m2+n,…,mn2),…各组明文分别在密钥k=(k1,k2,…,k t)的控制下,按固定的算法Ek一组一组进行加密。
加密后输出等长密文组(y1,…,ym),(y1+m,…,ym2),…分组密码的模型,如图1.1所示[3]。
图1.1 分组密码的模型它与流密码的不同之处在于输出的每一位数字不只与相应时刻输入明文数字有关,而是与一组长为m的明文数组有关。
它们的区别就在于有无记忆性(如图1.2)。
流密码的滚动密钥z0=f(k,σ0)由函数f、密钥k和指定的初态σ0完全确定。
此后,由于输入加密器的明文可能影响加密器中内部记忆元件的存储状态,因而σi(i>0)可能依赖于k,σ0,x0,x1,…,x i-1等参数。
图1.2流密码与分组密码的区别分组密码的优点在于其容易实现同步,因为一个密文组的传输错误不会影响其他组,丢失一个明密文组不会对其后的组的解密正确性带来影响。
分组密码又分为三类:代替密码(Substitution)、移位密码(Transposition)和乘积密码。
随着计算技术的发展,早期的代替和移位密码已无安全可言。
一个增加密码强度的显然的方法是合并代替和移位密码,这样的密码称为乘积密码。
如果密文是由明文运用轮函数多次而得,这样的乘积密码又称为迭代分组密码。
DES和今天的大多数分组密码都是迭代分组密码[4]。
目前著名的对称分组密码系统算法有DES、IDEA、Blowfish、RC4、RC5、FEAL等[4]。
1.3分组密码的总体结构分组密码采用两种类型的总体结构:SP网络与Feistel网络,它们的主要区别在于:SP结构每轮改变整个数据分组,而Feistel密码每轮只改变输入分组的一半。
AES和DES分别是这两种结构的代表。
Feistel网络(又称Feistel结构)可把任何轮函数转化为一个置换,它是由Horst Feistel在设计Lucifer分组密码时发明的,并因DES的使用而流行,“加解密相似”是Feistel型密码的实现优点。
SP网络(又称SP结构)是Feistel网络的一种推广,其结构清晰,S一般称为混淆层,主要起混淆作用,P一般称为扩散层,只要起扩散作用。
SP网络可以更快速的扩散,不过SP网络的加解密通常不相似[4]。
1.4分组密码的安全性安全性是分组密码最重要的设计原则,它要求即使攻击者知道分组密码的内部结构,仍不能破译该密码,这也意味着,不存在针对该密码的某种攻击方法,其工作量小于穷密钥搜索。
但是随着密码分析技术的发展,使得对于具有更多轮的分组密码的破译成为可能。
2.DES算法简介2.1简介DES是Data Encryption Standard(数据加密标准)的缩写。
它是由IBM公司在1971年设计出的一个加密算法,美国国家标准局(NBS)于1977年公布把它作为非机要部门使用的数据加密标准[5]。
DES自从公布以来,已成为金融界及其他各种行业最广泛应用的对称密钥密码系统。
DES是分组密码的典型代表,也是第一个被公布出来的标准算法。
原来规定DES算法的使用期为10年,可能是DES尚未受到严重威胁,更主要是新的数据加密标准研制工作尚未完成,或意见尚未统一,所以当时的美国政府宣布延长它的使用期。
因而DES超期服役到2000年。
近三十年来,尽管计算机硬件及破解密码技术的发展日新月异,若撇开DES的密钥太短,易于被使用穷举密钥搜寻法找到密钥的攻击法不谈,直到进入20世纪90年代以后,以色列的密码学家Shamir等人提出一种“差分分析法”,以后日本人也提出了类似的方法,这才称得上对它有了攻击的方法。
严格地说Shamir的“差分分析法”也只是理论上的价值。
至少到目前为止是这样,比如后来的“线形逼迫法”,它是一种已知明文攻击,需要243≈4.398×1012个明、密文对,在这样苛刻的要求下,还要付出很大的代价才能解出一个密钥。
不管是差分攻击还是线性攻击法,对于DES的安全性也仅仅只做到了“质疑”的地步,并未从根本上破解DES。
也就是说,若是能用类似Triple-DES或是DESX的方式加长密钥长度,仍不失为一个安全的密码系统[7,5]。
早在DES提出不久,就有人提出造一专用的装置来对付DES,其基本思想无非是借用硬件设备来实现对所有的密钥进行遍历搜索。
由于电子技术的突飞猛进,专门设备的造价大大降低,速度有质的飞跃,对DES形成了实际的威胁。
DES确实辉煌过,它的弱点在于专家们一开始就指出的,即密钥太短。
美国政府已经征集评估和判定出了新的数据加密标准AES以取代DES对现代分组密码理论的发展和应用起了奠基性的作用,它的基本理论和设计思想仍有重要参考价值[6,7]。
2.2 DES加密标准现如今,依靠Internet的分布式计算能力,用穷举密钥搜索攻击方法破译已成为可能。
数据加密标准DES已经达到它的信任终点。
但是作为一种Feistel加密算法的例子仍然有讨论的价值。
DES是对二元数字分组加密的分组密码算法,分组长度为64比特。
每64位明文加密成64位密文,没有数据压缩和扩展,密钥长度为56比特,若输入64比特,则第8,16,24,32,40,48,56,64为奇偶校验位,所以,实际密钥只有56位。
DES算法完全公开,其保密性完全依赖密钥。
它的缺点就在于密钥太短。
设明文串m=m1m2...m64;密钥串k=k1k2 (64)在后面的介绍中可以看到k8,k16,k24,k32,k40,k48,k56,k64实际上是不起作用的。
DES的加密过程可表示为:DES(m)= IP-1T16·T15…T2·T1·IP(m).下面是完全16轮DES算法框图:图2.1 完全16轮DES算法2.2.1 初始置换IP初始置换是将输入的64位明文分为8个数组,每一组包括8位,按1至64编号。
IP的置换规则如下表[7]:表2.1 IP置换规则58 50 42 34 26 18 10 260 52 44 36 28 20 12 462 54 46 38 30 22 14 664 56 48 40 32 24 16 857 49 41 33 25 17 9 159 51 43 35 27 19 11 361 53 45 37 29 21 13 563 55 47 39 31 23 15 7即将输入的第58位换到第1位,第50位换到第2位……,依次类推,最后一位是原来的第7位。
2.2.2 IP-1是IP的逆置换由于第1位经过初始置换后,已处于第40位。
逆置换就是再将第40位换回到第1位。