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

二、加密模式

(1)ECB模式

     DES ECB(电子密本方式)其实非常简单,就是将数据按照8个字节一段进行DES加密或解密得到一段8个字节的密文或者明文,最后一段不足8个字节,按照需求补足8个字节进行计算,之后按照顺序将计算所得的数据连在一起即可,各段数据之间互不影响。

(2)CBC模式

      DES CBC(密文分组链接方式)有点麻烦,它的实现机制使加密的各段数据之间有了联系。其实现的机理如下:

  加密步骤如下:

1)首先将数据按照8个字节一组进行分组得到D1D2......Dn(若数据不是8的整数倍,用指定的PADDING数据补位)

2)第一组数据D1与初始化向量I异或后的结果进行DES加密得到第一组密文C1(初始化向量I为全零)

3)第二组数据D2与第一组的加密结果C1异或以后的结果进行DES加密,得到第二组密文C2

4)之后的数据以此类推,得到Cn

5)按顺序连为C1C2C3......Cn即为加密结果。

解密是加密的逆过程,步骤如下:

1)首先将数据按照8个字节一组进行分组得到C1C2C3......Cn

2)将第一组数据进行解密后与初始化向量I进行异或得到第一组明文D1(注意:一定是先解密再异或)

3)将第二组数据C2进行解密后与第一组密文数据进行异或得到第二组数据D2

4)之后依此类推,得到Dn

5)按顺序连为D1D2D3......Dn即为解密结果。

这里注意一点,解密的结果并不一定是我们原来的加密数据,可能还含有你补得位,一定要把补位去掉才是你的原来的数据。


三. 3DES API

1. 基本数据结构

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;
2. 基本宏定义

#define DES_ENCRYPT 1
#define DES_DECRYPT 0

3. 设置密钥的函数

//根据字符串生成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
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
 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. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <openssl/des.h>
  5. /************************************************************************
  6. ** 本例采用:
  7. ** 3des-ecb加密方式;
  8. ** 24位密钥,不足24位的右补0x00;
  9. ** 加密内容8位补齐,补齐方式为:少1位补一个0x01,少2位补两个0x02,...
  10. ** 本身已8位对齐的,后面补八个0x08。
  11. ************************************************************************/
  12. int main(void)
  13. {
  14.     int docontinue = 1;
  15.     char *data = "hello world!"; /* 明文 */
  16.     int data_len;
  17.     int data_rest;
  18.     unsigned char ch;
  19.     unsigned char *src = NULL; /* 补齐后的明文 */
  20.     unsigned char *dst = NULL; /* 解密后的明文 */
  21.     int len;
  22.     unsigned char tmp[8];
  23.     unsigned char in[8];
  24.     unsigned char out[8];
  25.     char *k = "01234567899876543210"; /* 原始密钥 */
  26.     int key_len;
  27.     #define LEN_OF_KEY 24
  28.     unsigned char key[LEN_OF_KEY]; /* 补齐后的密钥 */
  29.     unsigned char block_key[9];
  30.     DES_key_schedule ks,ks2,ks3;
  31.     /* 构造补齐后的密钥 */
  32.     key_len = strlen(k);
  33.     memcpy(key, k, key_len);
  34.     memset(key + key_len, 0x00, LEN_OF_KEY - key_len);
  35.     /* 分析补齐明文所需空间及补齐填充数据 */
  36.     data_len = strlen(data);
  37.     data_rest = data_len % 8;
  38.     len = data_len + (8 - data_rest);
  39.     ch = 8 - data_rest;
  40.     src = (unsigned char *)malloc(len);
  41.     dst = (unsigned char *)malloc(len);
  42.     if (NULL == src || NULL == dst)
  43.     {
  44.         docontinue = 0;
  45.     }
  46.     if (docontinue)
  47.     {
  48.         int count;
  49.         int i;
  50.         /* 构造补齐后的加密内容 */
  51.         memset(src, 0, len);
  52.         memcpy(src, data, data_len);
  53.         memset(src + data_len, ch, 8 - data_rest);
  54.         /* 密钥置换 */
  55.         memset(block_key, 0, sizeof(block_key));
  56.         memcpy(block_key, key + 0, 8);
  57.         DES_set_key_unchecked((const_DES_cblock*)block_key, &ks);
  58.         memcpy(block_key, key + 8, 8);
  59.         DES_set_key_unchecked((const_DES_cblock*)block_key, &ks2);
  60.         memcpy(block_key, key + 16, 8);
  61.         DES_set_key_unchecked((const_DES_cblock*)block_key, &ks3);
  62.         printf("before encrypt:\n");
  63.         for (i = 0; i < len; i++)
  64.         {
  65.             printf("0x%.2X ", *(src + i));
  66.         }
  67.         printf("\n");
  68.         /* 循环加密/解密,每8字节一次 */
  69.         count = len / 8;
  70.         for (i = 0; i < count; i++)
  71.         {
  72.             memset(tmp, 0, 8);
  73.             memset(in, 0, 8);
  74.             memset(out, 0, 8);
  75.             memcpy(tmp, src + 8 * i, 8);
  76.             /* 加密 */
  77.             DES_ecb3_encrypt((const_DES_cblock*)tmp, (DES_cblock*)in, &ks, &ks2, &ks3, DES_ENCRYPT);
  78.             /* 解密 */
  79.             DES_ecb3_encrypt((const_DES_cblock*)in, (DES_cblock*)out, &ks, &ks2, &ks3, DES_DECRYPT);
  80.             /* 将解密的内容拷贝到解密后的明文 */
  81.             memcpy(dst + 8 * i, out, 8);
  82.         }
  83.         printf("after decrypt :\n");
  84.         for (i = 0; i < len; i++)
  85.         {
  86.             printf("0x%.2X ", *(dst + i));
  87.         }
  88.         printf("\n");
  89.     }
  90.     if (NULL != src)
  91.     {
  92.         free(src);
  93.         src = NULL;
  94.     }
  95.     if (NULL != dst)
  96.     {
  97.         free(dst);
  98.         dst = NULL;
  99.     }
  100.     return 0;
  101. }











你可能感兴趣的:(openssl 3des 加解密)