一、基本用法
// 发送端对加密后的数据使用base64编码
Base64 base64;
QByteArray encryptData = base64.enCode(reinterpret_cast<char*>(out), outLen);
// 接收端先对数据进行base64解码
Base64 base64;
data = base64.deCode(data);
必要头文件
#include <openssl/bio.h>
#include <openssl/buffer.h>
#include <openssl/evp.h>
二、Base64编码
2.1、BIO_new
创建 BIO
对象
BIO *BIO_new(const BIO_METHOD *method);
参数解释:
method :
BIO_METHOD
结构体指针,表示要使用的 BIO 方法,要获取一个BIO_METHOD*
指针,你可以使用 OpenSSL 库中一组已经定义好的BIO_METHOD
对象。这些BIO_METHOD
对象通常以BIO_s_
开头,表示特定类型的BIO
操作方法以下是几个常用的
BIO_METHOD
对象及其对应的函数:BIO_f_base64()
:用于base64编码BIO_s_file()
:用于文件 I/O 操作。BIO_s_mem()
:用于内存缓冲区的读写操作。BIO_s_socket()
:用于套接字 I/O 操作。
返回值:返回一个BIO对象指针
// 创建bio对象
BIO* base64 = BIO_new(BIO_f_base64());
BIO* mem = BIO_new(BIO_s_mem());
2.2、BIO_push
用于将两个 BIO
对象连接起来的函数,该函数将 next
对象串联在 bio
对象之后,形成一个 BIO
对象链。
BIO *BIO_push(BIO *bio, BIO *next);
参数解释:
- bio:当前使用的
BIO
对象 - next:要连接的下一个
BIO
对象
需要注意的是,当连接多个BIO
对象时,应将它们以正确的顺序连接起来,确保数据可以按照正确的顺序流经整个BIO
对象链。例如,如果需要在内存缓冲区和文件之间进行数据传输,应该先将内存缓冲区BIO
对象链接到文件BIO
对象之后,这样在写入数据时,数据会先写入内存缓冲区,然后再写入文件。
// 组织bio链
BIO_push(base64, mem);
2.3、BIO_write
用于在 BIO
对象中写入数据的函数
int BIO_write(BIO *bio, const void *buf, int len);
参数解释:
- 要写入数据的
BIO
对象指针bio
- 要写入的数据缓冲区指针
buf
- 要写入的数据长度
len
。
返回值:函数返回一个整数,表示实际写入的数据长度。
// 数据编码
BIO_write(base64, data, length);
BIO_flush(base64);
2.4、BIO_flush
将缓冲区中的数据写入磁盘
int BIO_flush(BIO *bio);
参数解释:
bio
:指向要刷新的BIO
对象的指针。
返回值:
- 成功:返回 1。
- 失败:返回 0。
2.5、BIO_get_mem_ptr
用于获取内存 BIO
对象中的数据指针和数据长度的函数。该函数会返回一个 BIO_MEM_PTR
结构体,包含了指向数据的指针和数据的长度。需要注意的是,获取到的数据指针 ptr
指向的数据是内存 BIO 对象中的数据,因此在使用数据时需要保证内存 BIO 对象的有效性,避免发生悬空指针的问题。
int BIO_get_mem_ptr(BIO *bio, BUF_MEM **pp);
参数解释:
- bio:之前写入数据的BIO对象
- pp:BUF_MEM对象,BIO_get_mem_ptr函数会将编码后的数据和数据的长度写入到pp
返回值:
- 1:成功
- 0:失败
// 把编码后的数据读出来
BUF_MEM* ptr;
BIO_get_mem_ptr(base64, &ptr);
QByteArray str(ptr->data, ptr->length);
2.6、BIO_free_all
用于释放 BIO
对象以及其关联资源的函数。该函数会递归地释放与 BIO
对象相关联的所有资源,包括底层的文件描述符、内存缓冲区等。
void BIO_free_all(BIO *bio);
参数解释:
- bio:前面创建的base64编码的BIO对象
BIO_free_all(base64);
完整示例:
QByteArray Base64::enCode(const char* data, int length)
{
// 创建bio对象
BIO* base64 = BIO_new(BIO_f_base64());
BIO* mem = BIO_new(BIO_s_mem());
// 组织bio链
BIO_push(base64, mem);
// 数据编码
BIO_write(base64, data, length);
BIO_flush(base64);
// 把编码后的数据读出来
BUF_MEM* ptr;
BIO_get_mem_ptr(base64, &ptr);
QByteArray str(ptr->data, ptr->length);
BIO_free_all(base64);
return str;
}
三、Base64解码
3.1、BIO_new
创建 BIO
对象
BIO *BIO_new(const BIO_METHOD *method);
参数解释:
method :
BIO_METHOD
结构体指针,表示要使用的 BIO 方法,要获取一个BIO_METHOD*
指针,你可以使用 OpenSSL 库中一组已经定义好的BIO_METHOD
对象。这些BIO_METHOD
对象通常以BIO_s_
开头,表示特定类型的BIO
操作方法以下是几个常用的
BIO_METHOD
对象及其对应的函数:BIO_f_base64()
:用于base64编码BIO_s_file()
:用于文件 I/O 操作。BIO_s_mem()
:用于内存缓冲区的读写操作。BIO_s_socket()
:用于套接字 I/O 操作。
返回值:返回一个BIO对象指针
// 创建bio对象
BIO* base64 = BIO_new(BIO_f_base64());
BIO* mem = BIO_new(BIO_s_mem());
3.2、BIO_push
用于将两个 BIO
对象连接起来的函数,该函数将 next
对象串联在 bio
对象之后,形成一个 BIO
对象链。
BIO *BIO_push(BIO *bio, BIO *next);
参数解释:
- bio:当前使用的
BIO
对象 - next:要连接的下一个
BIO
对象
需要注意的是,当连接多个BIO
对象时,应将它们以正确的顺序连接起来,确保数据可以按照正确的顺序流经整个BIO
对象链。例如,如果需要在内存缓冲区和文件之间进行数据传输,应该先将内存缓冲区BIO
对象链接到文件BIO
对象之后,这样在写入数据时,数据会先写入内存缓冲区,然后再写入文件。
// 组织bio链
BIO_push(base64, mem);
3.3、BIO_write
用于在 BIO
对象中写入数据的函数
int BIO_write(BIO *bio, const void *buf, int len);
参数解释:
- 要写入数据的
BIO
对象指针bio
- 要写入的数据缓冲区指针
buf
- 要写入的数据长度
len
。
返回值:函数返回一个整数,表示实际写入的数据长度。
// 将待解码的数据写入mem节点
BIO_write(mem, data, length);
2.5、BIO_read
用于从 BIO
对象中读取数据的函数
int BIO_read(BIO *bio, void *buf, int len);
参数解释:
- 要读取数据的
BIO
对象指针bio
- 用于存储读取数据的缓冲区指针
buf
- 要读取的最大数据长度
len
返回值:实际读取的数据长度,需要注意的是,BIO_read
函数可能会返回 0,表示已经没有更多数据可供读取。此外,如果返回的读取数据长度小于预期的长度 len
,应当根据实际需求进行处理。
// 解码,数据存入buf
char* buf = new char[length];
int result = BIO_read(base64, buf, length);
QByteArray out(buf, result);
2.6、BIO_free_all
用于释放 BIO
对象以及其关联资源的函数。该函数会递归地释放与 BIO
对象相关联的所有资源,包括底层的文件描述符、内存缓冲区等。
void BIO_free_all(BIO *bio);
参数解释:
- bio:前面创建的base64编码的BIO对象
BIO_free_all(base64);
完整示例:
QByteArray Base64::deCode(const char* data, int length)
{
// 创建bio对象
BIO* base64 = BIO_new(BIO_f_base64());
BIO* mem = BIO_new(BIO_s_mem());
// 组织bio链
BIO_push(base64, mem);
// 将待解码的数据写入mem节点
BIO_write(mem, data, length);
// 解码,数据存入buf
char* buf = new char[length];
int result = BIO_read(base64, buf, length);
QByteArray out(buf, result);
BIO_free_all(base64);
delete[] buf;
return out;
}