DES实验报告

  • Post author:
  • Post category:其他




DES 实验报告和执行原理



1. 实验目的

了解DES算法的原理,以及DES算法的使用



2. 实验原理

  1. DES算法介绍:DES算法作为密码体制中的对称密码体制,明文按64位进行分组,密匙长64位,密匙实际是56位参与DES运算,另外的8位被用于奇偶验证。
  2. 然后56位分成两个28位密匙,每半个密匙都被分别处理。在接下来的循环中,两个半密匙都被左移一位或2位,然后通过置换2产生48位子密匙,每个半密匙24位,
  3. 解密过程中,除了子密匙的输出顺序相反外,密匙的调度过程完全一样。整体架构如图:2-1所示。

在这里插入图片描述



3. DES工作

  1. DES是一个基于组块的加密算法,这意味着无论输入还是输出都是64位长度的。也就是说DES产生了一种最多264种的变换方法。每个64位的区块被分为2个32位的部分,左半部分L和右半部分R。(这种分割只在特定的操作中进行。)
  2. 比如取明文M= 123456789ABCDEF,转化为二进制,我们得到一个64位的区块,64位的区块分为两个32位的部分即

```c
M=0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
L= 0000 0001 0010 0011 0100 0101 0110 0111
R =1000 1001 1010 1011 1100 1101 1110 1111

3. 	初始IP置换是的产生的过程由下表决定(DES使用56位密匙进行操作的,也就是第8,16,24,32,40,48,56,64 位没有使用,即每一组的最后一位没有使用),得到新的密匙M+

```c
 
M = 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010
                   1011 1100 1101 1110 1111 
M+ = 1111000 0110011 0010101 0101111 0101010 1011001 
1001111 0001111

然后,将这个秘钥拆分为左右两部分,C0 和 D0,每半边都有28 位。比如,对于新秘钥,我们得到:

C0=1111000 0110011 0010101 0101111
D0= 0101010   1011001   1001111   0001111
  1. 对相同定义的C0 和 D0,我们现在创建16个块Cn 和 Dn, 1<=n<=16。每一对Cn 和 Dn都是由前一对Cn-1 和 Dn-1移位而来。具体说来,对于n = 1, 2, …, 16,在前一轮移位的结果上,使用下表进行一些次数的左移操作。什么叫左移?左移指的是将除第一位外的所有位往左移一位,将第一位移动至最后一位,使得移位后的比特的位置相较于变换前成为2, 3,…, 28, 1。。
C0 = 1111000011001100101010101111
D0 = 0101010101100110011110001111
C1 = 1110000110011001010101011111
D1 = 1010101011001100111100011110
C2 = 1100001100110010101010111111
D2 = 0101010110011001111000111101
C3 = 0000110011001010101011111111
D3 = 0101011001100111100011110101
C4 = 0011001100101010101111111100
D4 = 0101100110011110001111010101
C5 = 1100110010101010111111110000
D5 = 0110011001111000111101010101
C6 = 0011001010101011111111000011
D6 = 1001100111100011110101010101
C7 = 1100101010101111111100001100
D7 = 0110011110001111010101010110
C8 = 0010101010111111110000110011
D8 = 1001111000111101010101011001
C9 = 0101010101111111100001100110
D9 = 0011110001111010101010110011
C10 = 0101010111111110000110011001
D10 = 1111000111101010101011001100
C11 = 0101011111111000011001100101
D11 = 1100011110101010101100110011
C12 = 0101111111100001100110010101
D12 = 0001111010101010110011001111
C13 = 0111111110000110011001010101
D13 = 0111101010101011001100111100
C14 = 1111111000011001100101010101
D14 = 1110101010101100110011110001
C15 = 1111100001100110010101010111
D15 = 1010101010110011001111000111
C16 = 1111000011001100101010101111
D16 = 0101010101100110011110001111
  1. 我们现在就可以得到第n轮的新秘钥Kn( 1<=n<=16)了。具体做法是,对每对拼合后的子秘钥CnDn,按表PC-2执行变换:

每对子秘钥有56位,但PC-2仅仅使用其中的48位。于是,第n轮的新秘钥Kn 的第1位来自组合子秘钥CnDn的第14位,第2位来自第17位,依次类推,知道新秘钥的第48位来自组合秘钥的第32位。

C1D1 = 1110000 1100110 0101010 1011111 1010101 0110011
       0011110 0011110
