DES加密解密算法的实现(Java基本要求)

时间:2024.5.14

成都信息工程学院

课程设计报告

DES加密解密算法的实现(Java)

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

学生姓名:      李文浩         

学生学号:     2007122054    

专业班级:     信安072班       

任课教师:      万武南         

20##年  11 月  11  日



目  录

1.引言... 1

1.1 背景... 1

1.2 目的... 1

1.3 本设计的主要任务... 1

2.系统设计... 2

2.1系统主要目标... 2

2.1.1主要软件需求(运行环境)... 2

2.2 系统结构... 2

2.2.2 软件操作流程... 2

2.2.3功能模块... 3

3 系统功能程序设计... 3

3.1循环移位... 3

3.2获取RoundKey. 4

3.3 IP置换,逆置换,E扩展,置换P. 5

3.4 Fnew函数(F函数). 5

3.5异或... 7

3.6 S盒代替... 7

3.7十六进制转二进制... 7

3.8二进制转十六进制... 8

3.9加密... 9

3.10解密... 9

3.11程序界面预览... 10

4. 测试报告... 11

5.结论... 14

参考文献... 14


1.引言

1.1 背景

数据加密标准(Data Encryption Standard,,DES)曾被美国国家标准局(NBS,现为国家标准与技术研究所NIST)确定为联邦信息处理标准(FIPS PUB 46),得到过广泛使用,特别是在金融领域,曾是对称密码体制事实上的世界标准。目前在国内,随着三金工程尤其是金卡工程的启动,DES算法在POS,ATM,智能卡,加油站,高速公路收费站等领域被广泛使用,以此来实现关键数据加密,如信用卡持卡人的PIN的加密传输,IC卡与POS间的双向认证、金融交易数据包的MAC校验等,均用到DES算法。

DES起源于1973年美国国家标准局NBS征求国家密码标准方案。IBM就提交了其在20世纪60年代末设立的一个计算机密码编码学方面的研究项目的结果,这个项目在1971年结束时研制出了一种称为Lucifer算法。它是当时提出来的最好的算法,因而在1977年被选为数据加密标准,有效期为5年,随后在1983年、1987年、和1993年三次再度授权该算法续用5年。

DES使用一个56位的密钥以及附加的8位奇偶校验位,产生最大64位的分组大小。这是一个迭代的分组密码,使用称为 Feistel 的技术,其中将加密的文本块分成两半。使用子密钥对其中一半应用循环功能,然后将输出与另一半进行“异或”运算;接着交换这两半,这一过程会继续下去,但最后一个循环不交换。DES 使用 16 个循环。

1.2 目的

在一些特殊场合,人们交换信息并不希望被其他人知道,需要把消息进行一系列转换后在公共信道中传输,接收方再通过一些手段将消息转换回来,本程序用DES对称密钥加密算法加解密一组长度为64bit的十六进制数,达到保密传递信息的目的.

1.3 本设计的主要任务

根据DES加密算法实现一组长度为64bit的十六进制数加密解密。向用户提供良好的交互,具有良好的操作性。可完成一个明文分组的加解密,明文和密钥是十六进制,长度都为64比特(16个16进制数),输入明文和密钥,输出密文,进行加密后,能够进行正确的解密;程序运行时,要求输出每一轮使用的密钥,以及每一轮加密或解密之后的16进制表示的值。

2.系统设计

2.1系统主要目标

2.1.1主要软件需求(运行环境)

本软件适用java语言编写,编译成功后的.class文件可以在装有JDK开发环境的任何计算机上使用。本软件设计符合DES程序设计基本要求:

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

(2)完成一个明文分组的加解密,明文和密钥是十六进制,长度都为64比特(16个16进制数),输入明文和密钥,输出密文,进行加密后,能够进行正确的解密;

(3)程序运行时,要求输出每一轮使用的密钥,以及每一轮加密或解密之后的16进制表示的值;

(4)要求提供所设计系统的报告及完整的软件。

输入:

       加密:8字节定长的十六进制明文(16个十六进制数)。

       解密:8字节定长的十六进制密文(16个十六进制数)。

输出:

       加密:8字节定长的十六进制已加密的密文(16个十六进制数)。

       解密:8字节定长的十六进制的正常解密的明文(16个十六进制数)。

测试平台:Windows Vista Home Basic/Windows XP Professional

2.2 系统结构

2.2.2 软件操作流程

加密:

(1)按提示选择“1”进行加密过程,程序将正常执行下面的加密过程。

(2)按提示输入你加密所需要的长度为16个十六进制的密钥。

