DES 加密算法

DES是一种对称分组密码算法,基于Feistel结构,使用64位分组和56位密钥。加密过程包括初始置换、子密钥生成、16轮迭代和逆置换。子密钥生成通过PC-1和PC-2置换以及循环左移。每轮迭代包含扩展置换、异或、S盒和P盒操作。DES算法在加密领域曾是标准,但因安全性已不再足够,现已被AES取代。
摘要由CSDN通过智能技术生成

一、DES 加密算法概述

        现在密码算法可分为对称密码(Symmetric Cryptology)和非对称密码

        (Asymmetric Cryptology);其区分依据主要是所采用的密钥间的关系。在对称密码中,加密密钥和解密密钥是完全相同的,或彼此之间容易互相推导。在非对称密码算法,或称为公钥密码(Public Key Cryptology)中,加密密钥和解密密钥是不同的,从加密密钥推导出解密密钥在计算上是不可行的 (Computationally infeasible)。

        根据对明文的处理方式不同,密码算法又可分为流密码(Stream Cipher)和分组密码(Block Cipher)。一次只对明文中的单个比特(有时对字节)运算的密码称为流密码。对明文的一组比特进行运算,这些比特组称为分组(如 64位比特为一组),相应的密码称为分组密码。

        1973 年,美国国家标准局(NBS)开始征集一种标准的数据加密标准算法(DES),以用于非机密性政府机构、商业部门和民间的对非机密的敏感数据进行加密。IBM 公司在 1971 年完成的 LUCIFER 密码(64 比特分组,128 比特密钥)的基础上,改进成为建议的 DES。改进后的 DES 算法仅使用 56 比特密钥,同时对 S 盒的修改被列入官方机密,曾广受批评。1975 年 3 月 17 日,NBS 公布了这个算法,并说明要以它作为联邦信息处理标准,征求各方意见。1977 年 1 月15 日,建议被批准为联邦标准—FIPSPUB 46,并设计推出了 DES 芯片。1981 年, ANSI 将 DES 作为标准,即 DEA[ANSI X3.92]。1983 年,ISO 采用 DES 作为标准,即 DEA-1。DES(Data Encryption Standard)是一个优秀的对称分组密码算法,直到 2000 年 10 月 2 日 NIST 宣布 AES 算法前,其一直是业界的标准。

二、DES 加密算法原理

        DES 算法使用的是 Feistel 框架,Feistel 框架的密码结构是用于分组密码 中的一种对称结构,Feistel 框架使用的是对同一处理流程进行多次循环的方式。 DES 算法就是采用的 16 轮循环的加密,当然循环次数越多加密的效果越好,同 时时间成本也会上去,设计者需要考虑这两方面的因素进行密码设计。因为这个 框架是用于处理分组密码的,我们就要了解一下什么是分组密码,分组密码是一 种加解密方案,将输入的明文分组当作一个整体处理,并输出一个等长的密文分组,典型的分组大小为 64 位和 128 位,随着对加密算法安全性能的要求不断提高,分组大小也就会越来越大。DES 算法所采用的分组大小为 64 位分组,所以输入的数据和密钥都是按照 64 位进行处理的,输出的密文也是 64 位一组。

三、DES 加密算法过程

        DES 属于分组密码,明文和密文为 64 位分组。密钥的长度为 64 位,但是密钥的每个第八位设置为奇偶校验位,因此密钥的实际长度为 56 位。

1.初始置换:

        使用初始置换表对明文进行置换,这里的置换只是将数据的位置进行变化,得到一个新的数据。初始逆置换表和初始置换表是相互可逆的,就是将原来的数据的位置进行还原。

        置换处理:在密码学中置换是指在保持数据不变的情况下,打乱数据的位置顺序的操作称作置换,在 DES 算法中每个置换处理都会按照 相应的置换表进行操作,置换处理在 DES 算法中得到了充分的运用,通过置换处理可以打乱输入数据的顺序,使输入的数据变得面目全非,当然也会造成雪崩效应,因为只要有一个数据位发生变化,就会影响到很多地方。