K1 = 000110 110000 001011 101111 111111 000111 000001 110010
K2 = 011110 011010 111011 011001 110110 111100 100111 100101
K3 = 010101 011111 110010 001010 010000 101100 111110 011001
K4 = 011100 101010 110111 010110 110110 110011 010100 011101
K5 = 011111 001110 110000 000111 111010 110101 001110 101000
K6 = 011000 111010 010100 111110 010100 000111 101100 101111
K7 = 111011 001000 010010 110111 111101 100001 100010 111100
K8 = 111101 111000 101000 111010 110000 010011 101111 111011
K9 = 111000 001101 101111 101011 111011 011110 011110 000001
K10 = 101100 011111 001101 000111 101110 100100 011001 001111
K11 = 001000 010101 111111 010011 110111 101101 001110 000110
K12 = 011101 010111 000111 110101 100101 000110 011111 101001
K13 = 100101 111100 010111 010001 111110 101011 101001 000001
K14 = 010111 110100 001110 110111 111100 101110 011100 111010
K15 = 101111 111001 000110 001101 001111 010011 111100 001010
K16 = 110010 110011 110110 001011 000011 100001 011111 110101
  1. 上面我们通过IP置换的得到了初始M+,其中L0和R0
L0 = 0000 0001 0010 0011 0100 0101 0110 0111
R0 =1000 1001 1010 1011 1100 1101 1110 1111

我们接着执行16个迭代,对1<=n<=16,使用一个函数f。函数f输入两个区块——一个32位的数据区块和一个48位的秘钥区块Kn ——输出一个32位的区块。定义+表示异或XOR。那么让n从1循环到16,我们计算

Ln = Rn-1

Rn = Ln-1 + f(Rn-1,Kn)

这样我们就得到最终区块,也就是n = 16 的 L16R16。这个过程说白了就是,我们拿前一个迭代的结果的右边32位作为当前迭代的左边32位。对于当前迭代的右边32位,将它和上一个迭代的f函数的输出执行XOR运算。

当n=1 时,

K1 = 000110 110000 001011 101111 111111 000111 000001 110010
L1 = R0 = 1111 0000 1010 1010 1111 0000 1010 1010
R1 = L0+f(R0,K1)

计算F函数,首先将每一个Rn-1从32位扩展到48。我们把这个过程称为函数E。定义E位函数的输出,将其写成8组,每组6位。具体实现通过下表生成。

也就是说E(Rn-1) 开头的三个比特分别来自Rn-1的第32、1和2位。E(Rn-1) 末尾的2个比特分别来自Rn-1的第32位和第1位。

比如,给定R0 ,我们可以计算出E(R0) :

R0 = 1111 0000 1010 1010 1111 0000 1010 1010 
E(R0) = 011110 100001 010101 010101 011110 100001 010101 010101

接着在f函数中,我们对输出E(Rn-1) 和秘钥Kn执行XOR运算:

Kn + E(Rn-1)

比如:对K1,E(R0),进行异或操作

K1 = 000110 110000 001011 101111 111111 000111 000001 110010 
E(R0) = 011110 100001 010101 010101 011110 100001 010101 010101 
K1+E(R0) = 011000 010001 011110 111010 100001 100110 010100 100111.

到这里我们还没有完成f函数的运算,我们仅仅使用一张表将Rn-1 从32位拓展为48位,并且对这个结果和秘钥Kn执行了异或运算。我们现在有了48位的结果,或者说8组6比特数据。我们现在要对每组的6比特执行一些奇怪的操作:我们将它作为一张被称为“S盒”的表格的地址。每组6比特都将给我们一个位于不同S盒中的地址。在那个地址里存放着一个4比特的数字。这个4比特的数字将会替换掉原来的6个比特。最终结果就是,8组6比特的数据被转换为8组4比特(一共32位)的数据。

将上一步的48位的结果写成如下形式:

Kn + E(Rn-1) =B1B2B3B4B5B6B7B8,

每个Bi 都是一个6比特的分组,我们现在计算

S1(B1)S2(B2)S3(B3)S4(B4)S5(B5)S6(B6)S7(B7)S8(B8)

其中,Si(Bi) 指的是第i个S盒的输出。

为了计算每个S函数S1, S2,…, S8,取一个6位的区块作为输入,输出一个4位的区块。决定S1的表格如下

如果S1 是定义在这张表上的函数,B是一个6位的块,那么计算S1(B) 的方法是:B的第一位和最后一位组合起来的二进制数决定一个介于0和3之间的十进制数(或者二进制00到11之间)。设这个数为i。B的中间4位二进制数代表一个介于0到15之间的十进制数(二进制0000到1111)。设这个数为j。查表找到第i行第j列的那个数,这是一个介于0和15之间的数,并且它是能由一个唯一的4位区块表示的。这个区块就是函数S1 输入B得到的输出S1(B)。比如,对输入B = 011011 ,第一位是0,最后一位是1,决定了行号是01,也就是十进制的1 。中间4位是1101,也就是十进制的13,所以列号是13。查表第1行第13列我们得到数字5。这决定了输出;5是二进制0101,所以输出就是0101。也即S1(011011) = 0101。

同理,定义这8个函数S1,…,S8的表格如下所示

                         S1
 
 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
                              S2
 
 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
                              S3
 
 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
                              S4
 
  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
                              S5
 
  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
                             S6
 
 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
                             S7
 
  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

                             S8
 
 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