(3)按提示输入你要加密的长度为16个十六进制的明文。

(4)加密后,每轮加密结果和最终加密结果(即密文)将显示给用户。

解密:

(1)按提示选择“0”进行解密过程,程序将正常执行下面的解密过程。

(2)按提示输入你解密所需要的长度为16个十六进制的密钥。

(3)按提示输入你要解密的长度为16个十六进制的密文。

(4)解密后,每轮解密的结果和最终解密出的明文将显示给用户。

2.2.3功能模块

3 系统功能程序设计

3.1循环移位

实现循环移位,由于DES算法涉及到得只有循环左移一位或者两位,我考虑用穷举的方法,因为只有两种情况,因此用if条件语句判断每轮循环的位数。我定义了4个中间变量co,do,c1,d1存放中间结果。

Void LwhDES::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];

   }

}

3.2获取RoundKey

生成轮子密钥前调用了PC1变换函数,循环过程中调用了循环移位函数和PC2变换函数,最终生成了KeyArray[16][48]的轮子密钥。

int[][] LwhDES::KeyInitialize(int[] key)

{

   int i;

   int j;

   int[][] keyarray=new int[16][48];

   int[] K0 = new int[56];

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

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

         keyarray[i][j] = K0[PC_2[j] - 1]; // 生成子密钥keyarray[i][j]

      }

   }

   return keyarray;

}

3.3 IP置换,逆置换,E扩展,置换P

置换使用的是简单的查表置换,table置换,即将输出的数据与输入的数据相应的数组的对应项查出来。

IP置换:

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

{

       M[i] = timeData[IP[i] - 1]; // 明文IP变换, IP[]为IP置换表

       ……}

IP逆置换:

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

{

MIP_1[i] = M[IP_1[i] - 1]; // 进行IP-1运算, IP_1[]为IP逆置换表

……}

E扩展:

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

        RE[i] = R0[E[i] - 1]; // 经过E变换扩充,由32位变为48位}

置换P:

for (i = 0; i < 32; i++)

{

       RP[i] = sValue[P[i] - 1]; // 经过P变换, P[]为P置换表

……}

3.4 Fnew函数(F函数)

F函数为该加密程序最关键的地方,里面涉及到E扩展,与密钥异或,S盒压缩,P置换,每轮都要使用此函数,此函数编写的好坏很大程度上影响整个程序的执行效率。注意,此处的Fnew函数与标准F函数略有不同, Fnew函数将F函数后Lo,Ro的异或和换位都已经实现。

Void LwhDES::private void LoopF(int[] M, int times, int flag, int[][] keyarray)

{

  int i,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]; //存放经过E扩展的消息

  int[][] S = new int[8][6]; //存放成8行六列,以便进行S盒压缩

  int[] sBoxData = new int[8]; //每一行查出的数

  int[] sValue = new int[32]; //

  int[] RP = new int[32]; //经过置换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]; // 经过E变换扩充,由32位变为48位

        RE[i] = RE[i] + keyarray[times][i]; // 与KeyArray[times][i]按位作不进位加法运算

     if (RE[i] == 2) {     //与48位密钥异或

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

 }}}

3.5异或

Java语言我使用” ^ ”符号进行异或,结果没有成功,于是利用循环实现各个位相加,再每位检查,若等于2,则置为0。

  for (i = 0; i < 48; i++) { ……

        RE[i] = RE[i] + keyarray[times][i];     // 两个数进行不进位加法

     if (RE[i] == 2)    //若加出的结果为2则置为0,实现了异或

{

           RE[i] = 0;

    }}

3.6 S盒代替

S盒替换采用了将48个bit数先分为8组,每一组对应一个S盒,再通过行列计算查出S表里的十进制值,再转化为二进制。

int[] RE = new int[48];

  int[][] S = new int[8][6];

  int[] sBoxData = new int[8];

  int[] sValue = new int[32];

for (i = 0; i < 8; i++)                              // 48位分成8组

  {

              for (j = 0; j < 6; j++)                  //每组6位

              {

                     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;

              }

  }

3.7十六进制转二进制

本函数主要用于十六进制数向二进制数的转换,十六进制数只有十六种情况,本程序使用穷举方法,利用switch、case语句实现十六进制对二进制的转换,避免移位出现不可预计的错误。