表 3.0 初始置换表

58

50

42

34

26

18

10

02

60

52

44

36

28

20

12

04

62

54

46

38

30

22

14

06

64

56

48

40

32

24

16

08

57

49

41

33

25

17

09

01

59

51

43

35

27

19

11

03

61

53

45

37

29

21

13

05

63

55

47

39

31

23

15

07

2.子秘钥生成:

        DES 算法子密钥输入长度为 64 位,但是只有 48 位是有效的,所以需要对密钥 K 进行变换得到每一轮所需的子密钥。16 轮迭代就需要 16 个 48位的子密钥来进行加密。

        DES 算法子密钥生产比较简单,64 位密钥经过置换选择,只选择其中的 56位,对 56 位密钥同样分为左右 28 位,按照子密钥计算的逻辑表,每一轮进行循环左移运算分别得到新的 56 位,这 56 位再经过第二次置换选择就得到了本轮的子密钥。

图 3.1 子秘钥生成流程 

PC-1 置换:

        我们知道秘钥的长度是 64 (58 位真实秘钥 + 8 位奇偶校验位) , PC-1置换就是剔除掉奇偶校验位,并打乱用户秘钥的的过程。

表 3.2 PC-1 置换表

57

49

41

33

25

17

09

01

58

50

42

34

26

18

10

02

59

51

43

35

27

19

11

03

60

52

44

36

63

55

47

39

31

23

15

07

62

54

46

38

30

22

14

06

61

53

45

37

29

21

13

05

28

20

12

04

PC-2 置换:

PC-1 置换后生成了(CnDn)共 16 组 56 位的二进制字符,PC-2 置换就是根据公式 Kn(48 位) = PC-2(CnDn(56 位))再次进行置换,生成 16 组子秘钥。

表 3.2 PC-2 置换表

14

17

11

24

01

05

03

28

15

06

21

10

23

19

12

04

26

08

16

07

27

20

13

02

41

52

31

37

47

55

30

40

51

45

33

48

44

49

39

56

34

53

46

42

50

36

29

32

3.迭代:

         在 DES 算法中 F 函数蕴含了 DES 算法的主要操作,也是该算法中最重要的地方。F 函数就是不断计算 L,R 的过程,此过程包括四个部分:E 盒置换、S 盒置换、P 盒置换、左右校验。从 DES 算法的流程框架图中,我们可以清楚的看到 F 函数有两个输入,一个是右分组的 32 位数据,另一个是子密钥的 48 位数据,这两个长度不同的数据是怎样进行处理的呢?先来看看它的处理流程图吧:

F 函数处理流程:

        将输入的 32 位 R 组数据进行扩展置换,生成 48 位的数据。

        将置换后的 48 位结果与输入的 48 位子密钥进行异或运算,得到 48 位的运算结果。

        将 48 位运算结果分成 8 组,每组 6Bit 数据,按照组号对应相应的 S 盒,进行 8 个 S 盒置换,生成 8 个 4Bit 的数据。

        将这 8 个 4Bit 数据合并,得到一个 32 位数据。

        将 32 位进行置换 P 就得到最后的 32 位处理结果

 图 3.3 F 函数处理流程

E盒置换(扩充置换):

        通过扩展置换 E,数据的右半部分 Rn 从 32 位扩展到 48 位。扩展置换改变了位的次序,重复了某些位。

        扩展置换的目的:产生与秘钥相同长度的数据以进行异或运算,R0 是 32 位,子秘钥是 48 位,所以 R0 要先进行扩展置换之后与子秘钥进行异或运算提供更长的结果,使得在替代运算时能够进行压缩。

表 3.4 E 盒置换表

32

01

02

03

04

05

04

05

06

07

08

09

08

09

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

01

