当前位置:文档之家› 基于DES算法的数据加密解密的JSP实现

基于DES算法的数据加密解密的JSP实现

成都信息工程学院课程设计报告

基于JSP的DES加密解密算法页面的实现

课程名称:密码算法程序设计

学生姓名:钦曦

学生学号: 2011121064

专业班级:信安实验111班

任课教师:张金全

2013年 11 月 9 日

附件:课程设计成绩评价表

目录

1.引言 (1)

1.1 背景 (1)

1.2 目的 (2)

1.3 本设计的主要任务 (2)

2.系统设计 (2)

2.1系统主要目标 (2)

2.1.1主要程序需求(运行环境) (2)

2.2 系统结构 (3)

2.2.2程序操作流程 (3)

2.2.3功能模块 (4)

2.2.4 DES算法加密流程 (4)

3.系统功能程序设计 (5)

3.1初始置换IP (5)

3.2轮结构 (5)

3.3逆初始置换 (9)

3.4密钥选择置换 (9)

3.5循环左移 (10)

3.6字节填充 (11)

3.7数据转二进制数组 (12)

3.8二进制数组转八位数组 (13)

3.9密文字符串转byte数组 (13)

3.10加密或解密 (14)

3.11三重DES加密解密 (15)

4.测试报告 (16)

5.结论 (19)

参考文献 (20)

1.引言

1.1 背景

据记载,公元前400年,古希腊人发明了置换密码。1881年世界上的第一个电话保密专利出现。在第二次世界大战期间,德国军方启用“恩尼格玛”密码机,密码学在战争中起着非常重要的作用。

随着信息化和数字化社会的发展,人们对信息安全和保密的重要性认识不断提高,于是在1997年,美国国家标准局公布实施了“美国数据加密标准(DES)”,民间力量开始全面介入密码学的研究和应用中,采用的加密算法有DES、RSA、SHA等。随着对加密强度需求的不断提高,近期又出现了AES、ECC等。我国也相应提出了自己国家的ECC、SCB2、SCH等加密算法。

随着计算机和通信网络的广泛应用,信息的安全性已经受到人们的普遍重视。信息安全已不仅仅局限于政治,军事以及外交领域,而且现在也与人们的日常生活息息相关。现在,密码学理论和技术已得到了迅速的发展,它是信息科学和技术中的一个重要研究领域。在近代密码学上值得一提的大事有两件:一是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还是有非常重要的意义。

1.2 目的

在一些特殊场合,人们交换信息并不希望被其他人知道,需要把消息进行一系列转换后在公共信道中传输,接收方再通过一些手段将消息转换回来,本程序用DES对称密钥加密算法加解密一组长度为64bit的十六进制数,达到以下目的:1.保密性:防止用户的标识或数据被读取。2.数据完整性:防止数据被更改。3.身份验证:确保数据发自特定的一方。

1.3 本设计的主要任务

根据DES加密算法实现任意长度的字符串加密解密。向用户提供良好的交互,具有良好的操作性。可完成任意长度明文的加解密(自动分组为每组8字节),密钥最多8个字节(不足8个字节补0,超过8字节取前8字节),输入明文和密钥后,得到密文,进行加密后的密文,能够进行正确的解密。

可进行三重DES加密解密,输入任意长度明文以及3个不同的密钥,能正确的进行加密、解密。

此为DES加密解密网页版(JPS页面),

2.系统设计

2.1系统主要目标

2.1.1主要程序需求(运行环境)

本页面是用java和html语言编写,使用tomcat7.x进行服务器架设,架设成功后,可在任意计算机、任意浏览器上访问。本页面设计符合DES程序设计基本要求:

(1)在深入理解DES加密/解密算法理论的基础上,设计一个DES加密/解密页面;

(2)完成多个明文分组的加解密,明文可以是任意长度的,密钥最多8个字节(不足补0),输入明文和密钥后,得到密文,进行加密后的密文,能够进行正确的解密;

(3)程序运行时,要求自动对明文进行分组或者填充;

(4)可以进行三重DES加密、解密;

(5)显示加密解密所用的时间(计时器);

(6)要求提供所设计系统的报告及完整的程序;

输入:

加密:任意长度的明文以及长度为8的密钥。(3DES需要3个密钥)

解密:长度为16或16整数倍的伪16进制字符串以及长度为8的密钥。(3DES需要3个密钥)

输出:

加密:长度为16或16整数倍的伪16进制字符串。

解密:任意长度并正常解密的明文。

测试平台:Windows 8/Windows XP

2.2 系统结构

