OpenSSL编程-3DES编程详解

OpenSSL编程-3DES编程详解

一. 3DES加密原理

3DES(或称为Triple DES)是三重数据加密算法(TDEA,Triple Data Encryption Algorithm)块密码的通称。它相当于是对每个数据块应用三次DES加密算法。由于计算机运算能力的增强,原版DES密码的密钥长度变得容易被暴力破解;3DES即是设计用来提供一种相对简单的方法,即通过增加DES的密钥长度来避免类似的攻击,而不是设计一种全新的块密码算法。

3DES(即Triple DES)是DES向AES过渡的加密算法(1999年,NIST将3-DES指定为过渡的加密标准),加密算法,其具体实现如下:设Ek()和Dk()代表DES算法的加密和解密过程,K代表DES算法使用的密钥,P代表明文,C代表密文,这样:
3DES加密(EDE)过程为:C=Ek3(Dk2(Ek1(P)))
3DES解密(DED)过程为:P=Dk1(EK2(Dk3(C)))

二. 3DES API

1. 基本数据结构

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

typedef unsigned char DES_cblock[8];

typedef /* const */ unsigned char const_DES_cblock[8];

 

typedef struct DES_ks

{

    union

    {

        DES_cblock cblock;

        DES_LONG deslong[2];

    } ks[16];

} DES_key_schedule;

 

sizeof(DES_cblock) = 8字节

sizeof(const_DES_cblock ) = 8字节

sizeof(DES_key_schedule) = 128字节

2. 基本宏定义

1

2

#define DES_ENCRYPT 1

#define DES_DECRYPT 0

3. 设置密钥函数

1

2

3

4

5

6

7

8

9

10

11

//根据字符串生成key

void DES_string_to_key(const char *str, DES_cblock *key);

 

//设置密码表,并进行校验     

//will check that the key passed is of odd parity and is not a week or semi-weak key.

//If the parity is wrong, then -1 is returned. If the key is a weak key, then -2 is returned.

//If an error is returned, the key schedule is not generated

int DES_set_key_checked(const_DES_cblock *key, DES_key_schedule *schedule);

 

//设置密码表,不需要校验   

void DES_set_key_unchecked(const_DES_cblock *key, DES_key_schedule *schedule);

4. 3DES ECB模式加解密API

1

2

3

4

5

6

7

8

9

10

void DES_ecb3_encrypt(const_DES_cblock *input, DES_cblock *output,

      DES_key_schedule *ks1, DES_key_schedule *ks2, DES_key_schedule *ks3, int enc);

 

参数说明:

    input:输入数据, 8字节

    output:输出数据, 8字节

    ks1:密钥1

    ks2:密钥2

    ks3:密钥3

    enc:加密-DES_ENCRYPT, 解密-DES_DECRYPT

5. 3DES CBC模式加解密API

1

2

3

4

5

6

7

8

9

10

11

12

void DES_ede3_cbc_encrypt(const unsigned char *input,unsigned char *output, long length,

      DES_key_schedule *ks1, DES_key_schedule *ks2, DES_key_schedule *ks3, DES_cblock *ivec, int enc);

 

参数说明:

    input: 输入参数, 8字节倍数

    output: 输出参数, 8字节倍数

    length: input的长度, 通常为8字节倍数

    ks1: 密钥1

    ks2: 密钥2

    ks3: 密钥3

    ivec: 初始向量, 8字节, 默认为全0

    enc: 加密-DES_ENCRYPT, 解密-DES_DECRYPT

三. 3DES 示例

1. 3DES ECB模式示例

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <openssl/des.h>

#include <openssl/rand.h>

 

#include "hex.h"

 

/************************************************************************

 * 3DES-ECB加密方式

 * 8字节密钥,加密内容8位补齐,补齐方式为:PKCS7。

 *

 * file: test_des3_ecb.c

 * gcc -Wall -O2 -o test_des3_ecb test_des3_ecb.c hex.c -lcrypto

 *

 * author: tonglulin@gmail.com by www.qmailer.net

 ************************************************************************/

int main(int argc, char *argv[])