S 盒替代:

        S 盒替代简而言之就是“6 进 4 出”的。(传入 S 盒的是 6 位数据,从 S 盒输出的是 4 位数据),将 E 盒输出的 48 位替换压缩为 32 位。

        扩展置换之后与子秘钥异或以后的结果作为输入块进行 S 盒代替运算功能是把 48 位数据变为 32 位数据。代替运算由 8 个不同的代替盒(S 盒)完成。每个S 盒有 6 位输入,4 位输出。所以 48 位的输入块被分成 8 个 6 位的分组,每一个分组对应一个 S 盒代替操作。经过 S 盒代替,形成 8 个 4 位分组结果。

        注意:每一个 S 盒的输入数据是 6 位,输出数据是 4 位,但是每个 S 盒自身是 64 位!!每个 S 盒是 4 行 16 列的格式,因为二进制 4 位是 0~15。

S 盒的计算规则:

        例如:若 S 盒 1 的输入为 110111,第一位与最后一位构成 11,十进制值为 3,则对应第 3 行,中间 4 位为 1011 对应的十进制值为 11,则对应第 11 列。查找 S-盒 1 表的值为 14,则 S 盒 1 的输出为 1110。8 个 S 盒将输入的 48 位数据输出为 32 位数据。

图 3.5 S 盒替换示意图 

表 3.6 S 盒替换数据

S1

行\列

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

0

14

4

13

1

2

15

11

8

3

10

6

12

5

9

0

7

1

0

15

7

4

14

2

13

1

10

6

12

11

9

5

3

8

2

4

1

14

8

13

6

2

11

15

12

9

7

3

10

5

0

3

15

12

8

2

4

9

1

7

5

11

3

14

10

0

6

13

S2

行\列

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

0

15

1

8

14

6

11

3

4

9

7

2

13

12

0

5

10

1

3

13

4

7

15

2

8

14

12

0

1

10

6

9

11

5

2

0

14

7

11

10

4

13

1

5

8

12

6

9

3

2

15

3

13

8

10

1

3

15

4

2

11

6

7

12

0

5

14

9

S3

行\列

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

0

10

0

9

14

6

3

15

5

1

13

12

7

11

4

2

8

1

13

7

0

9

3

4

6

10

2

8

5

14

12

11

15

1

2

13

6

4

9

8

15

3

0

11

1

2

12

5

10

14

7

3

1

10

13

0

6

9

8

7

4

15

14

3

11

5

2

12

S4

行\列

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

0

7

13

14

3

0

6

9

10

1

2

8

5

11

12

4

15

1

13

8

11

5

6

15

0

3

4

7

2

12

1

10

14

9

2

10

6

9

0

12

11

7

13

15

1

3

14

5

2

8

4

3

3

15

0

6

10

1

13

8

9

4

5

11

12

7

2

14

S5

行\列

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

0

2

12

4

1

7

10

11

6

8

5

3

15

13

0

14

9

1

14

11

2

12

4

7

13

1

5

0

15

10

3

9

8

6

2

4

2

1

11

10

13

7

8

15

9

12

5

6

3

0

14

3

11

8

12

7

1

14

2

13

6

15

0

9

10

4

5

3

S6

行\列

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

0

12

1

10

15

9

2

6

8

0

13

3

4

14

7

5

11

1

10

15

4

2

7

12

9

5

6

1

13

14

0

11

3

8

2

9

14

15

5

2

8

12

3

7

0

4

10

1

13

11

6

3

4

3

2

12

9

5

15

10

11

14

1

7

6

0

8

13

S7

行\列

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

0

4

11

2

14

15

0

8

13

3

12

9

7

5

10

6

1

1

13

0

11

7

4

9

1

10

14

3

5

12

2

15

8

6

2

1

4

11

13

12

3

7

14

10

15

6

8

0

5

9

2

3

6

11

13

8

1

4

10

7

9

5

0

15

14

2

3

12

S8

行\列

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

0

13

2

8

4

6

15

11

1

10

9

3

14

5

0

12

7

1

