一、DES算法介绍

一、DES算法介绍
DES( Data Encryption Standard)算法,于1977年得到美国政府的正式许可,是一种用56位密钥来加密64位数据的方法。以下简要地介绍该算法的步骤。

A. 密钥生成
1、取得密钥

从用户处取得一个64位长的密码key ,去除64位密码中作为奇偶校验位的第8、16、24、32、40、48、56、64位,剩下的56位作为有效输入密钥。
2、 等分密钥

把生成的56位输入密钥分成均等的A,B两部分,每部分为28位,参照表1和表2把输入密钥的位置填入相应的位置。 按表1所示A的第一位为输入的64位密钥的第57位,A的第2位为64位密钥的第49位,……,依此类推,A的最后一位是64位密钥的第36位。
3、 密钥的移位

DES算法的密钥是经过16次迭代得到一组密钥的,把生成的A,B视为迭代的起始密钥,表3显示在第I次迭代时密钥循环左移的位数。 比如在第1次迭代时密钥循环左移1位,第3次迭代时密钥循环左移2位。 第9次迭代时密钥循环左移1位,第14次迭代时密钥循环左移2位。
4、 密钥的选取

 


把第I次迭代生成的两个28位长的密钥为合并,按表4所示k的第一位为56位密钥的第14位,k的第2位为56位密钥的第17位,……,依此类推,k的最后一位是56位密钥的第32位。 这样就得到子密钥K[I]。
5、迭代
DES算法密钥生成需要进行16次迭代,在完成16次迭代前,循环执行密钥的移位和密钥的选取。最终形成16个子密钥:K[0],K[1],……,[15]。

B. 数据的加密操作
1、 取得数据
把明文数据分成64位的数据块,不够64位的数据块以适当的方式补足。
2、 初始换位

按表5所示,把输入的64位数据的原第58位换到第一位,原第50位换到第二位,……,依此类推,最后的得到新的64位数据。
3 、数据扩展
第一次迭代以刚生成的新数据作为输入数据,第I(I > 1)次迭代以第I-1次的64位输出数据为输入数据,把64位数据按位置等分成左右两部分:left和right。
保持left不变,根据表6把right由32位扩展成48位

把扩展后的48位right与第I次迭代生成的48位子密钥,进行按位异或原是,形成一个新的48位的right。
4、 数据压缩
上面形成的48位的right值, 需要把它转换成32位的right值。把right视为由8个6位二进制组成, a,b,……,h都是6位,强制转换成10进制整数的值都不大于64 ,a,b,……,h转成10进制整数后,在对应的表中根据转换后整数值,取得对应位置的替代值, a对应表7.1,b对应表7.2,……,h对应表7.8。每6位用一个4位替换这样就完成了从48位向32位数据的转换。比如:
a = 32 ,那么到表7.1中找到32的位置,把对应的替代值0x8赋给a;
d = 53 ,那么到表7.4中找到的位置,把对应的替代值 0x3赋给d ;
g = 16, 那么到表7.7中找到16的位置,把对应的替代值0xa赋给g;

5 、数据换位
把上面形成的32位right,根据表8进行转换。数据的原第16位换到第一位,原第7位换到第二位,……,依此类推,最后得到新的32位数据。

6 、交换数据
把right 和left按位异或运算后的值赋给right,然后将本轮输入的原始right值赋给left。
7 、迭代
DES算法需要进行16次迭代,在完成16次迭代前,把第I-1次得到的left和right的值作为第I次的输入数据,重复3,4,5,6的步骤,但是有一点要记住:在步骤3中第I次迭代要选择第I次迭代生成的子密钥与数据进行按位异或运算。
8 、数据整理

为保证加密和解密的对称性,DES算法的前15次迭代每完成一次迭代都要交换left和right的值,第16次迭代不交换两者的数值。 到此把32位的left和right合并成64位的数据。
根据表9重新调整位置。数据的原第40位换到第一位,原第8位换到第二位,……,依此类推,最后的得到新的64位数据,即为密文。
C. 数据的解密
数据解密的算法与加密算法相同,区别在于和数据进行按位异或运算时,子密钥的使用顺序不同,在加密中是按照第I次迭代就采用第I次迭代生成的子密钥进行异或,而解密时第I次迭代就采用第15-I次迭代生成的密钥和数据进行异或。

 