int[] LwhDES::changeHtoB(String s) //实现十六进制到二进制的转换;

       {

          int [] Message=new int[64];

          StringBuffer buf = new StringBuffer();

          String str=s;

          String message="";

          int i,j;

          for(i=0;i<str.length();i++)

       {

            char ch=str.charAt(i);

            switch(ch){

         

                  case '0' : message = "0000"; break;  case '1' : message = "0001"; break;

                     case '2' : message = "0010"; break;  case '3' : message = "0011"; break;

                     ……

                     case 'e' : message = "1110"; break;  case 'f' : message = "1111"; break;

                     default: break;

                  }

        buf=buf.append(message);

              }

              //System.out.print(buf);

           for(j=0;j<64;j++)

              {

                 if (buf.charAt(j)=='0')

                        { Message[j]=0; }

                 else Message[j]=1;

              } 

              return Message;

   }

3.8二进制转十六进制

本函数主要用于将结果二进制数转换成十六进制向用户输出,实现二进制转十六进制数,即4个bool型变量转化为一个十六进制数,先将bool流写入StringBuffer,再调用toString转化成字符串,对字符串进行取子串,再调用Integer.toHexString方法转换为十六进制。

String LwhDES::changeBtoH(int[] data)

{      //实现二进制到十六进制的转换;

    StringBuffer buf=new StringBuffer();

String s=new String();

for(int i=0;i<data.length;i++)

       {

              if(data[i]==0) buf.append('0');

              else if(data[i]==1) buf.append('1');

       }

    String string=buf.toString(); //形成一个全是bool变量(0或1)的字符串

    int temp=0;

    StringBuffer outputbuf=new StringBuffer();

    String s1=string.substring(0,data.length);

    for(int i=0;i<s1.length()/4;i++)    //每四位取一次,表示一个十六进制数

       {

        temp=Integer.valueOf(  s1.substring(i*4,(i+1)*4)  ,  2 );

        outputbuf=outputbuf.append(Integer.toHexString(temp));

     }

//System.out.print(outputbuf);

s=outputbuf.toString();

return s;

}

3.9加密

加密过程其实就是调用以写好的模块,对消息进行16次迭代加密,但在每一轮中要进行中间一些加密结果的显示,又因为加密和解密我写在了同一个Encrypt函数里,因此只用标志位flag区别加解密,1为加密,0为解密。

int[] LwhDES::Encrypt(int[] timeData, int flag, int[][] keyarray)

