使用OpenSSL进行DES加密

openssl库实现了大多数的加密算法,如AES,DES,RSA等等。

首先安装openssl库,命令如下:

sudo apt-get install libssl-dev

在代码中,引用对应的头文件

#include <openssl/des.h>

DES加密的主要函数如下:

[cpp] 
view plain
 copy

  1. typedef unsigned char DES_cblock[8];  
  2.   
  3. //生成一个随机的key,必须使用下面的set_key函数转换为schedule之后才能使用  
  4. void DES_random_key(DES_cblock *ret);  
  5.   
  6. //设置key  
  7. //这两个函数的主要区别在于是否检测key的奇偶校检位  
  8. //checked会对奇偶校检位进行检查,如果校检位错误,返回-1,如果key强度比较弱,返回-2;  
  9. //unchecked则不会检查  
  10. int DES_set_key_checked(const_DES_cblock *key, DES_key_schedule *schedule);  
  11. void DES_set_key_unchecked(const_DES_cblock *key, DES_key_schedule *schedule);  
  12.   
  13. //使用ECB模式进行加密  
  14. //每次仅能加密一个DES_cblock,即8个字节  
  15. //enc可以是DES_ENCRYPT或者DES_DECRYPT  
  16. void DES_ecb_encrypt(const_DES_cblock *input, DES_cblock *output, DES_key_schedule *ks, int enc);  
  17.   
  18. //使用CBC模式进行加密  
  19. //length指明文或者密文长度  
  20. //ivec是初始化向量IV  
  21. //如果length不是8的倍数,会使用00填充  
  22. void DES_ncbc_encrypt(const unsigned char *input, unsigned char *output, long length, DES_key_schedule, DES_cblock *ivec, int enc);  

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

CBC,密文分组链接方式,它的实现机制使加密的各段数据之间有了联系。其实现的机理如下:
1. 首先将数据按照8个字节一组进行分组得到D1D2……Dn(若数据不是8的整数倍,用指定的PADDING数据补位)
2. 第一组数据D1与初始化向量IV异或后的结果进行DES加密得到第一组密文C1(初始化向量I为全零)
3. 第二组数据D2与第一组的加密结果C1异或以后的结果进行DES加密,得到第二组密文C2
4. 之后的数据以此类推,得到Cn
5. 按顺序连为C1C2C3……Cn即为加密结果。

代码示例:

ECB模式

[cpp] 
view plain
 copy

  1. #include <stdio.h>  
  2. #include <openssl/des.h>  
  3.   
  4. int main(int argc,char **argv)  
  5. {  
  6.     DES_cblock key;  
  7.     //随机密钥  
  8.     DES_random_key(&key);  
  9.   
  10.     DES_key_schedule schedule;  
  11.     //转换成schedule  
  12.     DES_set_key_checked(&key, &schedule);   
  13.   
  14.     const_DES_cblock input = “hehehe”;  
  15.     DES_cblock output;  
  16.   
  17.     printf(“cleartext: %s\n”, input);  
  18.   
  19.     //加密  
  20.     DES_ecb_encrypt(&input, &output, &schedule, DES_ENCRYPT);  
  21.     printf(“Encrypted!\n”);  
  22.   
  23.     printf(“ciphertext: “);  
  24.     int i;  
  25.     for (i = 0; i < sizeof(input); i++)  
  26.          printf(“%02x”, output[i]);  
  27.     printf(“\n”);  
  28.   
  29.     //解密  
  30.     DES_ecb_encrypt(&output, &input, &schedule, DES_DECRYPT);  
  31.     printf(“Decrypted!\n”);  
  32.     printf(“cleartext:%s\n”, input);  
  33.   
  34.     return 0;  
  35. }   

CBC模式:

[cpp] 
view plain
 copy

  1. #include <openssl/des.h>  
  2. #include <stdio.h>  
  3. #include <string.h>  
  4.   
  5. int main(int argc, char** argv)  
  6. {  
  7.       unsigned char *keystring = “this is my key”;  
  8.       DES_cblock key;  
  9.       DES_key_schedule key_schedule;  
  10.   
  11.       //生成一个 key  
  12.       DES_string_to_key(keystring, &key);  
  13.       if (DES_set_key_checked(&key, &key_schedule) != 0) {  
  14.           printf(“convert to key_schedule failed.\n”);  
  15.           return -1;  
  16.       }  
  17.   
  18.       //需要加密的字符串  
  19.       unsigned char input[] = “this is a text being encrypted by openssl”;  
  20.       size_t len = (sizeof(input)+7)/8 * 8;    
  21.       unsigned char *output = malloc(len+1);  
  22.       //IV  
  23.       DES_cblock ivec;  
  24.   
  25.       //IV设置为0x0000000000000000  
  26.       memset((char*)&ivec, 0, sizeof(ivec));  
  27.        
  28.       //加密  
  29.       DES_ncbc_encrypt(input, output, sizeof(input), &key_schedule, &ivec, DES_ENCRYPT);  
  30.   
  31.       //输出加密以后的内容  
  32.       for (int i = 0; i < len; ++i)  
  33.          printf(“%02x”, output[i]);  
  34.       printf(“\n”);  
  35.   
  36.       memset((char*)&ivec, 0, sizeof(ivec));  
  37.   
  38.       //解密  
  39.       DES_ncbc_encrypt(output, input, len, &key_schedule, &ivec, 0);  
  40.         
  41.       printf(“%s\n”, input);  
  42.   
  43.       free(output);  
  44.       return EXIT_SUCCESS;  
  45. }  

注意编译的时候要加上crypto库,命令如下:

[plain] 
view plain
 copy

  1. gcc main.c -lcrypto  

使用DES_string_to_key()时,函数内部会对传入的string进行处理,设置奇偶校检位等,可能会造成同样的密钥,加密的结果与其他DES实现方式不同。解决这个问题,可以使用下面的代码:

[cpp] 
view plain
 copy

  1. DES_cblock key;  
  2. memcpy(key, “password”, 8);  
  3. DES_set_key_unchecked(&key, &schedule);  
点赞