二、算法的实现
以下是用c语言编写的基于DES算法的核心加密解密程序的接口函数。
1、加密函数
unsigned char enDES(unsigned char* indata,unsigned long inlen,unsigned char key[8],/
unsigned char* outdata,unsigned long* outlen);//加密
功能:本函数实现了根据初始密钥生成16个子密钥。把明文数据分割成64位的数据块,逐块实现16次循环迭代加密。密文数据放指针outdata所指向的内存中,它必须提前分配,并要求足够大(>inlen+8)。这是最简单的ECB模式的DES加密。
参数:
indata:指向明文数据的指针。
inlen:明文数据的长度。
key:用户输入的密钥。
outdata:存放密文数据的指针。
outlen:传入outdata内存的大小,传出密文数据的长度。
返回值:1-成功,0-失败。
unsigned char enDES_cbc(unsigned char* indata,unsigned long inlen,unsigned char key[8],/
        unsigned char* outdata,unsigned long* outlen,unsigned char* iv);
功能:本函数实现了根据初始密钥生成16个子密钥。把明文数据分割成64位的数据块,逐块实现16次循环迭代加密。密文数据放指针outdata所指向的内存中,它必须提前分配,并要求足够大(>inlen+8)。这是CBC模式的DES加密。
参数:
indata:指向明文数据的指针。
inlen:明文数据的长度。
key:用户输入的密钥。
outdata:存放密文数据的指针。
outlen:传入outdata内存的大小,传出密文数据的长度。
返回值:1-成功,0-失败。
unsigned char enY5DES(gYan5DES* y5);
功能:本函数是专门为研五封装的加密接口。内部调用了enDES函数和base64编码的函数。
参数:
Y5:结构体指针。
返回值:1-成功,0-失败。
2、解密函数
unsigned char unDES(unsigned char* indata,unsigned long inlen,unsigned char key[8],/
        unsigned char* outdata,unsigned long* outlen);//解密
功能:本函数实现了根据初始密钥生成16个子密钥。把密文数据分割成64位的数据块,逐块实现16次循环迭代解密。明文数据放指针outdata所指向的内存中,它必须提前分配,并要求足够大(>inlen+8)。这是最简单的ECB模式的DES加密。
参数:
indata:指向密文数据的指针。
inlen:密文数据的长度。
key:用户输入的密钥。
outdata:存放明文数据的指针。
outlen:传入outdata内存的大小,传出明文数据的长度。
返回值:1-成功,0-失败。
unsigned char* unDES_cbc(unsigned char* data,unsigned char* key,/
        unsigned long inlen,unsigned long* outlen,char* iv);//解密
功能:本函数实现了根据初始密钥生成16个子密钥。把密文数据分割成64位的数据块,逐块实现16次循环迭代解密。明文数据放指针outdata所指向的内存中,它必须提前分配,并要求足够大(>inlen+8)。这是CBC模式的DES加密。
参数:
data:指向密文数据的指针。
key:用户输入的密钥。
inlen:密文数据的长度。
outlen:传入outdata内存的大小,传出明文数据的长度。
iv:初始向量。
返回值:1-成功,0-失败。
unsigned char unY5DES(gYan5DES* y5);
功能:本函数是专门为研五封装的解密接口。内部调用了base64解码的函数和unDES函数。
参数:
Y5:结构体指针。
返回值:1-成功,0-失败。
3、密钥生成函数
void randKey(unsigned char key[8]);//生成随机密钥
功能: 本函数调用编译器的参数随机数的函数,生成一个64位的随机密钥。由于随机数参产生器产生的不是真正的随机数,所以这种方法不可靠。
参数:
key[]:存放8字节二进制密钥的数组。
返回值:无返回值。
4、加密解密公共函数
unsigned char comDES(unsigned char in[8],unsigned char out[8],
        unsigned char subkey[16][8],unsigned char flg);
功能:根据加密解密标志flg和16个48位的子密钥subkey。把64位的初始数据in,加密解密成64位的新数据out。
5、生成子密钥函数
void genKey(unsigned char*,unsigned char[16][8]);
功能:根据用户给出的一个64位密钥,产生16个48位的子密钥。
6、S盒代替函数
void sReplace(unsigned char*) ;
功能:实现S盒代替,把48位的数据压缩到32位。

 

 

