学号:姓名:年级:专业:
DES密码的实现
一、DES算法介绍
DES算法为密码中的对称密码,又被称为美国数据加密标准,是19__年公司研制的对称密码加密算法。明文按位进行分组,密钥长位,密钥事实上是56位参与DES运算。它将位输入经过一系列变换得到位的输出。
图1表示了DES加密的整个机制。对于任意加密方案,总有两个输入,明文和密钥。DES的明文长位,密钥长56位。从图中左半部分,可见明文的处理经过了三个阶段。首先,位的明文经过初始置换(IP)而被重新排列。然后进行16轮相同函数作用,每轮作用都有置换和代替。最后一轮的输出有位,它是输入明文和密钥的函数。其左半部分和右半部分互换产生预输出。最后预输出再被与初始置换(IP)互逆的置换(IP-1)产生位的密文。
右半部分给出了使用56位密钥的过程。首先,密钥经过了一个置换后,再经过循环左移和一个置换分别得到各轮字谜要Ki用于各轮的迭代。每轮的置换函数都是一样的,但是由于密钥的循环和移位使得各轮子密钥互不相同。
图2给出了一轮变换的内部结构。首先,左半部分,位中间数据的左右两部分作为的32位数据,分别记为L和R。在经典的Feistel密码中,每轮变换的整个过程可以写为下面公式:
Li=Ri-1
Ri=Li-1F(Ri-1,Ki)
轮密钥Ki长度为48位,R是32位。首先将R拓展成48位,其中有16位是重复的。这48位与Ki异或,所得结果再用一个代替函数作用产生32位输出,再用一个置换表置换后输出。
二、DES算法源代码及运行结果
/程序的输入输出都是16位十六进制的数/
include"stdio.h"
change函数:将每位十六进制转换为二进制数
voidchange(inta,intN[4])
inti,b;
i=3;
while(a!=0)
b=a%2;
a=a/2;
N[i]=b;
i--;
if(i>=0)
while(i>=0)
N[i--]=0;
ipbiao函数:构造位的ip置换表voidipbiao(intip[8][8])
longi,j,k;
for(j=0;j<4;j++)
i=2+j2;
for(k=7;k>=0;k--)
ip[j][k]=i;
i+=8;
for(j=4;j<8;j++)
i=1+(j-4)2;
for(k=7;k>=0;k--)
ip[j][k]=i;
i+=8;
IPRevFun函数:构造逆初始置换表
voidIPRevFun(intL[32],intR[32],intre[]){
inti,j;
inttem[];
intip11[]={40,8,48,16,56,24,,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};j=0;
for(i=0;i<32;i++)
tem[j++]=L[i];
for(i=0;i<32;i++)
tem[j++]=R[i];
for(i=0;i<;i++)
re[i]=tem[ip11[i]-1];
PUTIN函数:请用户输入明文voidPUTIN(intmw[8][8])
charM[16];
intnum[4];
inti,s,j,n,h,l;
n=0;
printf("请输入16位十六进制数:");for(i=0;i<16;i++)
scanf("%c",M[i]);
for(i=0;i<16;n++,i++)
if(M[i]<60)
s=M[i]-48;
elseif(M[i]<90)
s=M[i]-55;
else
s=M[i]-87;
change(s,num);
if(4(n+1)%8==0)
h=4(n+1)/8-1;
else
h=4(n+1)/8;
if((n+1)%2==0)
l=4;
else
l=0;
for(j=0;j<4;j++)
mw[h][l++]=num[j];}
InitRep函数:将明文按ip表重新排列
voidInitRep(intmw[8][8],inttem[8][8])
inti,j,h,l,a;
intip[8][8];
ipbiao(ip);
for(i=0;i<8;i++)
for(j=0;j<8;j++)
a=ip[i][j];
if(a%8==0)
h=a/8-1;
l=7;
else
h=a/8;
l=a%8-1;
tem[i][j]=mw[h][l];
BreakLR函数:将位明文分为两个32位,分别为L和RvoidBreakLR(inttem[8][8],intL[32],intR[32]){
inth,l,i;
i=0;
for(h=0;h<4;h++)
for(l=0;l<8;l++)
L[i++]=tem[h][l];
i=0;
for(h=4;h<8;h++)
for(l=0;l<8;l++)
R[i++]=tem[h][l];
XXX函数:将R的32位明文变为48位
voidXXX(intr[32],intE[8][6])
inti,h,l;
i=0;
while(i<32)
for(h=0;h<8;h++)
for(l=1;l<5;l++)
E[h][l]=r[i++];
E[0][0]=r[31];
E[0][5]=r[4];
i=9;
for(h=1;h<7;h++)
E[h][0]=r[4h-1];
E[h][5]=r[i-1];
i=i+4;
E[7][0]=r[27];
E[7][5]=r[0];
KeyProd函数:将68位密钥通过左移和置换/压缩(置换选择2)压缩成48位voidKeyProd(intmw[8][8],intn,intkey[48])
inta,i,h,l,j,N,tem,hm,lm,t;
intd[28];
intkt[56];
intc[28];
intk[56];
intls[17]={0,1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1};
intip1[8][7]={{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}};intpc2[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};
i=0;
for(h=0;h<8;h++)
for(l=0;l<7;l++)
a=ip1[h][l];
if(a%8==0)
hm=a/8-1;
lm=7;
else
hm=a/8;lm=a%8-1;}
kt[i++]=mw[hm][lm];}
j=0;
for(i=0;i<28;i++)
c[j++]=kt[i];
t=0;
for(i=28;i<56;i++)
d[t++]=kt[i];
N=0;
for(i=1;i<=n;i++)
N+=ls[i];
while(N)
tem=c[0];
for(i=1;i<28;i++)c[i-1]=c[i];c[27]=tem;
N--;
N=0;
for(i=1;i<=n;i++)
N+=ls[i];
while(N)
tem=d[0];
for(i=1;i<28;i++)d[i-1]=d[i];d[27]=tem;
N--;
for(i=0;i<28;i++)
k[i]=c[i];
for(j=0;j<28;j++)
k[i++]=d[j];
for(i=0;i<48;i++)
key[i]=k[pc2[i]-1];}
_orFun函数:48位明X与48位密钥的异或运算
void_orFun(intE[8][6],intk[48],intr[48])
inth,l,a;
a=0;
for(h=0;h<8;h++)
for(l=0;l<6;l++)
if(E[h][l]!=k[a])
r[a++]=1;
else
r[a++]=0;
LP_orFun函数:参数为两个一维数组的异或函数voidLP_orFun(intpout[32],intlr[32],intre[32]){
inti;
for(i=0;i<32;i++)
if(pout[i]==lr[i])
re[i]=0;
else
re[i]=1;
FSPFun函数:每一轮迭代过程F函数中的置换(P)voidFSPFun(intp[32],intpout[32])
inti;
intsp[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};
for(i=0;i<32;i++)
pout[i]=p[sp[i]-1];
FeiSFun函数:每一轮F函数中的代替/选择(S盒)voidFeiSFun(intk[48],intp[32])
inti,ni,pi,h,l,sh,sl,out;
intnum[4];
intsi[8][6];
ints[8][]={{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}};pi=0;
i=0;
for(h=0;h<8;h++)
for(l=0;l<6;l++)
si[h][l]=k[i++];
for(h=0;h<8;h++)
sh=2si[h][0]+si[h][5];
sl=8si[h][1]+4si[h][2]+2si[h][3]+si[h][4];
out=s[h][sh16+sl];
change(out,num);
for(ni=0;ni<4;ni++)
p[pi++]=num[ni];
ArrayCopy函数:将一个数组的值直接复制到另一个数组voidArrayCopy(inta[32],intb[32])
inti;
for(i=0;i<32;i++)
a[i]=b[i];
Feistel函数
voidFeistel(intr[32],intk[48],intpo[32])
intE_[8][6];
intpi[32];
intre[48];
E_tension(r,E_);
_orFun(E_,k,re);
FeiSFun(re,pi);
FSPFun(pi,po);
BtoO_函数:将二进制数转化为十六进制
voidBtoO_(inta[],charb[16])
inti,j,k,n,r;
n=0;
for(i=0;i<16;i++)
k=8;
r=0;
for(j=1;j<5;j++)
r+=a[n]k;
k=k/2;
n++;
if(r<10)
b[i]=r+48;
else
b[i]=r+55;
主函数
voidmain()
inti,d;
intms[8][8];
intmw[8][8];
inttem[8][8];
intkey[48];
charres[16];
intrr[32];
intR1[32];
intresult[];
intL[32];
intR[32];
printf("--------------------欢迎使用DES加密--------------------
");printf("------------------请输入要加密的明文-------------------
");PUTIN(mw);
getchar();
printf("----------------------请输入密匙-----------------------
");PUTIN(ms);
InitRep(mw,tem);
BreakLR(tem,L,R);
for(d=1;d<16;d++)
KeyProd(ms,d,key);
Feistel(R,key,rr);
LP_orFun(rr,L,R1);
ArrayCopy(L,R);
ArrayCopy(R,R1);
KeyProd(ms,16,key);
Feistel(R,key,rr);
LP_orFun(rr,L,R1);
ArrayCopy(L,R1);
IPRevFun(L,R,result);
BtoO_(result,res);
printf("---------------------加密后的密文为--------------------
");
for(i=0;i<16;i++)
printf("%2c",res[i]);
if((i+1)%4==0)
printf("
");
运行结果:
三、实验心得
随着计算机处理能力的提高,只有56位密钥长度的DES算法不再被认为是安全的,但是认识DES算法还是很有必要的,通过学习DES算法可以更好的了解它的代替者——3DES,而且DES算是对称密码中的一个经典。
通过两周的DES编程让我更加深入的理解了这一算法,编程过程是枯燥的,常常会出现错误,打击自我,但是最后还是克服困难成功的完成了本次实验。这次实验也使我懂得了理论与实际相结合是很非常重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,在实践中深化对理论的理解。