{

    int i = 0;

    int len = 0;

    int nlen = 0;

 

    char ch = '\0';

    char *key1 = "0000000000000000"/* 原始密钥, 十六进制字符串 */

    char *key2 = "0000000000000000"/* 原始密钥, 十六进制字符串 */

    char *key3 = "0000000000000000"/* 原始密钥, 十六进制字符串 */

    char *data = "12345678123456781234567812345678"/* 原始明文, 十六进制字符串 */

    unsigned char src[64] = {0};

    unsigned char out[64] = {0};

    unsigned char tmp[64] = {0};

 

    unsigned char *ptr  = NULL;

    unsigned char block[8] = {0};

    DES_key_schedule ks1, ks2, ks3;

 

    /* 设置密码表 */

    ptr = hex2bin(key1, strlen(key1), &nlen);

    memcpy(block, ptr, sizeof(block));

    free(ptr);

    DES_set_key_unchecked((C_Block *)block, &ks1);

 

    ptr = hex2bin(key2, strlen(key2), &nlen);

    memcpy(block, ptr, sizeof(block));

    free(ptr);

    DES_set_key_unchecked((C_Block *)block, &ks2);

 

    ptr = hex2bin(key3, strlen(key3), &nlen);

    memcpy(block, ptr, sizeof(block));

    free(ptr);

    DES_set_key_unchecked((C_Block *)block, &ks3);

 

    ptr = hex2bin(data, strlen(data), &nlen);

    memcpy(src, ptr, nlen);

    free(ptr);

 

    len = (nlen / 8 + (nlen % 8 ? 1: 0)) * 8;

 

    ch = 8 - nlen % 8;

    memset(src + nlen, ch, (8 - nlen % 8) % 8);

 

    printf("加密前数据: ");

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

        printf("%02X", *(src + i));

    }

    printf("\n");

 

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

        DES_ecb3_encrypt((C_Block *)(src + i), (C_Block *)(out + i), &ks1, &ks2, &ks3, DES_ENCRYPT);

    }

 

    printf("加密后数据: ");

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

        printf("%02X" , *(out + i));

    }

    printf("\n");

 

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

        DES_ecb3_encrypt((C_Block *)(out + i), (C_Block *)(tmp + i), &ks1, &ks2, &ks3, DES_DECRYPT);

    }

 

    printf("解密后数据: ");

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

        printf("%02X", *(tmp + i));

    }

    printf("\n");

 

    return 0;

}

2. 3DES CBC模式示例

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <openssl/des.h>

#include <openssl/rand.h>

 

#include "hex.h"

 

/************************************************************************

 * 3DES-ECB加密方式

 * 8字节密钥,加密内容8位补齐,补齐方式为:PKCS7。

 *

 * file: test_des3_ecb.c

 * gcc -Wall -O2 -o test_des3_cbc test_des3_cbc.c hex.c -lcrypto

 *

 * author: tonglulin@gmail.com by www.qmailer.net

 ************************************************************************/

int main(int argc, char *argv[])

{

    int i = 0;

    int len = 0;

    int nlen = 0;

 

    char ch = '\0';

    char *key1 = "0000000000000000"/* 原始密钥, 十六进制字符串 */

    char *key2 = "0000000000000000"/* 原始密钥, 十六进制字符串 */

    char *key3 = "0000000000000000"/* 原始密钥, 十六进制字符串 */

    char *data = "12345678123456781234567812345678"/* 原始明文, 十六进制字符串 */

    unsigned char src[64] = {0};

    unsigned char out[64] = {0};

    unsigned char tmp[64] = {0};

 

    unsigned char *ptr  = NULL;

    unsigned char block[8] = {0};

    DES_key_schedule ks1, ks2, ks3;

    DES_cblock ivec;

    DES_cblock ivsetup = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

 

    /* 设置密码表 */

    ptr = hex2bin(key1, strlen(key1), &nlen);

    memcpy(block, ptr, sizeof(block));

    free(ptr);

    DES_set_key_unchecked((C_Block *)block, &ks1);

 

    ptr = hex2bin(key2, strlen(key2), &nlen);

    memcpy(block, ptr, sizeof(block));

    free(ptr);

    DES_set_key_unchecked((C_Block *)block, &ks2);

 

    ptr = hex2bin(key3, strlen(key3), &nlen);

    memcpy(block, ptr, sizeof(block));

    free(ptr);

    DES_set_key_unchecked((C_Block *)block, &ks3);

 

    ptr = hex2bin(data, strlen(data), &nlen);

    memcpy(src, ptr, nlen);

    free(ptr);

 

    len = (nlen / 8 + (nlen % 8 ? 1: 0)) * 8;

 

    ch = 8 - nlen % 8;

    memset(src + nlen, ch, (8 - nlen % 8) % 8);

 

    printf("加密前数据: ");

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

        printf("%02X", *(src + i));

    }

    printf("\n");

 

    memcpy(ivec, ivsetup, sizeof(ivsetup));

    /* 按照8字节数据进行加密,length=8 */

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

        DES_ede3_cbc_encrypt(src + i, out + i, 8, &ks1, &ks2, &ks3, &ivec, DES_ENCRYPT);

    }

 

    printf("加密后数据: ");

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

        printf("%02X" , *(out + i));

    }

    printf("\n");

 

    memcpy(ivec, ivsetup, sizeof(ivsetup));

    /* 按照8字节数据进行解密,length=8 */

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

        DES_ede3_cbc_encrypt(out + i, tmp + i, 8, &ks1, &ks2, &ks3, &ivec, DES_DECRYPT);

    }

 

    printf("解密后数据: ");

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

        printf("%02X", *(tmp + i));

    }

    printf("\n");

 

    return 0;

}

3. 输出结果

1

2

3

4

5

6

7

8

9

# ECB模式

加密前数据: 12345678123456781234567812345678

加密后数据: 4A438AC15D8074B54A438AC15D8074B5

解密后数据: 12345678123456781234567812345678

 

# CBC模式

加密前数据: 12345678123456781234567812345678

加密后数据: 4A438AC15D8074B58244AE0E7477AF78

解密后数据: 12345678123456781234567812345678

由结果可见,ECB和CBC模式的第一个8字节加密结果一致,而CBC模式的第二个8字节起会不断变化,同时,如果k1=k2=k3,则加密结果和DES加密算法相同。

四. HEX转换函数

请参考前面的Blog:《OpenSSL编程-DES编程详解

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值