例子:对于第一轮,我们得到这8个S盒的输出:

K1 + E(R0) = 011000 010001 011110 111010 100001 100110 010100 100111.
S1(B1)S2(B2)S3(B3)S4(B4)S5(B5)S6(B6)S7(B7)S8(B8) = 0101 1100 1000 0010 1011 0101 1001 0111

函数f的最后一步就是对S盒的输出进行一个变换来产生最终值:

f = P(S1(B1)S2(B2)…S8(B8))

变换P由如下表格定义。P输入32位数据,通过下标产生32位输出:

                      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

比如,对于8个S盒的输出:

S1(B1)S2(B2)S3(B3)S4(B4)S5(B5)S6(B6)S7(B7)S8(B8) = 0101 1100 1000 0010 1011 0101 1001 0111

我们得到

f = 0010 0011 0100 1010 1010 1001 1011 1011
那么,
R1 = L0 + f(R0 , K1 )
= 1100 1100 0000 0000 1100 1100 1111 1111 
+ 0010 0011 0100 1010 1010 1001 1011 1011 
= 1110 1111 0100 1010 0110 0101 0100 0100

在下一轮迭代中,我们的L2 = R1,这就是我们刚刚计算的结果。之后我们必须计算R2 =L1 + f(R1, K2),一直完成16个迭代。在第16个迭代之后,我们有了区块L16 and R16。接着我们逆转两个区块的顺序得到一个64位的区块: R16L16

然后对其执行一个最终的变换 IP-1 ,其定义如下表所示:

也就是说,该变换的的输出的第1位是输入的第40位,第2位是输入的第8位,一直到将输入的第25位作为输出的最后一位。

比如,如果我们使用了上述方法得到了第16轮的左右两个区块:

L16 = 0100 0011 0100 0010 0011 0010 0011 0100 
R16 = 0000 1010 0100 1100 1101 1001 1001 0101

我们将这两个区块调换位置,然后执行最终变换:

R16L16 = 00001010 01001100 11011001 10010101 01000011 01000010 00110010 00110100
IP-1=-10000101 11101000 00010011 01010100 00001111 00001010 10110100 00000101
所以明文:M= 123456789ABCDEF
得到密文:85E813540F0AB405



4.实验代码



4.1 运行环境

  1. 运行平台:window 10
  2. Idea工具:eclipse
  3. JDK:1.8



4.2 实现代码:

 package com.dome.des;

import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class DESDome {
	
	public static void main(String[] args) 
	{
		
        String source  = "测试des加密";
        String key = "123456781";
        String result = encrypt(source, key);
        //加密结果
        System.out.println("密文:"+result);
        //解密
        String s=decrypt(result, key);
        System.out.println("明文:"+s);
	}
	
	/*
	 * DES 解密
	 * @param cryptograph 密文
	 * @param key 密匙
	 * */
	private static String decrypt(String cryptograph, String key) {
		// 强加密随机生成器
		SecureRandom rand=new SecureRandom();
		try 
		{ 
			//定义私钥的规则
			DESKeySpec keySpec=new DESKeySpec(key.getBytes());
			//定义密钥工厂
			SecretKeyFactory factory=SecretKeyFactory.getInstance("DES");
			//按照密钥规则生成密钥
			SecretKey secretKey=factory.generateSecret(keySpec);
			//创建加密对象
			Cipher cipher =Cipher.getInstance("DES");
			cipher.init(Cipher.DECRYPT_MODE,secretKey,rand);
			byte[] result=new BASE64Decoder().decodeBuffer(cryptograph);
			return new String(cipher.doFinal(result));
		
		}catch(Exception e)
		{
			e.printStackTrace();
		}
		return null;
		
	}

	/**
	 * 
	 * DES 加密操作
	 * @param source  明文
	 * @param key 密匙
	 * */
	public  static String encrypt(String source,String key) 
	{
		//强加密随机数生成器
		SecureRandom  rand=new SecureRandom();
		try 
		{
			//创建密匙
			DESKeySpec keySpec =new DESKeySpec(key.getBytes());
		      //创建密钥工厂 
			SecretKeyFactory factory= SecretKeyFactory.getInstance("DES");
			//将密码规则生长密匙
			SecretKey secretKey = factory.generateSecret(keySpec);
			//加密对象
			Cipher cipher =Cipher.getInstance("DES");
			//初始化加密对象需要的属性
			cipher.init(Cipher.ENCRYPT_MODE, secretKey,rand);
			//开始加密
			byte[] result= cipher.doFinal(source.getBytes());
			//Base64加密
			 return  new BASE64Encoder().encode(result) ;
			
			
		}catch (Exception e) {
		   e.printStackTrace();
		}
		return null;
		
	}

}



5. 实验结果

在这里插入图片描述


原作者的详细介绍



版权声明:本文为golden_stone_fish原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。