base64 编码和解码
base64 背景
Base64 是一种用 64 个可打印字符(ASCII字符)来表示任意二进制数据的编码方式。
这 64 个字符包括:'A-Z'(大写)、'a-z'(小写)、'0-9'(数字),外加 '+' 和 '/',用作填充的 '='。
注意:这里的 '=' 不算64个字符里面。'=' 是一个辅助符号,它不在索引表中(索引表里没有它的位置,它不代表任何 6 bit 的数值)
它的本质不是加密,而是一种“翻译”规则,把原本乱码似的二进制(比如图片、压缩包)转成由这些常见字母数字组成的字符串。
早期互联网传输的核心是文件,例如:电子邮件协议最初也只设计用于传输的 ASCII字符 。ASCII 只使用一个字节的低7位(bit6 ~ bit0),这包括了字母、数字等等。如果出现了中文等非英文字符时,问题就出现了。这些数据包含大量 "不可见" 的控制字符(bit7 被使用,值 128~255)。
base64 编码
现代计算机中,“中”字采用 UTF-8 编码,其十六进制字节为:E4 B8 AD,对应的二进制是:11100100 10111000 10101101。
问题来了:这三个字节的最高位都是 1,它们不属于ASCII的可打印范围(0-127)。当老旧的邮件服务器看到这些字节时,会认为它们“非法”,直接粗暴地把最高位砍掉(置0),变成:01100100 (d) 、00111000 (8)、00101101 (-),接收方看到的就会是乱码 "d8-",原始信息彻底丢失。
Base64 把这些“高危”二进制位,重新翻译成绝对安全的字母和数字:
-
原始二进制(24 bit):
11100100 10111000 10101101 -
按6bit重新分组(拆成4组):
111001 → 十进制 57 → 查表得 5
001011 → 十进制 11 → 查表得 L
100010 → 十进制 34 → 查表得 i
101101 → 十进制 45 → 查表得 t
- 最终Base64编码结果:
5Lit
原本包含高位乱码风险的 E4 B8 AD,经过Base64转换,变成了完全由ASCII可见字符组成的 5Lit
base64 使用
- linux
#include <openssl/bio.h>
int base64_encode(const uint8_t *in, char *out, int length)
{
BIO *bmem = NULL;
BIO *b64 = NULL;
BUF_MEM *bptr;
int count = 0;
b64 = BIO_new(BIO_f_base64());
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
bmem = BIO_new(BIO_s_mem());
b64 = BIO_push(b64, bmem);
BIO_write(b64, in, length);
BIO_flush(b64);
BIO_get_mem_ptr(b64, &bptr);
BIO_set_close(b64, BIO_NOCLOSE);
count = bptr->length;
memcpy(out, bptr->data, bptr->length);
out[bptr->length] = 0;
BIO_free_all(b64);
return count;
}
- esp32
#include "mbedtls/base64.h"
static int base64_decode(char *in_str, int in_len, char *out_str, size_t out_str_size)
{
int size = 0;
int ret = 0;
size_t out_len = 0;
size_t src_len = in_len;
unsigned char *src = (unsigned char *)in_str;
if (in_str == NULL || out_str == NULL || in_len <= 0)
{
return -1;
}
ret = mbedtls_base64_decode((unsigned char *)out_str,
out_str_size,
&out_len,
(const unsigned char *)in_str, in_len);
if (0 != ret)
{
return -1;
}
out_str[out_len] = '\0';
size = (int)out_len;
return size;
}

浙公网安备 33010602011771号