1

15

13

8

10

3

7

4

12

5

6

11

0

14

9

2

2

7

11

4

1

9

12

14

2

0

6

10

13

15

3

5

8

3

2

1

14

7

4

10

8

13

15

12

9

0

3

5

6

11

P 盒置换 :

        P 盒置换是 32 位的输入移位转换成 32 位的输出。其具体过程同 IP 置换。

表 3.7 S 盒替换数据

16

07

20

21

29

12

28

17

01

15

23

26

05

18

31

10

02

08

24

14

32

27

03

09

19

13

30

06

22

11

04

25

4. 逆置换:

        将初始置换进行 16 次的迭代,即进行 16 层的加密变换,得到L16 和 R16,将此作为输入块,进行逆置换得到最终的密文输出块。逆置换是初始置换的逆运算。从初始置换规则中可以看到,原始数据的第 1 位置换到了第40 位,第 2 位置换到了第 8 位。则逆置换就是将第 40 位置换到第 1 位,第 8位置换到第 2 位。以此类推,逆置换规则表如下:

表 3.8 S 逆置换规则表

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

四、DES 加密总流程

加密:

        DES 算法是对固定大小(64 位)的数据块进行加密解密操作的;

        明文串 M 经过长度都为 48 位的 16 个子密钥 K 来加密,最后生成长度为 64 比特的密文 E;经过长度都为 48 位的 16 个子密钥 K 来加密,最后生成长度为 64 比特的密文 E;

  1. 进行 IP 初始置换,将该明文串 M(64bit)被分为 32 位的左半部分 L0 和 32位的右半部分 R0 两部分;
  2. 将数据的右半部分 R0 通过扩展置换 E 从 32 位扩展为 48 位;
  3. 扩展后的 48 位与 K1 进行异或;
  4. 异或后的结果通过 S 盒子转换为 32 位;
  5. 输出结果再通过一个 P 盒置换产生一个 32 位的输出;
  6. 最后,P 盒置换的结果与左半部分进行异或运算,然后将左右两部分交换,之后进入下一轮迭代。
  7. 在完成完全相同的 16 轮运算后,将得到的两部分数据 L16 和 R16 合在一起,即 L16R16;(L16:指进行了 16 轮处理得到的 32 位左半部分数据)
  8. 将 L16 与 R16 的位置交换,得到 R16L16,再经过一个末置换函数 IP-1,即可得到 64 位的密文。

子密钥生成:

  1. 密钥先被转化成 64 比特的二进制;
  2. 再按照密钥置换函数 PC-1(8x7)进行压缩置换,变成 56 位;
  3. 将其置换的输出再分为前 28 位 C0 和后 28 位 D0 两部分;
  4. 进行 16 轮数据处理,每一轮中,先将 C0 和 D0 分别 进行循环左移,再将两部分左移结果 一起执行压缩置换 PC-2(8X6),最后生成 16 个 48 位的子密钥。

 图 3.9 总流程图

五、代码

/*@ClassName:DES

        *@Description:DES算法 自己研发的算法与SHA1、RSA同级

        *@author:XHH


        *@date2021年12月4日晚上21:38

        *@version 1.0
        * 使用方法:
        明文
        static long DES_Input_Data = 0x0123456789ABCDEFL;
        密钥
        static long DES_Secret_Key = 0x0123456789ABCDEFL;
        public static void main(String[] args) {
            System.out.printf("原数据:0x%X\r\n", DES_Input_Data);
            System.out.printf("密  钥:0x%X\r\n", DES_Secret_Key);
            DES_Input_Data = DES_Algorithm(DES_Input_Data, DES_Secret_Key, ENCRYPTION); 加密
            System.out.printf("加密后:0x%X\r\n", DES_Input_Data);
            DES_Input_Data = DES_Algorithm(DES_Input_Data, DES_Secret_Key, DECODE);解密
            System.out.printf("解密后:0x%X\r\n", DES_Input_Data);
        }
        */