2.2.2 程序操作流程

加密:

(1)按提示在“加密密钥”输入框输入密钥。(密钥长度为8字节)

(2)按提示在“加密明文”输入框输入明文。(明文为任意长度)

(3)点击加密按钮,会在其后显示加密后的密文。(密文为长度16或16整数倍的伪16进制字符串)

(4)三重DES加密需要输入3个密钥。

解密:

(1)按提示在“加密密钥”输入框输入密钥。(密钥长度为8字节)

(2)按提示在“解密密文”输入框输入密文。(密文为长度16或16整数倍的伪16进制字符串)

(3)点击解密按钮,后在其后显示正常解密后的明文。

(4)三重DES解密需要输入3个密钥。

2.2.3功能模块

表2-2-3功能模块表2.2.4 DES算法加密流程

3 系统功能程序设计

3.1初始置换IP

先设置好初始变换IP 变换的数组IP[],然后定义新的数组M[]存储变换后的内容,依靠变换明文的数组timeData[]的下标来变换数据顺序,并存入数组M[]中。

图3-1 初始置换IP 示意图

主要代码:

for (int i = 0; i < 64; i++) {

M[i] = timeData[IP [i] - 1]; }

3.2轮结构

定义L0、R0数组分别存储明文左右两部分(32bite );然后使用设置好的E 盒扩充R0成48bite 并存入RE 中,紧接着让RE 与48bite 子密钥进行异或(XOR )。

再把RE 分成8组,每组6比特,定义一个二维数组S[][]进行存储,每行代表一组数据。然后用设置好的S 盒(三维数组S_Box )进行替换,定义新数组sBoxData 存储替换得到的8个数,替换方法方位为对S[][]中数值进行移位,算出十进制值,以此确定三维数组S_Box 的下标,接着使用经典模2取余法,将S_Box 中8个数转为2进制存入数组sValue[]。

然后用设置好的P 盒(P[]),对sValue[]进行替换,存入RP[]

,其左边部

分L1=R0,右边部分R1为L0与RP进行异或(XOR),得到R1。

以上操作会执行16次。

最后一次将左右两部分L1与R1合并,存储到数组M[](Encrypt函数会传flags值进来,来判断是加密还是解密,在最后来区分是何时进行左右部分合并存储到M[]数组)。

图3-2-1 DES算法的一轮结构变换图

图3-2-2 加密最后一轮示意图

图3-2-3 解密最后一轮示意图输入右半部分 32位

输出 48位

图3-2-4 E盒扩展示意图

输入32位(来自S盒的输出)

输出 32位

图3-2-5 P盒置换示意图

主要代码:

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];

RE[i] = RE[i] + keyarray[times][i];

if (RE[i] == 2) {

RE[i] = 0;

}

}

for (i = 0; i < 8; i++) {

for (j = 0; j < 6; j++) {

S[i][j] = RE[(i * 6) + j];

}

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]];

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];

L1[i] = R0[i];

R1[i] = L0[i] + RP[i];

if (R1[i] == 2) {

R1[i] = 0;

}

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];

}

3.3逆初始置换

用先设置好逆初始置换IP_1变换的数组IP_1[],然后定义新的数组MIP_1[]存储变换后的内容,依靠变换明文的数组M[]的下标来变换数据顺序,并存入数

组MIP_1[]中。

图3-3 逆初始置换示意图

主要代码:

for (int i = 0; i < 64; i++) {

MIP_1[i] = M[IP_1[i] - 1];

}

3.4密钥选择置换

数组key[]存储着密钥的二进制形式,用设置好的选择置换PC_1的数组PC_1[]对key[]进行置换,其结果存入K0[](56bite);

接着对K0[]进行循环左移(详细方法见3.5)。

循环左移后返回的数组K0[],用设置好的选择置换PC_2的数组PC_2[]对K0[]进行置换,得到的结果存入二维数组keyarray[][]中,将会进行16轮运算,keyarray中每行代表1轮运算结果。

图3-4 子密钥计算流程图

主要代码:

for (i = 0; i < 56; i++) {

K0[i] = key[PC_1[i] - 1];

}

for (i = 0; i < 16; i++) {

LeftBitMove(K0, LeftMove[i]);

for (j = 0; j < 48; j++) {

keyarray[i][j] = K0[PC_2[j] - 1];

}

}

3.5循环左移

K[]存储着56bite初始密钥,用C0[]、D0[]分别存储其28比特部分,然后根据各轮位移位数的LeftMove[]数组,判断C0、D0的数据分别左移1位或2位,

