des加密算法的实现及应用Word文件下载.docx
《des加密算法的实现及应用Word文件下载.docx》由会员分享,可在线阅读,更多相关《des加密算法的实现及应用Word文件下载.docx(17页珍藏版)》请在冰豆网上搜索。
最后,按照置换顺序,DES将64位的置换结果分为左右两部分,第1位到第32位记为L0,第33位到第64位记为R0。
第二阶段:
16次迭代变换。
DES采用了典型的Feistel结构,是一个乘积结构的迭代密码算法。
其算法的核心是算法所规定的16次迭代变换。
DES算法的16才迭代变换具有相同的结构,每一次迭代变换都以前一次迭代变换的结果和用户密钥扩展得到的子密钥Ki作为输入;
每一次迭代变换只变换了一半数据,它们将输入数据的右半部分经过函数f后将其输出,与输入数据的左半部分进行异或运算,并将得到的结果作为新的有半部分,原来的有半部分变成了新的左半部分。
用下面的规则来表示这一过程(假设第i次迭代所得到的结果为LiRi):
Li
=
Ri-1;
Ri
Li-1⊕f(Ri-1,Ki);
在最后一轮左与右半部分并未变换,而是直接将R16
L16并在一起作为未置换的输入。
第三阶段:
逆(初始)置换。
他是初始置换IP的逆置换,记为IP-1。
在对16次迭代的结果(R16
L16)再使用逆置换IP-1后得到的结果即可作为DES加密的密文Y输出,即Y
IP-1
(R16
L16)。
DES解密过程:
DES的解密算法与其加密算法使用的算法过程相同。
两者的不同之处在于解密时子密钥Ki的使用顺序与加密时相反,如果子密钥为K1K2…K16,那么解密时子密钥的使用顺序为K16K15…K1,即使用DES解密算法进行解密时,将以64位密文作为输入,第1次迭代运算使用子密钥K16,第2次迭代运算使用子密钥K15,……,第16
次迭代使用子密钥K1,其它的运算与加密算法相同。
这样,最后输出的是64位明文。
对数据进行加密传输能有效地保证数据的机密性,DES是一个保证数据机密性的经典算法,本次课程设计将基于C语言简单实现DES加密解密算法
本文第二节介绍了DES算法的实现原理,第三节详细描述了DES加密算法的设计步骤,第四节为结束语。
1.2设计平台
笔记本,
windows764bit操作系统,
MicrosoftVisualC++6.0,
C语言。
2设计原理
2.1对称密码算法简介
对称加密(也叫私钥加密)指加密和解密使用相同密钥的加密算法。
有时又叫传统密码算法,就是加密密钥能够从解密密钥中推算出来,同时解密密钥也可以从加密密钥中推算出来。
而在大多数的对称算法中,加密密钥和解密密钥是相同的,所以也称这种加密算法为秘密密钥算法或单密钥算法。
它要求发送方和接收方在安全通信之前,商定一个密钥。
对称算法的安全性依赖于密钥,泄漏密钥就意味着任何人都可以对他们发送或接收的消息解密,所以密钥的保密性对通信性至关重要.
对称加密算法的特点是算法公开、计算量小、加密速度快、加密效率高。
不足之处是,交易双方都使用同样钥匙,安全性得不到保证。
此外,每对用户每次使用对称加密算法时,都需要使用其他人不知道的惟一钥匙,这会使得发收信双方所拥有的钥匙数量呈几何级数增长,密钥管理成为用户的负担。
对称加密算法在分布式网络系统上使用较为困难,主要是因为密钥管理困难,使用成本较高。
而与公开密钥加密算法比起来,对称加密算法能够提供加密和认证却缺乏了签名功能,使得使用范围有所缩小.
在计算机专网系统中广泛使用的对称加密算法有DES和IDEA等。
2.2DES算法基本原理
DES算法把64位的明文输入块变为64位的密文输出块,它所使用的密钥也是56位,其算法主要分为两步[2]:
1)初始置换
其功能是把输入的64位数据块按位重新组合,并把输出分为L0、R0两部分,每部分各长32位,其置换规则为将输入的第58位换到第一位,第50位换到第2位……依此类推,最后一位是原来的第7位。
L0、R0则是换位输出后的两部分,L0是输出的左32位,R0是右32位,例:
设置换前的输入值为D1D2D3……D64,则经过初始置换后的结果为:
L0=D58D50……D8;
R0=D57D49……D7。
2)逆置换
经过16次迭代运算后,得到L16、R16,将此作为输入,进行逆置换,逆置换正好是初始置换的逆运算,由此即得到密文输出。
如图3.1.1。
图2.2.1DES算法流程图
从子密钥Ki的生成算法描述图中我们可以看到:
初始Key值为64位,但DES算法规定,其中第8、16、......64位是奇偶校验位,不参与DES运算。
故Key实际可用位数便只有56位。
即:
经过缩小选择换位表1的变换后,Key的位数由64位变成了56位,此56位分为C0、D0两部分,各28位,然后分别进行第1次循环左移,得到C1、D1,将C1(28位)、D1(28位)合并得到56位,再经过缩小选择换位2,从而便得到了密钥K0(48位)。
依此类推,便可得到K1、K2、......、K15,不过需要注意的是,16次循环左移对应的左移位数要依据下述规则进行:
循环左移位数1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1
图2.2.2子密钥生成图
2.3DES算法相关知识
现如今,依靠Internet的分布式计算能力,用穷举密钥搜索攻击方法破译已成为可能。
数据加密标准DES已经达到它的信任终点。
但是作为一种Feistel加密算法的例子仍然有讨论的价值。
DES是对二元数字分组加密的分组密码算法,分组长度为64比特。
每64位明文加密成64位密文,没有数据压缩和扩展,密钥长度为56比特,若输入64比特,则第8,16,24,32,40,48,56,64为奇偶校验位,所以,实际密钥只有56位。
DES算法完全公开,其保密性完全依赖密钥。
DES算法把64位的明文输入块变为64位的密文输出块,它所使用的密钥也是64位,其功能是把输入的64位数据块按位重新组合,并把输出分为L0
、R0两部分,每部分各长32位,其置换规则见下表:
58
50
12
34
26
18
10
2
60
52
44
36
28
20
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
即将输入的第58位换到第一位,第50位换到第2位,„„,依此类推,最后一位是原来的第7位。
L0、R0则是换位输出后的两部分,L0是输出的左32位,R0
是右32位,例:
设置换前的输入值为D1D2D3„„D64,则经过初始置换后的结果为:
L0=D550„„D8;
R0=D57D49...D7。
经过26次迭代运算后,得到L16、R16,将此作为输入,进行逆置换,即得到密文输出。
逆置换正好是初始置的逆运算,例如,第1位经过初始置换后,处于第40位,而通过逆置换,又将第40位换回到第1位,其逆置换规则如下表所示:
42
放大换位表
单纯换位表
在f(Ri,Ki)算法描述图中,S1,S2...S8为选择函数,其功能是把6bit数据变为4bit数据。
下面给出选择函数Si(i=1,2......8)的功能表:
选择函数Si
S1:
S2:
S3:
S4:
S5:
S6:
S7:
S8:
3.子密钥Ki(48bit)的生成算法
故Key
实际可用位数便只有56位。
经过缩小选择换位表1的变换后,Key
的位数由64
位变成了56位,此56位分为C0、D0两部分,各28位,然后分别进行第1次循环左移,得到C1、D1,将C1(28位)、D1(28位)合并得到56位,再经过缩小选择换位2,从而便得到了密钥K0(48位)。
循环左移位数1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1
以上介绍了DES算法的加密过程。
DES算法的解密过程是一样的,区别仅仅在于第一次迭代时用子密钥K15,第二次K14、„„,最后一次用K0,算法本身并没有任何变化。
所谓分组加密算法就是对一定大小的明文或密文来做加密或解密动作。
而在DES这个加密系统中,每次加密或解密的分组大小均为64位,所以DES没有密文扩充的问题。
对大于64位的明文只要按每64位一组进行切割,而对小于64位的明文只要在后面补“0”即可。
另一方面,DES所用的加密或解密密钥也是64位大小,但因其中有8个位是用来作奇偶校验的,所以64位中真正起密钥作用的只有56位,密钥过短也是DES最大的缺点[1]。
DES加密与解密所用的算法除了子密钥的顺序不同外,其他部分完全相同。
3设计步骤
3.1设计思路
Y
N
N
3.2程序实现
加密函数:
voidEncryption(intm0[64],intc1[64])
{
inti,k;
intarry[32];
intc0[64],m1[64];
Replacement(m0,IP_Table,m1,64);
//初始置换IP
for(i=0;
i<
32;
i++)//将明文分成两部分L,R
{
L[0][i]=m1[i];
R[0][i]=m1[i+32];
}
k=1;
while(k<
17)//进行16次循环,将明文右部分与子密钥合并
F_Function(R[k-1],arry,k-1);
for(i=0;
i++)
{
L[k][i]=R[k-1][i];
R[k][i]=L[k-1][i]^arry[i];
}
k++;
i++)//合并为64位
c0[i]=R[16][i];
c0[i+32]=L[16][i];
Replacement(c0,IP_1_Table,c1,64);
//逆初始置换
}
子密钥的生成函数:
voidSubKey(intK0[64])
inti;
intK1[56],K2[56];
intC[17][28],D[17][28];
Replacement(K0,PC_1,K1,56);
//密钥置换PC_1,将64位初始密钥压缩为56位。
28;
i++)//将PC_1输出的56比特分为左右两部分
C[0][i]=K1[i];
D[0][i]=K1[i+28];
i=0;
while(i<
16)//进行16轮迭代,形成16轮密钥。
intj;
lif_move(C[i],C[i+1],move_times[i]);
//调用左移函数
lif_move(D[i],D[i+1],move_times[i]);
for(j=0;
j<
j++)//通过循环,将两部分密钥合并到K2中,此时K2为56位的
K2[j]=C[i+1][j];
K2[j+28]=D[i+1][j];
Replacement(K2,PC_2,K[i],48);
//密钥置换PC_2,合并为48位密钥
i++;
子密钥生成过程中的循环左移函数:
voidlif_move(intarry1[],intarry2[],intn)//左移位实现函数
i++)//通过FOR循环,根据传入的n值,决定左移的位数
arry2[i]=arry1[(n+i)%28];
//进行了模运算
S盒压缩变换函数,其中数组shc存放经过s盒的结果:
voidS_compress(intarry[],intshc[])
inth,l;
//行,列
intsha[8];
//存放经过s盒的十进制结果
inti,j;
inttemp[4];
8;
i++)//s盒压缩变换
h=arry[(1+(i*6))-1]*2+arry[(6+(i*6))-1];
//取二进制数两端为行
l=arry[(2+(i*6))-1]*8+arry[(3+(i*6))-1]*4+arry[(4+(i*6))-1]*2+arry[(5+(i*6))-1];
//取二进制数中间数为列。
sha[i]=S_Box[i][h][l];
根据行列值,在第i个S盒取出对应的位置上的值。
}
i++)//十进制转二进制。
for(j=3;
j>
=0;
j--)
temp[j]=sha[i]%2;
sha[i]=sha[i]/2;
for(j=0;
4;
j++)
shc[4*i+j]=temp[j];
密钥与一半明文的处理函数:
voidF_Function(inta[32],intb[32],intn)
inttmp[48];
inttep[32];
Replacement(a,E_Table,tmp,48);
//扩展变换E
48;
i++)//与子密钥异或
tmp[i]^=K[n][i];
S_compress(tmp,tep);
//压缩变换S
Replacement(tep,P_Table,b,32);
//置换运算P
转换密钥函数,用于解密时用:
voidchangeKey(inta[16][48])
inttmp[16][48];
16;
tmp[i][j]=a[i][j];
K[i][j]=tmp[15-i][j];
解密函数:
voidDecryption(intc1[],intm[])
intc0[64],t[64];
changeKey(K);
//处理加密密钥为解密密钥
Replacement(c1,IP_Table,c0,64);
//初始置换
i++)//密文分成两部分
L[0][i]=c0[i];
R[0][i]=c0[i+32];
17)//16次循环,合并密文右部分与子密钥
F_Function(R[k-1],a