前言
在上一篇文章中我们讲了如何使用 CMake
搭建 OpenSSL
环境,并打印了 OpenSSL
的版本。
今天要使用 OpenSSL
进行 Base64
编解码。
Base64
Base64
是一种基于64个可打印字符来表示二进制数据的编码方法。
它最初是为电子邮件系统设计的,因为早期的网络和邮件传输协议不能可靠地处理非文本数据(如图像、音频文件等)。
通过将这些二进制数据转换成ASCII字符串格式,可以确保它们在网络上传输时不会被破坏或修改。
Base64
由大写字母A-Z、小写字母a-z、数字0-9以及符号"+“和”/"。
64 = 2^6,所以用 6 位就能容纳,但是一个字节是 8 位,它们的最小公倍数是 24,所以每 3 个字节(3 * 8 = 4 * 6)可以分成一组,用 4 个字符可以表示。
如果不足 24 位则用 0 补齐。
使用
上面简单讲了一下 Base64
的原理和出现的原因,接下来看一下如何使用 OpenSSL
进行编解码。
如何搭建 OpenSSL
在CMake OpenSSL 环境搭建中已经讲过了,不会的可以前去查看
编码
我们直接看代码如何编写,先来导入一下头文件
1
2
3
4
5
|
#include <iostream>
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/buffer.h>
using namespace std;
|
要使用 Base64
编码,我们需要用到 OpenSSL
的 BIO
接口。
BIO(Basic Input Output)
接口是用于实现输入输出操作的一套抽象层。它提供了一种灵活的方法来处理各种类型的I/O,包括文件、套接字、内存缓冲区等,并且支持过滤器(filters),这些过滤器可以在数据传递给最终目的地之前对其进行处理。
BIO
使用的流程一般是:
- 创建
BIO
对象
比如: BIO_new
- 配置算法/过滤器
比如:加解密,Base64,摘要算法
- 执行 IO 操作
使用
BIO_read
和 BIO_write
来进行写入或读取数据。
- 清理创建的对象,释放内存
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
|
// 创建 BIO 对象
auto bio_mem = BIO_new(BIO_s_mem());
if (bio_mem == nullptr) {
return 0;
}
// 添加 Base64 过滤器
auto bio_b64 = BIO_new(BIO_f_base64());
if (bio_b64 == nullptr) {
BIO_free(bio_mem);
return 0;
}
// 把内存和 Base64 编码算法关联起来
BIO_push(bio_b64, bio_mem);
string data = "OpenSSL Base64 编码";
// 写入数据
int re = BIO_write(bio_b64, reinterpret_cast<unsigned char*>(data.data()), data.size());
if (re <= 0) {
BIO_free_all(bio_b64);
return 0;
}
// 刷新缓存,写入到 mem
BIO_flush(bio_b64);
BIO_set_flags(bio_b64, BIO_FLAGS_BASE64_NO_NL); // 不进行换行,不设置一些情况下会解码失败
string encoded_data;
BUF_MEM *encoded_mem = 0;
BIO_get_mem_ptr(bio_b64, &encoded_mem); // 读到 buffer 里
if (encoded_mem) {
encoded_data = string(encoded_mem->data, encoded_mem->length);
}
BIO_free_all(bio_b64);
cout << "Base64 编码: " << encoded_data << endl;
|
输入如下:
1
|
Base64 编码: T3BlblNTTCBCYXNlNjQg57yW56CB
|
解码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
string encoded_data = "T3BlblNTTCBCYXNlNjQg57yW56CB";
auto bio_mem_decode = BIO_new_mem_buf(encoded_data.data(), encoded_data.size());
if (bio_mem_decode == nullptr) {
return 0;
}
auto bio_b64_decode = BIO_new(BIO_f_base64());
if (bio_b64_decode == nullptr) {
BIO_free(bio_mem_decode);
return 0;
}
BIO_push(bio_b64_decode, bio_mem_decode);
BIO_set_flags(bio_b64_decode, BIO_FLAGS_BASE64_NO_NL); // 不进行换行,不设置一些情况下会解码失败
int capcity = 1024;
string decode_data(capcity, 0);
size_t size = 0;
BIO_read_ex(bio_b64_decode, decode_data.data(), capcity, &size);
BIO_free_all(bio_b64_decode);
decode_data.resize(size);
cout << "Base64 解码: " << decode_data << endl;
|
结果如下:
1
|
Base64 解码: OpenSSL Base64 编码
|
总结
Base64
编码还是比较简单的, OpenSSL
使用起来比其它语言标准库的要复杂一些。