其结果存储到C1、D1中,然后合并C1、D1的数据存储到数组K[]中。

表3-5 循环左移位表

主要代码:

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];

}

1[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];

}

3.6字节填充

先读取用户输入数据的byte数组data[]的长度位len,若len位8的整数倍,则不需要填充,直接返回数值。

否则,先判断需要填充的位数padlen,然后计算出填充后的位数newlen,

最后定义一个新数组newdata[](长度为newlen),使用arraycopy方法将data[]拷入newdata[]中,新补充的位数自动填充为0。

主要代码:

if(len%8==0){

return data;

}else{

byte[] newdata = new byte[newlen];

System.arraycopy(data, 0, newdata, 0, len);

return newdata;

3.7数据转二进制数组

定义1个8位数组InDa[](int型),来存储用户输入数据的byte数组intdata[],若是intdata含有负数值(例如中文输入),将其转为正数的ASCII 值。

定义1个64位数组IntVa[](int型),然后使用经典的模2取余法,将数组InDa中的值转为2进制,然后依次存储到InVa中。

主要代码:

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;

}

}

3.8二进制数组转八位数组

对2进制数组data[]使用移位的方式,每位进行累加,算出结果即是二进制转换的一个整数。若是算出的值超出ASCII的256范围或可显示的128位,则转换成可显示的位数。

主要代码:

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;

}

}

}

3.9密文字符串转byte数组

将输入的字符串strIn用getBytes()方法存储到arrB数组中,然后查询字符串长度Len。定义新数组arrOut[]来存储转换后的数据,因为输入的字符串是2个字符组成一个字节的数据,所以arrOut长度为Len/2。

用创建新String类型的方法,将arrB中每2个字符写成1个新字符串strTmp,最后使用Interger.parseInt方法将其转为byte类型,装入arrOut。

主要代码:

byte[] arrB = strIn.getBytes();

int Len = arrB.length;

byte[] arrOut = new byte[Len / 2];

for (int i = 0; i < Len; i = i + 2) {

String strTmp = new String(arrB, i, 2);

arrOut[i / 2] = (byte) Integer.parseInt(strTmp, 16);

}

3.10加密或解密

定义flags,若为1代表加密,为0代表解密。

先对内容进行IP初始置换,然后根据flags值,用不同的循环调用LoopF 函数进行轮结构。若是flags为1,则在i=15时合并左右部分;若是flags为0,则在i=0时合并左右部分(原因是涉及到LoopF函数的构造)。接着进行IP_1逆初始置换,最后调用Arraytobyte函数将保存着内容的MIP_1(2进制数组)转为存着8个整数的数组。

图3-10 加密流程图

主要代码:

M = IPchange(timeData);

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);

}

}

MIP_1 = IP_1change(M);

Arraytobyte(MIP_1, encrypt);

3.11三重DES加密解密

使用已经完成的DES加解密方法,连续调用3次方法,每次使用3个不同的密钥,这是3DES实现的基本思路。

由于每次加密后是byte数组,必须先转化为伪16进制字符串,然后再次转化为byte数组进行加解密。用flag值来确定是加密还是解密。其最终的结果保存在result3中,返回其值。

图3-11 三重DES加密解密示意图

if(flag == 1){

result1 = des1.DesEncrypt(data.getBytes(), 1);

String tmp="";

for(int i=0;i

{

String tmpStr=Integer.toHexString(result1[i]&0xff);

tmp += "00".substring(tmpStr.length()) + tmpStr;

}

result2 = des2.DesEncrypt(tmp.getBytes(), 1);

tmp="";

for(int i=0;i

{

String tmpStr=Integer.toHexString(result2[i]&0xff);

tmp += "00".substring(tmpStr.length()) + tmpStr;

}

result3 = des3.DesEncrypt(tmp.getBytes(), 1);

}else if(flag == 0){

result1 = des3.DesEncrypt(Stringtobyte(data), 0);

result2 = des2.DesEncrypt(Stringtobyte(new String(result1)), 0);

result3 = des1.DesEncrypt(Stringtobyte(new String(result2)), 0);

}

4. 测试报告

(1) 对十六进制数加密

明文:2011121064

密钥:12345678

密文:8b5cfb54621eadb27e9330d85c042369

解密后的明文: 2011121064

图4-1 加密示意图

(2) 对十六进制数解密

明文:2011121064

密钥:12345678

密文:8b5cfb54621eadb27e9330d85c042369

图4-2 解密示意图(3)三重DES加密

图4-3 3des加密示意图

相关主题
文本预览
相关文档 最新文档