安装 OpenSSL

官网:https://www.openssl.org/
在 ubuntu 下,本身应该是已经装了 OpenSSL(也或许什么时候装别的东西时依赖安装的?),如果仅仅是使用 OpenSSL 进行平时的加解密,是够了终端输入命令是可以运行的:

1
2
~$ openssl
OpenSSL>

但如果要想使用 OpenSSL 自己写些什么东西,则需要安转 OpenSSL 库函数,当然安装起来也很简单:

1
$ sudo apt-get install libssl-dev

也可以选择下载源代码手动编译:https://github.com/openssl/openssl

这样保证你可以调用 OpenSSL 库中的函数。

现在,你就可以随手使用 OpenSSL 提供的各种加密方式了,什么 MD5,RC4,RSA 都不在话下了。

而且,现在我们的所有操作都可以有两种途径来实现,命令行 OR 代码。

作为实验,我们以 RSA 为例,简单使用一下 OpenSSL,先用命令行来生成密钥,再用代码来实现对一个字符串的加解密。

生成密钥

RSA 作为非对称加密算法,密钥分为 公钥 和 私钥,它们是成对儿的。公钥公布出去,别人想给你发加密消息时,公钥用来加密,加密内容发给你;私钥自己留着,当收到别人发你的加密消息时,就可以用自己的私钥用来解密。不得不说,公钥密码体制这个想法太秒了。

生成一对密钥

1
openssl genrsa -out key.pem 1024

提取公钥

两种格式?

  • 1.The PEM public key format uses the header and footer lines:
    1
    2
    -----BEGIN PUBLIC KEY-----
    -----END PUBLIC KEY-----

提取方法:

1
openssl rsa -in key.pem -pubout -out pubkey.pem

  • 2.The PEM RSAPublicKey format uses the header and footer lines:
    1
    2
    -----BEGIN RSA PUBLIC KEY-----
    -----END RSA PUBLIC KEY-----

提取方法:

1
openssl rsa -in key.pem -RSAPublicKey_out -out pubkey.pem

具体为什么有两种格式呢,可以参看这里:
https://tls.mbed.org/kb/cryptography/asn1-key-structures-in-der-and-pem

加解密

公私钥都准备好了,就可以来加解密了。
我们用代码的方式来实现对一个字符串的加密,具体函数可以参看
官方文档:
https://www.openssl.org/docs/manmaster/man3/

好,上代码:

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
#include <iostream>
#include <fstream>
#include "string.h"
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
//准备好的公私钥
#define PUBLIC_KEY "pubkey.key"
#define PRIVATE_KEY "prikey.pem"
using namespace std;
char* my_encrypt(char *str, char *path_key);
char* my_decrypt(char *str, char *path_key);
int main() {
// 声明一个字符数组,用来接受输入的字符串
char message[128];
cout << "input message: " << endl;
cin.getline(message, 128);
cout << "your message: " << message << endl;
char *ptr_en, *ptr_de;
// 加密
ptr_en = my_encrypt(message, PUBLIC_KEY);
cout << "============ encrypt: ============" << endl;
cout << ptr_en << endl;
// 解密
ptr_de = my_decrypt(ptr_en, PRIVATE_KEY);
cout << "============ decrypt: ============" << endl;
cout << ptr_de << endl;
return 0;
}
char * my_encrypt(char *str, char *path_key) {
char *p_en;
RSA *p_rsa;
FILE *file;
int flen, rsa_len;
if ((file = fopen(path_key, "r")) == NULL)
{
cout << "open public key file error." << endl;
return NULL;
}
// if ((p_rsa = PEM_read_RSA_PUBKEY(file, NULL, NULL, NULL)) == NULL)
if((p_rsa=PEM_read_RSAPublicKey(file,NULL,NULL,NULL))==NULL)
{
cout << "read public key error." << endl;
return "NULL";
}
flen = strlen(str);
rsa_len = RSA_size(p_rsa);
p_en = (char *) malloc (rsa_len + 1);
memset(p_en, 0, rsa_len + 1);
if (RSA_public_encrypt(rsa_len - 11, (unsigned char *) str, (unsigned char *) p_en, p_rsa, RSA_PKCS1_PADDING) <0)
{
cout << "encrypt error." << endl;
return NULL;
}
RSA_free(p_rsa);
fclose(file);
return p_en;
}
char *my_decrypt(char *str, char *path_key) {
char *p_de;
RSA *p_rsa;
FILE *file;
int rsa_len;
if ((file = fopen(path_key, "r")) == NULL)
{
cout << "open private key file error." << endl;
return NULL;
}
if ((p_rsa = PEM_read_RSAPrivateKey(file, NULL, NULL, NULL)) == NULL)
{
cout << "read private key error." << endl;
return NULL;
}
rsa_len = RSA_size(p_rsa);
p_de = (char *) malloc (rsa_len + 1);
memset(p_de, 0, rsa_len + 1);
if (RSA_private_decrypt(rsa_len, (unsigned char *) str, (unsigned char *) p_de, p_rsa, RSA_NO_PADDING) < 0)
{
cout << "decrypt error." << endl;
return NULL;
}
RSA_free(p_rsa);
fclose(file);
return p_de;
}