package mycode.SF;

public class DES {
    static final boolean ENCRYPTION = false;   //加密
    static final boolean  DECODE    = true;   //解密
    /*子密钥*/
    static long [] DES_Subkey = new long[16];
    static final int DES_IP_Substitution_Table[] = {
            58, 50, 42, 34, 26, 18, 10, 02,
            60, 52, 44, 36, 28, 20, 12, 04,
            62, 54, 46, 38, 30, 22, 14, 06,
            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,
    };
    /*PC1置换表*/
    static final int DES_PC1_Substitution_Table[] = {
            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
    };
    /*PC2置换表*/
    static final int DES_PC2_Substitution_Table[] = {
            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
    };
    /*扩展置换表*/
    static final int DES_Extend_Displacement[] = {
            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
    };
    /*循环位移数据*/
    static final int DES_Move_Data[] = {
            1, 1, 2, 2, 2, 2, 2, 2,
            1, 2, 2, 2, 2, 2, 2, 1
    };
    /*S盒*/
    static final int[][][] DES_SBox_Table = {
        {//S盒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盒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盒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盒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盒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盒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盒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盒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},
        }
    };
    /*P盒*/
    static final int DES_PBox_Table[] = {
            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,
    };
    /*逆置换*/
    static final int [] DES_Inverse_Permutation = {
            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,
    };
    /**
     * @brief	数据查找
     * @param   Input    需要查找的数据
    uint8_t Location  查找位
    uint8_t Size      数据位大小
     * @retval	查找位的数据
     * @note	数据:0x80 -> 查找位:1 -> 返回:1
     */
    private static int DES_Data_Search(long Input,int Location, int Size)
    {
        long Temp_Data= Input;//临时数据
        if ((((Temp_Data << (Location - 1)) & (1L << (Size - 1))) >>> (Size - 1)) !=0){
            return 1;
        }
        return 0;
    }
    /**
     * @brief	数据打印
     * @param   Input   需要打印的数据
     *			uint8_t Size     数据大小
     * @retval	None
     * @note	None
     */
    private static void DES_Data_Printf(long Input, int Size)
    {
        long Temp_Data = Input;//临时数据
        for (int i = 0; i < Size; i++)
        {
            if (((Temp_Data & (1L << (Size - 1))) >>> (Size - 1))!=0) {
                System.out.printf("1");
            }
            else {
                System.out.printf("0");
            }
            Temp_Data <<= 1;
        }
        System.out.printf("\r\n");
    }
    /**
     * @brief	循环左位移(28bit)
     * @param   In_Data   需要位移的数据
     *			uint32_t Move_Size 位移次数
     * @retval	uint32_t 位移完成数据
     * @note	None
     */
    private static int DES_Move_28(int In_Data, int Move_Size)
    {
        while (Move_Size!=0) {
            if ((In_Data & (1<<(28-1)))!=0) {
                In_Data <<= 1;
                In_Data |= 0x1;
            }
            else {
                In_Data <<= 1;
            }
            Move_Size--;
        }
        In_Data &= 0xFFFFFFF;
        return In_Data;
    }
    /**
     * @brief	数据置换
     * @param  Input			需要置换的数据
     *			uint8_t *Table			置换表
     *			uint8_t Size			置换表大小(小于64)
     *			uint8_t Original_Size   原始数据大小
     * @retval	None
     * @note	None
     */
    private static long DES_Replacement(long  Input, int [] Table,int Size, int Original_Size)
    {
        long Temp_Data = 0;
        for (int i = 0; i < Size; i++){
            Temp_Data <<= 1;
            if ((DES_Data_Search(Input, Table[i], Original_Size))==1) {
                Temp_Data |= 1;
            }
        }
        Input = Temp_Data;
        return Input;
    }
    /**
     * @brief	子密钥生成
     * @param   Key 密钥 uint64_t Subkey[16]子密钥
     * @retval	None
     * @note	None
     */
    private static void DES_Subkey_Generation(long Key, long [] Subkey)
    {
        int DES_C0;//前28位作为C0
        int DES_D0;//后28位作为D0

        /*数据PC1置换*/
        Key = DES_Replacement(Key,DES_PC1_Substitution_Table, 56,64);
        /*数据合并*/
        DES_C0 = ((int)(Key >>> 28)) & 0xFFFFFFF;
        DES_D0 = ((int)Key) & 0xFFFFFFF;
        /*16次循环*/
        for (int i = 0; i < 16; i++)
        {
            /*C0 循环位移*/
            DES_C0 = DES_Move_28(DES_C0, DES_Move_Data[i]);
            /*D0 循环位移*/
            DES_D0 = DES_Move_28(DES_D0, DES_Move_Data[i]);
            /*数据合并*/
            Subkey[i] = ((long)DES_C0 << 28) | DES_D0;
            /*数据PC2置换*/
            Subkey[i] = DES_Replacement(Subkey[i], DES_PC2_Substitution_Table, 48, 56);
        }
    }
    /**
     * @brief	S盒
     * @param  Input 输入数据
     * @retval	None
     * @note	None
     */
    private static long DES_SBox(long  Input)
    {
        int Columns =0;	//行
        int Rows = 0;	//列
        long S_Box = 0;	//S盒结果
        for (int i = 0; i < 8; i++){
            /*提取行*/
            Columns = DES_Data_Search(Input, 1+(i*6), 48);
            Columns <<= 1;
            Columns |= DES_Data_Search(Input, 6+(i * 6), 48);
            /*提取列*/
            Rows = DES_Data_Search(Input, 2+(i * 6), 48);
            Rows <<= 1;
            Rows |= DES_Data_Search(Input, 3+(i * 6), 48);
            Rows <<= 1;
            Rows |= DES_Data_Search(Input, 4+(i * 6), 48);
            Rows <<= 1;
            Rows |= DES_Data_Search(Input, 5+(i * 6), 48);
            S_Box <<= 4;
            /*索引到S盒里提取*/
            S_Box |= DES_SBox_Table[i][Columns][Rows];
        }
        return S_Box;//指针返回
    }
    /**
     * @brief	DES算法
     * @param   Input		明文
     * @param 	Key		密钥
     * @param	Mode		模式
     * @retval	None
     * @note	密文指向明文的指针做返回
     */
    public static long DES_Algorithm(long Input,long Key,boolean Mode)
    {
        long DES_L = 0;//拆分的左数据
        long DES_R = 0;//拆分的右数据
        long DES_T = 0;//临时数据
        /*数据IP置换*/
        Input = DES_Replacement(Input,DES_IP_Substitution_Table,64, 64);
        /*子密钥生成*/
        DES_Subkey_Generation(Key, DES_Subkey);
        /*数据拆分*/
        DES_L = (Input >>> 32) & 0xFFFFFFFF;
        DES_R = Input & 0xFFFFFFFF;
        /*16次循环*/
        for (int i = 0; i < 16; i++)
        {
            /*拆分*/
            DES_T = DES_R;//右数据暂存
            /*数据扩充置换*/
            DES_R = DES_Replacement(DES_R, DES_Extend_Displacement, 48, 32);
            /*异或A*/
            if (Mode) {
                DES_R ^= DES_Subkey[15-i];//解密
            }else{
                DES_R ^= DES_Subkey[i];//加密
            }
            /*S盒*/
            DES_R = DES_SBox(DES_R);
            /*P盒*/
            DES_R = DES_Replacement(DES_R,DES_PBox_Table, 32, 32);
            /*异或B*/
            DES_R ^= DES_L;
            /*左数据替换*/
            DES_L = DES_T;

        }
        Input =  DES_R << 32;
        Input |= DES_L;
        /*逆运算*/
        Input = DES_Replacement(Input,DES_Inverse_Permutation, 64, 64);
        return Input;
    }

}

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值