DES加密算法的Java实现

proof 贡献于2014-02-03

作者 yb  创建于2006-12-04 02:39:00   修改者Jac  修改于2010-12-16 11:41:00字数13635

文档摘要: 1973年5月15日,美国国家标准局(现在的美国国家标准就是研究所,即NIST)在联邦记录中公开征集密码体制,这一举措最终导致了数据加密标准(DES)的出现,它曾经成为世界上最广泛使用的密码体制。DES由IBM开发,它是早期被称为Lucifer体制的改进。DES在1975年3月17日首次在联邦记录中公布,在经过大量的公开讨论后,1977年2月15日DES被采纳为“非密级”应用的一个标准。最初预期DES作为标准只能使用10~15年;然而,事实证明DES要长寿得多。
关键词:

目录 摘要 …………………………………………3 一、目的与意义 ……………………………4 二、DES概述 ………………………………5 三、DES加解密算法原理 …………………7 1.加密 ……………………………………6 2.子密钥生成 ……………………………11 3.解密 ……………………………………13 四、加解密算法的实现 …………………14 1.软件版本 ………………………………14 2.平台 ……………………………………14 3.源代码 …………………………………14 4.运行结果 ………………………………24 五、总结 …………………………………25 【摘要】1973年5月15 日,美国国家标准局(现在的美国国家标准就是研究所,即NIST)在联邦记录中公开征集密码体制,这一举措最终导致了数据加密标准(DES)的出现,它曾经成为世界上最广泛使用的密码体制。DES由IBM开发,它是早期被称为Lucifer体制的改进。DES在1975年3月17日首次在联邦记录中公布,在经过大量的公开讨论后,1977年2月15日DES被采纳为“非密级”应用的一个标准。最初预期DES作为标准只能使用10~15年;然而,事实证明DES要长寿得多。被采纳后,大约每隔5年就被评审一次。DES的最后一次评审是在1999年1月。 本文阐述了DES发展现状及对网络安全的重要意义,并在此基础上对DES算法原理进行详细的介绍和分析。通过应用DES算法加解密的具体实现,进一步加深对DES算法的理解,论证了DES算法具有加密快速且强壮的优点,适合对含有大量信息的文件进行加密,同时分析了DES算法密钥过短(56位)所带来的安全隐患。 【关键词】DES 加密 解密 明文 密文 一 、目的与意义 随着计算机和通信网络的广泛应用,信息的安全性已经受到人们的普遍重视。信息安全已不仅仅局限于政治,军事以及外交领域,而且现在也与人们的日常生活息息相关。现在,密码学理论和技术已得到了迅速的发展,它是信息科学和技术中的一个重要研究领域。在近代密码学上值得一提的大事有两件:一是1977年美国国家标准局正式公布实施了美国的数据加密标准(DES),公开它的加密算法,并批准用于非机密单位及商业上的保密通信。密码学的神秘面纱从此被揭开。二是Diffie和Hellman联合写的一篇文章“密码学的新方向”,提出了适应网络上保密通信的公钥密码思想,拉开了公钥密码研究的序幕。 DES(Data Encryption Standard)是IBM公司于上世纪1977年提出的一种数据加密算法。在过去近三十年的应用中,还无法将这种加密算法完全、彻底地破解掉。而且这种算法的加解密过程非常快,至今仍被广泛应用,被公认为安全的。虽然近年来由于硬件技术的飞速发展,破解DES已经不是一件难事,但学者们似乎不甘心让这样一个优秀的加密算法从此废弃不用,于是在DES的基础上有开发了双重DES(DoubleDES,DDES)和三重DES(Triple DES,TDES)。 在国内,随着三金工程尤其是金卡工程的启动,DES 算法在POS、ATM、磁卡及智能卡(IC 卡)、加油站、高速公路收费站等领域被广泛应用,以此来实现关键数据的保密,如信用卡持卡人的PIN 码加密传输,IC 卡与POS 间的双向认证、金融交易数据包的MAC 校验等,均用到DES 算法。DES加密体制是ISO颁布的数据加密标准。 因此研究DES还是有非常重要的意义。 二、 DES概述 DES的前身是IBM的Lucifer算法,后经美国联邦采用这个算法后更名为数据加密标准。 DES是一种块加密算法,每块长64比特。DES的密钥长度也是64比特,但由于其中的8,16,24,32,48,56,64为作为奇偶校验位,所以实际的密钥只有56比特。DES利用了香农提出的混淆和扩散的概念。DES共有16论,每一轮都进行混淆和扩散。 DES主要有三个步骤: (1) 利用初始置换函数IP对64比特明文块进行初始置换。将初始置换的输出分成联邦,分别表示为左明文L0和右明文R0。 (2) 进行16次迭代,迭代规则如下:Li=Ri,Ri=Li-1⊕f(Ri-1,Ki)。其中Li和Ri分别表示第i轮的左半部和右半部。f()是运算函数,Ki是长为48位的子密钥。子密钥K1,K2,……,K16是根据56比特的密钥K计算而来的。 (3) 对比特串R16L16使用逆置换IP-1得到密文。 在DES被提出时,曾出现过很多批评,其中之一就是针对S盒。DES里的所有计算,除了S盒,全是线性的也就是说,计算两个输出的异或与先将两个对应输入异或再计算其输出是相同的。作为非线性部分,S盒对密码体制的安全性至关重要。在DES刚提出时就有人怀疑S盒里隐藏了“陷门(trapdoor)”,而美国国家安全局能够轻易的解密消息。当然,无法否定这样的猜测,但到目前为止也没有任何证据能证明DES里有陷门。事实上,后来表明DES里的S盒是被设计来防止模型攻击的。对DES最中肯的批评是,密钥空间的规模是256,对实际安全而言确实太小了。对于穷举法,一台每毫秒执行一次DES加密的计算机需要一千年才能破解密文。然而,早在1977年Diffie和Hellman就指出,若用现有技术造一台并行机,它带有1百万个加密机,每个加密机都可以每毫秒执行一次DES加密,那么穷举时间大约10小时。他们估计这台计算机造价两千万。1998年7月当EFF(Electronic Frontier Foundation)宣布一台造价不到25万美元、为特殊目的设计的“DES破译机”破译了DES时,DES终于被清楚地证明是不安全的。 三 、DES算法加解密原理 DES算法由加密、子密钥和解密的生成三部分组成。现将DES算法介绍如下。 1. 加密 DES算法处理的数据对象是一组64比特的明文串。设该明文串为m=m1m2…m64 (mi=0或1)。明文串经过64比特的密钥K来加密,最后生成长度为64比特的密文E。其加密过程图示如下: DES算法加密过程 对DES算法加密过程图示的说明如下: 待加密的64比特明文串m,经过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 该比特串被分为32位的L0和32位的R0两部分。R0子密钥K1(子密钥的生成将在后面讲)经过变换f(R0,K1)(f变换将在下面讲)输出32位的比特串f1,f1与L0做不进位的二进制加法运算。运算规则为: f1与L0做不进位的二进制加法运算后的结果赋给R1,R0则原封不动的赋给L1。L1与R0又做与以上完全相同的运算,生成L2,R2…… 一共经过16次运算。最后生成R16和L16。其中R16为L15与f(R15,K16)做不进位二进制加法运算的结果,L16是R15的直接赋值。 R16与L16合并成64位的比特串。值得注意的是R16一定要排在L16前面。R16与L16合并后成的比特串,经过置换IP-1(终结置换)后所得比特串的下标列表如下: IP-1 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 经过置换IP-1后生成的比特串就是密文e.。 变换f(Ri-1,Ki): 它的功能是将32比特的输入再转化为32比特的输出。其过程如图所示: f变换说明:输入Ri-1(32比特)经过变换E(扩展置换E)后,膨胀为48比特。膨胀后的比特串的下标列表如下: E: 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 膨胀后的比特串分为8组,每组6比特。各组经过各自的S盒后,又变为4比特(具体过程见后),合并后又成为32比特。该32比特经过P变换(压缩置换P)后,其下标列表如下: 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 经过P变换后输出的比特串才是32比特的f(Ri-1,Ki). S盒的变换过程: 任取一S盒。见图: 在其输入b1,b2,b3,b4,b5,b6中,计算出x=b1*2+b6, y=b5+b4*2+b3*4+b2*8,再从Si表中查出x 行,y 列的值Sxy。将Sxy化为二进制,即得Si盒的输出。(S表如图所示) 以上是DES算法加密原理 加密过程实现(JAVA主要源代码) l 输入64位明文串,经过IP置换:  for (i = 0; i < 64; i++) {    M[i] = timeData[IP[i] - 1];   } l 迭代(由于各次迭代的方法相同只是输入输出不同,因此以任意一次为例): 首先进行S盒的运算。 输入32位比特串, 经过E变换,由32位变为48位: for (i = 0; i < 48; i++) {    RE[i] = R0[E[i] - 1]; 与keyarray[times][i]按位作不进位加法运: RE[i] = RE[i] + keyarray[times][i]; if (RE[i] == 2) { RE[i] = 0;     } 48位分成8组: for(i=0;i<8;i++){ for(j=0;j<6;j++){ S[i][j]=RE[(i*6)+j];} } 经过S盒,得到8个数:   sBoxData[i] = S_Box[i][(S[i][0] << 1) + S[i][5]][(S[i][1] << 3)      + (S[i][2] << 2) + (S[i][3] << 1) + S[i][4]]; 将8个数变换输出二进制:  for (j = 0; j < 4; j++) {     sValue[((i * 4) + 3) - j] = sBoxData[i] % 2;     sBoxData[i] = sBoxData[i] / 2;    } 经过P变换: RP[i] = sValue[P[i] - 1]; 至此,S盒运算完成 左右交换:  L1[i] = R0[i];    R1[i] = L0[i] + RP[i]; Ri为Li-1与f(R,K)进行不进位二进制加法运算结果: R1[i] = L0[i] + RP[i];  if (R1[i] == 2) { R1[i] = 0;    } 各次迭代类似,可以依此类推。 2、子密钥的生成 64比特的密钥生成16个48比特的子密钥。其生成过程见图: 子密钥生成过程 具体解释如下: 64比特的密钥K,经过PC-1(置换A)后,生成56比特的串。其下标如表所示: PC-1 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 该比特串分为长度相等的比特串C0和D0。然后C0和D0分别循环左移1位,得到C1和D1。C1和D1合并起来生成C1D1。C1D1经过PC-2(置换B)变换后即生成48比特的K1。K1的下标列表为: PC-2 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 C1、D1分别循环左移LS2位,再合并,经过PC-2,生成子密钥K2……依次类推直至生成子密钥K16。注意:Lsi (I =1,2,….16)的数值是不同的。具体见下表: 迭代顺序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 左移位数 1 1 2 2 2 2 2 2 1 2 2 2 2 2 2 1 子密钥的生成(JAVA源代码): 输入64位K,经过PC-1变为56位: for (i = 0; i < 56; i++) {    K0[i] = key[PC_1[i] - 1];   } 56位的K0,均分为28位的C0,D0。C0,D0生成K1和C1,D1(以下几次迭代方法相同,仅以生成任意一次为例): if (offset == 1) { for (i = 0; i < 27; i++) { // 循环左移一位 c1[i] = c0[i + 1]; d1[i] = d0[i + 1]; } c1[27] = c0[0]; d1[27] = d0[0]; } else if (offset == 2) { for (i = 0; i < 26; i++) { // 循环左移两位 c1[i] = c0[i + 2]; d1[i] = d0[i + 2]; } c1[26] = c0[0]; d1[26] = d0[0]; c1[27] = c0[1]; d1[27] = d0[1]; } for (i = 0; i < 28; i++) { k[i] = c1[i]; //生成子密钥ki k[i + 28] = d1[i]; } 注意:生成的子密钥不同,所需循环左移的位数也不同。在编程中,生成不同的子密钥应以上述offset表为准。 3解密 DES的解密过程和DES的加密过程完全类似,只不过将16圈的子密钥序列K1,K2……K16的顺序倒过来。即第一圈用第16个子密钥K16,第二圈用K15,其余类推。 第一圈: 加密后的结果 L=R15, R=L15⊕f(R15,K16)⊕f(R15,K16)=L15 同理R15=L14⊕f(R14,K15), L15=R14。 同理类推: 得 L=R0, R=L0。 其程序源代码与加密相同。 四 、加解密算法的实现 1 软件版本:jdk1.6.0, JCreator Pro v3.5.013 汉化版 2 平台:Windows XP 3 源代码: public class DesUtil { byte[] bytekey; public DesUtil(String strKey) { this.bytekey = strKey.getBytes(); }// 声明常量字节数组 private static final int[] 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 }; // 64 private static final int[] IP_1 = { 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 private static final int[] PC_1 = { 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 }; // 56 private static final int[] PC_2 = { 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 }; // 48 private static final int[] E = { 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 }; // 48 private static final int[] 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 }; // 32 private static final int[][][] S_Box = {//S-盒 {// S_Box[1] { 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_Box[2] { 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_Box[3] { 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_Box[4] { 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_Box[5] { 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_Box[6] { 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_Box[7] { 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 } }, { // S_Box[8] { 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 } } }; private static final int[] LeftMove = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2,2, 2, 2, 1 }; // 左移位置列表 private byte[] UnitDes(byte[] des_key, byte[] des_data, int flag) { // 检测输入参数格式是否正确,错误直接返回空值(null) if ((des_key.length != 8) || (des_data.length != 8)|| ((flag != 1) && (flag != 0))) { throw new RuntimeException("Data Format Error !"); } int flags = flag;// 二进制加密密钥 int[] keydata = new int[64];// 二进制加密数据 int[] encryptdata = new int[64]; // 加密操作完成后的字节数组 byte[] EncryptCode = new byte[8];// 密钥初试化成二维数组 int[][] KeyArray = new int[16][48];// 将密钥字节数组转换成二进制字节数组 keydata = ReadDataToBirnaryIntArray(des_key);// 将加密数据字节数组转换成二进制字节数组 encryptdata = ReadDataToBirnaryIntArray(des_data);// 初试化密钥为二维密钥数组 KeyInitialize(keydata, KeyArray); // 执行加密解密操作 EncryptCode = Encrypt(encryptdata, flags, KeyArray); return EncryptCode; }// 初试化密钥数组 private void KeyInitialize(int[] key, int[][] keyarray) { int i; int j; int[] K0 = new int[56];// 特别注意:xxx[IP[i]-1]等类似变换 for (i = 0; i < 56; i++) { K0[i] = key[PC_1[i] - 1]; // 密钥进行PC-1变换 } for (i = 0; i < 16; i++) { LeftBitMove(K0, LeftMove[i]); // 特别注意:xxx[IP[i]-1]等类似变换 for (j = 0; j < 48; j++) { keyarray[i][j] = K0[PC_2[j] - 1]; // 生成子密钥keyarray[i][j] } } } // 执行加密解密操作 private byte[] Encrypt(int[] timeData, int flag, int[][] keyarray) { int i; byte[] encrypt = new byte[8]; int flags = flag; int[] M = new int[64]; int[] MIP_1 = new int[64]; // 特别注意:xxx[IP[i]-1]等类似变换 for (i = 0; i < 64; i++) { M[i] = timeData[IP[i] - 1]; // 明文IP变换 } if (flags == 1) { // 加密 for (i = 0; i < 16; i++) { LoopF(M, i, flags, keyarray); } } else if (flags == 0) { // 解密 for (i = 15; i > -1; i--) { LoopF(M, i, flags, keyarray); } } for (i = 0; i < 64; i++) { MIP_1[i] = M[IP_1[i] - 1]; // 进行IP-1运算 } GetEncryptResultOfByteArray(MIP_1, encrypt);// 返回加密数据 return encrypt; } private int[] ReadDataToBirnaryIntArray(byte[] intdata) { int i; int j; // 将数据转换为二进制数,存储到数组 int[] IntDa = new int[8]; for (i = 0; i < 8; i++) { IntDa[i] = intdata[i]; if (IntDa[i] < 0) { IntDa[i] += 256; IntDa[i] %= 256; } } int[] IntVa = new int[64]; for (i = 0; i < 8; i++) { for (j = 0; j < 8; j++) { IntVa[((i * 8) + 7) - j] = IntDa[i] % 2; IntDa[i] = IntDa[i] / 2; } } return IntVa; } private void LeftBitMove(int[] k, int offset) { int i; // 循环移位操作函数 int[] c0 = new int[28]; int[] d0 = new int[28]; int[] c1 = new int[28]; int[] d1 = new int[28]; for (i = 0; i < 28; i++) { c0[i] = k[i]; d0[i] = k[i + 28]; } if (offset == 1) { for (i = 0; i < 27; i++) { // 循环左移一位 c1[i] = c0[i + 1]; d1[i] = d0[i + 1]; } c1[27] = c0[0]; d1[27] = d0[0]; } else if (offset == 2) { for (i = 0; i < 26; i++) { // 循环左移两位 c1[i] = c0[i + 2]; d1[i] = d0[i + 2]; } c1[26] = c0[0]; d1[26] = d0[0]; c1[27] = c0[1]; d1[27] = d0[1]; } for (i = 0; i < 28; i++) { k[i] = c1[i]; k[i + 28] = d1[i]; } } private void LoopF(int[] M, int times, int flag, int[][] keyarray) { int i; int j; int[] L0 = new int[32]; int[] R0 = new int[32]; int[] L1 = new int[32]; int[] R1 = new int[32]; int[] RE = new int[48]; int[][] S = new int[8][6]; int[] sBoxData = new int[8]; int[] sValue = new int[32]; int[] RP = new int[32]; for (i = 0; i < 32; i++) { L0[i] = M[i]; // 明文左侧的初始化 R0[i] = M[i + 32]; // 明文右侧的初始化 } for (i = 0; i < 48; i++) { RE[i] = R0[E[i] - 1]; // 经过E变换扩充,由32位变为48位 RE[i] = RE[i] + keyarray[times][i]; // 与KeyArray[times][i]按位作不进位加法运算 if (RE[i] == 2) { RE[i] = 0; } } for (i = 0; i < 8; i++) { // 48位分成8组 for (j = 0; j < 6; j++) { S[i][j] = RE[(i * 6) + j]; } // 下面经过S盒,得到8个数 sBoxData[i] = S_Box[i][(S[i][0] << 1) + S[i][5]][(S[i][1] << 3) + (S[i][2] << 2) + (S[i][3] << 1) + S[i][4]]; // 8个数变换输出二进制 for (j = 0; j < 4; j++) { sValue[((i * 4) + 3) - j] = sBoxData[i] % 2; sBoxData[i] = sBoxData[i] / 2; } } for (i = 0; i < 32; i++) { RP[i] = sValue[P[i] - 1]; // 经过P变换 L1[i] = R0[i]; // 右边移到左边 R1[i] = L0[i] + RP[i]; if (R1[i] == 2) { R1[i] = 0; } // 重新合成M,返回数组M // 最后一次变换时,左右不进行互换。此处采用两次变换实现不变 if (((flag == 0) && (times == 0)) || ((flag == 1) && (times == 15))) { M[i] = R1[i]; M[i + 32] = L1[i]; } else { M[i] = L1[i]; M[i + 32] = R1[i]; } } } private void GetEncryptResultOfByteArray(int[] data, byte[] value) { int i; int j; // 将存储64位二进制数据的数组中的数据转换为八个整数(byte) for (i = 0; i < 8; i++) { for (j = 0; j < 8; j++) { value[i] += (data[(i << 3) + j] << (7 - j)); } } for (i = 0; i < 8; i++) { value[i] %= 256; if (value[i] > 128) { value[i] -= 255; } } } private byte[] ByteDataFormat(byte[] data, int flag) { int len = data.length; int padlen = 8 - (len % 8); int newlen = len + padlen; byte[] newdata = new byte[newlen]; System.arraycopy(data, 0, newdata, 0, len); for (int i = len; i < newlen; i++) newdata[i] = (byte) padlen; return newdata; } public byte[] DesEncrypt(byte[] des_data, int flag) { byte[] format_key = ByteDataFormat(bytekey, flag); byte[] format_data = ByteDataFormat(des_data, flag); int datalen = format_data.length; int unitcount = datalen / 8; byte[] result_data = new byte[datalen]; for (int i = 0; i < unitcount; i++) { byte[] tmpkey = new byte[8]; byte[] tmpdata = new byte[8]; System.arraycopy(format_key, 0, tmpkey, 0, 8); System.arraycopy(format_data, i * 8, tmpdata, 0, 8); byte[] tmpresult = UnitDes(tmpkey, tmpdata, flag); System.arraycopy(tmpresult, 0, result_data, i * 8, 8); } // 当前为解密过程,去掉加密时产生的填充位 byte[] decryptbytearray = null; if (flag == 0) { int total_len = datalen; int delete_len = result_data[total_len - 8 - 1]; delete_len = ((delete_len >= 1) && (delete_len <= 8)) ? delete_len : 0; decryptbytearray = new byte[total_len - delete_len - 8]; boolean del_flag = true; for (int k = 0; k < delete_len; k++) { if (delete_len != result_data[total_len - 8 - (k + 1)]) del_flag = false; } if (del_flag == true) { System.arraycopy(result_data, 0, decryptbytearray, 0, total_len- delete_len - 8); } } return (flag == 1) ? result_data : decryptbytearray; } public static void main(String[] args) { String key = "这是密钥"; String data = "这是明文"; DesUtil desUtil = new DesUtil(key); System.err.println("加密前明文:" + data); // 加密后的byte型的密文 byte[] result = desUtil.DesEncrypt(data.getBytes(), 1); System.err.println("加密后密文:" + new String(result)); // 下句直接把byte类型的密文解密 System.err.println("解密后明文:"+ new String(desUtil.DesEncrypt(result, 0))); } } 4 运行结果 五 、总结 本文的论述是基于DES算法分析的实现,DES的工作模式,DES的安全性及其应用,重点对DES对DES算法的流程做一个详细的描述,对算法的数学基础和函数描述也有比较详细的描述,应用 JAVA语言实现DES的最基本的核心算法,从而对DES有更深的理解。 通过此次课程设计,不仅使自己对信息安全有了初步了解,同时使自己编程能力有了较大的提高。基本掌握了JAVA结构化程序设计。并且熟悉掌握了密码学中一个重要的算法—DES密码算法,并且通过JAVA工具编程实现。 但是由于对JAVA的图形用户界面的设计理解不深,编写的窗口无法对时间进行处理,最终只有放弃编写窗口。 参考文献 1[加] Douglas R.Stinson 著 冯登国 译 Cryptography Theory and Practice (Second Edition) 电子工业出版社 2006. 2[美] William Stallings 著 孟庆树 王丽娜 傅建明 等译 Cryptography and Network Security Principles and Practices,Fourth Edition 电子工业出版社 2007. 3郝玉洁 刘贵松 秦科 晏华 编著 信息安全概论 电子科技大学出版社 2007. 4耿祥义 张跃平 编著 Java2实用教程 清华大学出版社 2008. 5雍俊海 编著 Java程序设计教程(第2版) 清华大学出版社 2007.

下载文档到电脑,查找使用更方便

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 5 金币 [ 分享文档获得金币 ] 3 人已下载

下载文档