类别:c/c++/c# | 浏览( 301) | 评论 (2)
DES算法的C语言代码及实现 首先新建头文件des_encode.H 内容如下: void EncodeMain(); //EncodeMain function void DecodeMain(); //Sorry ,it has not used void Decode(int *str,int *keychar); //decode :input 8 chars,8 keychars void Encode(int *str,int *keychar); //encode: input 8 chars,8 keychars void keyBuild(int *keychar); //create key array void StrtoBin(int *midkey,int *keychar); //change into binary void keyCreate(int *midkey2,int movebit,int i); //call by keyBuild void EncodeData(int *lData,int *rData,int *srt); //encodedata function void F(int *rData,int *key); //F function void Expand(int *rData,int *rDataP); //Expand function void ExchangeS(int *rDataP,int *rData); //S-diagram change void ExchangeP(int *rData); //P change void FillBin(int *rData,int n,int s); // data to binary;call by S-Diagram change function void DecodeData(int *str,int *lData,int *rData); //DecodeData from binary int IP1[]={58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, //initial change 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 IP2[]={40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31, //opp initial change 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 }; int s[][4][16]={{ //S-diagram array {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} } }; int Ex[48]={ 32,1,2,3,4,5, //Expand array 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 }; int P[32]={16,7,20,21, //P-change 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 PC1[56]={57,49,41,33,25,17,9, //PC-1 in keyBuild 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,33,15, 7,62,54,46,38,30,22, 14,6,61,53,45,37,29, 21,13,5,28,20,12,4 }; int PC2[48]={14,17,11,24,1,5, //PC-2 in keyBuild 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 }; 再创建des.cpp 内容如下: #include<stdio.h> #include<string.h> #include"des_encode.h" int key[16][48]; char str[8]; void main() //main function { EncodeMain(); } void EncodeMain() //EncodeMain function { int i; char keychar[8]; int key2[8]; int strkey[8]; printf("请输入8个要加密的字符:\n"); for(i=0;i<8;i++) scanf("%c",&str[i]); getchar(); for(i=0;i<8;i++) strkey[i]=str[i]; printf("\n输入明文的十六进制为:\n"); for(i=0;i<8;i++) printf("%10x",strkey[i]); printf("\n请输入密钥(8个字符):\n"); for(i=0;i<8;i++) scanf("%c",&keychar[i]); for(i=0;i<8;i++) key2[i]=keychar[i]; getchar(); // printf("%c",keychar[i]); Encode(strkey,key2); printf("\n加密后十六进制密文是:\n"); for(i=0;i<8;i++) printf("%10x",strkey[i]); printf("\n\n清输入解密密码\n"); for(i=0;i<8;i++) scanf("%c",&keychar[i]); for(i=0;i<8;i++) key2[i]=keychar[i]; Decode(strkey,key2); for(i=0;i<8;i++) printf("%10x",strkey[i]); for(i=0;i<8;i++) str[i]=strkey[i]; printf("\n明文为:\t"); for(i=0;i<8;i++) printf("%c",str[i]); printf("\n\n"); } void keyBuild(int *keychar){ //create key array int i,j; int movebit[]={1,1,2,2,2,2,2,2, 1,2,2,2,2,2,2,1}; int midkey2[56]; int midkey[64]; StrtoBin(midkey,keychar); for(i=0;i<56;i++) midkey2[i]=midkey[PC1[i]-1]; for(i=0;i<16;i++) keyCreate(midkey2,movebit[i],i); } void StrtoBin(int *midkey,int *keychar){ //change into binary int trans[8],i,j,k,n; n=0; for(i=0;i<8;i++){ j=0; while(keychar[i]!=0){ trans[j]=keychar[i]%2; keychar[i]=keychar[i]/2; j++; } for(k=j;k<8;k++)trans[k]=0; for(k=0;k<8;k++) midkey[n++]=trans[7-k]; } } void keyCreate(int *midkey2,int movebit,int n){ int i,temp[4]; temp[0]=midkey2[0]; temp[1]=midkey2[1]; temp[2]=midkey2[28]; temp[3]=midkey2[29]; if(movebit==2){ for(i=0;i<26;i++){ midkey2[i]=midkey2[i+2]; midkey2[i+28]=midkey2[i+30]; } midkey2[26]=temp[0];midkey2[27]=temp[1]; midkey2[54]=temp[2];midkey2[55]=temp[3]; } else { for(i=0;i<27;i++){ midkey2[i]=midkey2[i+1]; midkey2[i+28]=midkey2[i+29]; } midkey2[27]=temp[0];midkey2[55]=temp[2]; } for(i=0;i<48;i++) key[n][i]=midkey2[PC2[i]-1]; } void EncodeData(int *lData,int *rData,int *str){ //encodedata function int i,j,temp[8],lint,rint;//int h; int data[64]; lint=0,rint=0; for(i=0;i<4;i++){ j=0; while(str[i]!=0){ temp[j]=str[i]%2; str[i]=str[i]/2; j++; } while(j<8)temp[j++]=0; for(j=0;j<8;j++) lData[lint++]=temp[7-j]; j=0; while(str[i+4]!=0){ temp[j]=str[i+4]%2; str[i+4]=str[i+4]/2; j++; } while(j<8)temp[j++]=0; for(j=0;j<8;j++)rData[rint++]=temp[7-j]; } for(i=0;i<32;i++){ data[i]=lData[i]; data[i+32]=rData[i]; } for(i=0;i<32;i++){ lData[i]=data[IP1[i]-1];//printf("P1:%5d:%5d,%5d\n",IP1[i],lData[i],data[IP1[i]-1]); rData[i]=data[IP1[i+32]-1]; } } void F(int *rData,int *key){ //F function int i,rDataP[48]; Expand(rData,rDataP); for(i=0;i<48;i++){ rDataP[i]=rDataP[i]^key[i];// printf("%10d",rDataP[i]);if((i+1)%6==0)printf("\n"); } ExchangeS(rDataP,rData); ExchangeP(rData); } void Expand(int *rData,int *rDataP){ //Expand function int i; for(i=0;i<48;i++) rDataP[i]=rData[Ex[i]-1]; } void ExchangeS(int *rDataP,int *rData){ //S-diagram change int i,n,linex,liney; linex=liney=0; for(i=0;i<48;i+=6){ n=i/6; //printf("%10d\n",(rDataP[i]<<1)); linex=(rDataP[i]<<1)+rDataP[i+5]; liney=(rDataP[i+1]<<3)+(rDataP[i+2]<<2)+(rDataP[i+3]<<1)+rDataP[i+4]; FillBin(rData,n,s[n][linex][liney]); } } void ExchangeP(int *rData){ //P change int i,temp[32]; for(i=0;i<32;i++) temp[i]=rData[i]; for(i=0;i<32;i++) rData[i]=temp[P[i]-1]; } void FillBin(int *rData,int n,int s){ // data to binary;call by S-Diagram change function int temp[4],i; for(i=0;i<4;i++){ temp[i]=s%2; s=s/2; } for(i=0;i<4;i++) rData[n*4+i]=temp[3-i]; } void DecodeData(int *str,int *lData,int *rData){ //DecodeData from binary int i;int a,b;int data[64]; a=0,b=0; for(i=0;i<32;i++){ data[i]=lData[i]; data[i+32]=rData[i]; } for(i=0;i<32;i++){ lData[i]=data[IP2[i]-1]; rData[i]=data[IP2[i+32]-1]; } for(i=0;i<32;i++){ a=(lData[i]&0x1)+(a<<1); b=(rData[i]&0x1)+(b<<1); if((i+1)%8==0){ str[i/8]=a;a=0;//printf("%d",i/8); str[i/8+4]=b;b=0;//printf("%d",i/8+4); } } } void Encode(int *str,int *keychar){ //encode: input 8 chars,8 keychars int lData[32],rData[32],temp[32],rDataP[48]; int i,j; keyBuild(keychar); EncodeData(lData,rData,str); for(i=0;i<16;i++){ for(j=0;j<32;j++) temp[j]=rData[j]; F(rData,key[i]); for(j=0;j<32;j++){ rData[j]=rData[j]^lData[j]; } for(j=0;j<32;j++) lData[j]=temp[j]; } DecodeData(str,rData,lData); } void Decode(int *str,int *keychar){ //decode :input 8 chars,8 keychars int lData[32],rData[32],temp[32],rDataP[48]; int i,j; keyBuild(keychar); EncodeData(lData,rData,str); //这个位置 for(i=0;i<16;i++){ for(j=0;j<32;j++) temp[j]=rData[j]; F(rData,key[15-i]); for(j=0;j<32;j++){ rData[j]=rData[j]^lData[j]; } for(j=0;j<32;j++){ lData[j]=temp[j]; } } DecodeData(str,rData,lData); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值