{

   int i;

   int flags = flag;

   int[] M = new int[64];

   int[] MIP_1 = new int[64];

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

   {

          M[i] = timeData[IP[i] - 1]; // 明文IP变换

  }

   if (flags == 1)

   { // 加密

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

         {

Fnew(M, i, flags, keyarray);  //注意,LoopF函数将每轮迭代运算的 Li=Ri-1, //Ri=Li-1^F(Ri-1,Ki)一起写了进去

……//显示中间结果

       }

}

3.10解密

解密过程与加密相逆,其实也是调用写好的模块,对密文进行16次迭代解密,但在每一轮中要进行中间一些加密结果的显示,又因为加密和解密我写在了同一个Encrypt函数里,因此只用标志位flag区别加解密,1为加密,0为解密。

int[] LwhDES::Encrypt(int[] timeData, int flag, int[][] keyarray)

{

else if (flags == 0)

  { // 解密

      for (i = 15; i > -1; i--)

      {

                     Fnew(M, i, flags, keyarray); //关键的解密步骤,下面代码都是为显示中间结果

                     int n,j;

                     int [] k=new int[48];

                     System.out.println("第" + (16-(i+1)) +"轮输出的密文的十六进制形式:");

                     System.out.println(changeBtoH(M));

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

          {

                     k[j]=keyarray[i][j];

          }

          System.out.println("第" + (16-(i+1)) +"轮输出的轮子密钥十六进制形式:");

          System.out.println(changeBtoH(k));

       }

  }}

3.11程序界面预览

在命令行窗口进行操作,界面比较友好,易于操作,下图为开始界面:

图1

4. 测试报告

(1) 对十六进制数加密

明文:31 32 33 34 35 36 37 38

密钥:31 32 33 34 35 36 37 38

密文:96 d0 02 88 78 d5 8c 89

解密后的明文: 31 32 33 34 35 36 37 38

选择加密初始化明文和密钥:

图2

加密结果与标准一致:

图3

图4

对密文进行直接解密,得出正确的结果:

图5

图6

(2) 对十六进制数解密

明文:96 d0 02 88 78 d5 8c 89

密钥:31 32 33 34 35 36 37 38

密文:31 32 33 34 35 36 37 38

经过检测:

1.本软件符合DES基本要求,能对16个十六进制数进行正常的加密和解密,加密和解密结果没有错误,并能显示每轮加密的中间结果。

2.对于错误的输入,能以提示性语言加以提示。

3.没有发现导致致命错误的操作方法。

5.结论

本软件可以实现DES加密解密算法的基本要求,可以正确地对8个字节的明文进行加密,或者对8个字节的密文进行正常的解密。通过本次的课程,我对DES的算法有了进一步深入的了解,深刻了解了DES加密的每轮迭代过程,对简单的异或,移位有了更深的了解,灵活运用可以实现许多功能,通过对DES算法的异或,置换,查S盒压缩等方便的编写,对java语言编程有了更深刻的掌握,比如编写异或事由于没查到Java语言中异或的运算符,我就简单的使用各位相加后,若为2则置为零来代替。本来希望使用c++实现DES加密解密算法,虽然能正常加解密,但是中间过程输出结果与标准有差异,而且,由于Java中String, StringBuffer提供许多方法,使程序比C++方便的实现了十六进制的转换问题。

参考文献

[1]  胡向东、魏琴芳,应用密码学,电子工业出版社,2008

[2]  Mary Campione,语言导学,机械工业出版社,2003

[3] 孙卫琴,Java面向对象编程,电子工业出版社,2006

[4] (美)埃克尔,Java编程思想,机械工业出版社,2007

更多相关推荐:
DES加密算法实验报告

网络安全作业题目DES学号专业及班级姓名日期20xx0414加密算法网络工程0902班一DES简介DES是一个分组密码算法使用64位密钥除去8位奇偶校验实际密钥长度为56位对64比特的数据分组二进制数据加密产生...

RSA加密算法实验报告

四川大学计算机学院实验报告

AES加密算法实验报告

实验报告AES加密算法一实验环境1硬件配置酷睿i3cpu2G内存2使用软件1操作系统windows7旗舰版2软件工具visualc60二AES涉及的相关概念或基本原理简介密码学中的高级加密标准AdvancedE...

DES加密算法实验报告

DES加密算法实验报告在DES加密算法中加密方使用一个64位明文与56位密钥来生成64位的密文解密方通过64位的密文与56位密钥还原出明文在此过程中加解密双方使用一个56位密钥DES加密算法一般结构如下DES加...

RSA加密算法实验报告

信息与计算科学专业操作性实验报告年级20xx级姓名学号指导教师实验课程名称RSA加密算法开课实验室理学楼210实验内容1实验作业题目用Cbuilder实现RSA加密算法2实验作业课时4个课时3实验过程包括实验环...

DES加密算法实验报告

苏州科技学院实验报告学生姓名杨刘涛学号1220xx6117指导教师陶滔刘学书1220xx6114实验地点计算机学院大楼东309实验时间20xx0420一实验室名称软件实验室二实验项目名称DES加解密算法实现三实...

DES加密算法的简单实现实验报告

苏州科技学院电子与信息工程学院实验报告实验一实验课程名称实验名称实验报告一实验室名称电子学院213机房二实验项目名称DES加密算法的简单实现三实验学时2学时四实验原理DES的描述DES是一种分组加密算法他以64...

计算机网络安全传统加密算法实验报告

北京林业大学20xx学年20xx学年第2学期计算机网络安全实验报告书专业计算机科学与技术班级计算机122姓名侯丹学号120xx4227实验地点N01任课教师蒋东辰实验题目传统加密算法实验环境Windows操作系...

加密算法编程实验

天津机电职业技术学院教师备课纸实验五加密算法编程一实验目的通过C语言编程实现替代加密算法加深对古典密码体制的了解二实验环境1安装WindowsXP系统的计算机2WinTC三实验理论基础凯撒密码caeser是罗马...

DES_加密解密算法的C++实现--实验报告

实验报告课程名称高级Java程序设计实验项目搭建JSP开发和运行环境实验仪器个人计算机系别理学院专业信息与计算科学班级学号信计110220xx012529学生姓名高敏实验日期20xx311成绩指导教师徐莉实验项...

DES 加密解密算法的C++实现--实验报告

网络与信息安全IntroductiontoNetworkandSecurityDES加密解密算法的C实现姓名学号学院20xx年10月一DES算法的实现1DES简介本世纪五十年代以来密码学研究领域出现了最具代表性...

RSA加密算法实验报告

现代密码学实验报告题目RSA算法的实现过程一实验目的简单实现RSA过程通过OpenSSL命令编辑器实现发送方对明文进行加密签名接受方验证解密的简单过程二实验原理RSA加密算法的基本流程三实验步骤发送方对明文进行...

加密算法实验总结(22篇)