使用Openssl的AES加密算法

使用Openssl的AES加密算法

http://blog.gpjtag.com/?p=18

在网络应用的信息安全是基于密码学的,所以如果想做安全方面的邻域需要有一定的密码学基础。当然最好的学习方法就是边看书边尝试。

我的学习过程有三个阶段:

  1. 看书、通过使用一些软件了解基本的流程。
  2. 深入算法,自己实现部分加密算法。
  3. 了解常用的库的用法。

有人说“不要重复造轮子,有现成的要拿来用。”我赞同,但是这个的前提是你造过轮子,知道装配轮子的时候会有什么注意事项:)

所以在学习的过程中一定要“自己造轮子”,在工作的时候一定要“找轮子,用现成的”:)

Openssl是很常见的C接口的库,个人觉得易用。以下是AES加密的使用备忘。如果你有一定的密码学基础,那么就很好理解。代码是从网上弄下来的(原始地址已经忘记了),然后在尝试的过程中改了一点东西。其它的cbc、cfb、ecb加密方式的用法都是类似的,只是函数名有点区别,就不一一列举了。

一、接口简介

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//设置加密密钥,使用字符缓冲区
int AES_set_encrypt_key(
         const unsigned char *userKey,
         const int bits,
         AES_KEY *key);
 
//设置解密密钥,同样适用字符缓冲区
int AES_set_decrypt_key(
         const unsigned char *userKey,
         const int bits,
         AES_KEY *key);
 
//加解密的接口,通过最后的enc来区分是加密还是解密操作
//每次执行AES_cbc_encrypt后,iv(向量)会被更新,
//所以需要自己保存它。
void AES_cbc_encrypt(
         const unsigned char *in,
         unsigned char *out,
         const unsigned long length,
         const AES_KEY *key,
         unsigned char *ivec,
         const int enc);

二、一个简单的Makefile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
CFLAGS = /nologo /I .. /c /Fo./objs/
LFLAGS = /nologo
LLIBS  = ../lib/ssleay32MD.lib ../lib/libeay32MD.lib
all:./release/testaes.exe
 
./release/testaes.exe:./objs/testaes.obj
         link $(LFLAGS) ./objs/testaes.obj $(LLIBS) \
                 /out:./release/testaes.exe
 
{.}.cpp{./objs}.obj:
         cl $(CFLAGS) $<
 
clean:
         rm -rf *.obj

三、示例代码

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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include <stdio.h>
#include <string.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
 
/* file testaes.cpp */
 
static void hexdump(
                 FILE *f,
                 const char *title,
                 const unsigned char *s,
                 int l)
{
     int n = 0;
 
     fprintf (f, "%s" , title);
     for (; n < l; ++n) {
         if ((n % 16) == 0) {
                 fprintf (f, "\n%04x" , n);
         }
         fprintf (f, " %02x" , s[n]);
     }
 
     fprintf (f, "\n" );
}
 
int main( int argc, char **argv)
{
         //256bits key.
         unsigned char   rkey[16];
         //Internal key.
         AES_KEY         key;
 
         //Testdata.
         unsigned char   plaintext[AES_BLOCK_SIZE * 4];
         unsigned char   ciphertext[AES_BLOCK_SIZE * 4];
         unsigned char   checktext[AES_BLOCK_SIZE * 4];
 
         //Init vector.
         unsigned char   iv[AES_BLOCK_SIZE * 4];
         //Save vector.
         unsigned char   saved_iv[AES_BLOCK_SIZE * 4];
 
         int nr_of_bits = 0;
         int nr_of_bytes = 0;
 
         //Zeror buffer.
         memset (plaintext, 0, sizeof plaintext);
         memset (ciphertext, 0, sizeof ciphertext);
         memset (checktext, 0, sizeof checktext);
 
         //Generate random
         RAND_pseudo_bytes(rkey, sizeof rkey);
         RAND_pseudo_bytes(plaintext, sizeof plaintext);
         RAND_pseudo_bytes(saved_iv, sizeof saved_iv);
 
         hexdump(stdout, "== rkey ==" ,
                         rkey,
                         sizeof (rkey));
         hexdump(stdout, "== iv ==" ,
                         saved_iv,
                         sizeof (saved_iv));
         printf ( "\n" );
 
         hexdump(stdout, "== plaintext ==" ,
                         plaintext,
                         sizeof (plaintext));
         printf ( "\n" );
 
         //Entrypt
         memcpy (iv, saved_iv, sizeof (iv));
         nr_of_bits = 8 * sizeof (rkey);
         AES_set_encrypt_key(rkey, nr_of_bits, &key);
         nr_of_bytes = sizeof (plaintext);
         AES_cbc_encrypt(plaintext,
                         ciphertext,
                         nr_of_bytes,
                         &key,
                         iv,
                         AES_ENCRYPT);
 
         hexdump(stdout, "== ciphertext ==" ,
                         ciphertext,
                         sizeof (ciphertext));
         printf ( "\n" );
 
         //Decrypt
         memcpy (iv, saved_iv, sizeof (iv));
         nr_of_bytes = 8 * sizeof (rkey);
         AES_set_decrypt_key(rkey, nr_of_bits, &key);
         nr_of_bytes = sizeof (ciphertext) / 2;
         //Decrypt in two step:)
         AES_cbc_encrypt(ciphertext,
                         checktext,
                         nr_of_bytes,
                         &key, iv,
                         AES_DECRYPT);
         AES_cbc_encrypt(
                         ciphertext + nr_of_bytes,
                         checktext + nr_of_bytes,
                         nr_of_bytes,
                         &key,
                         iv,
                         AES_DECRYPT);
         hexdump(stdout, "== checktext ==" ,
                         checktext,
                         sizeof (checktext));
         printf ( "\n" );
 
         return 0;
}