目录

使用Python自己实现Base64

不用 Python 的 base64 标准库,如何自己实现一个 Base64 编码函数?

什么是 Base64

Base64 是一种使用 64 个可打印字符来表示任意二进制数据的编码方法。常用在一些通常处理文本数据的场合,表示、传输、存储一些二进制数据,例如:

  • 在电子邮件中嵌入多媒体内容或者附件;
  • 在 HTML 中嵌入图片;

完整的 Base64 定义可见 RFC 1421 和 RFC 2045。需要注意的是,Base64 是一种编码方法,而不是加密方法。

Base64 使用的 64 个可打印字符为 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/,分别代表 0~63 的所有数值。

Base64 原理

由于 $2^6=64$,因此每 6 bits 数据可以用 1 个 Base64 的单元表示,即 3 Byte 的数据(24 bits)可以用 4 个 Base 64 的单元表示,即 3 个字节可以用 4 个可打印字符表示。可以看出,Base64 的代价是编码后数据长度增加了。

Base64 规定,编码时每 3 个字节为 1 组,编码为 4 个可打印字符。若要编码的二进制数据字节数不是 3 的整数倍,最后会剩下 1 个或 2 个字节,需要使用 \x00 补齐到 3 个字节,再进行 Base64 的编码。在编码后的Base64文本后加上一个或两个 = 号,代表补足的字节数。具体来说:

  • 当二进制数据剩下 1 个字节,需要补 2 个字节,我们用 x 表示原数据的 bit,这三个字节可以表示为 xxxxxxxx0000000000000000,Base64 编码时,拆分为 xxxxxxxx0000000000000000,可见前 2 个 Base64 字符含有原始数据,此时就把最后两个不含有原始数据的 Base64 字符替换为 =,即编码后的数据中会有 2 个 =,也代表了补足的字节数为 2。
  • 当二进制数据剩下 2 个字节,需要补 1 个字节,我们用 x 表示原数据的 bit,这三个字节可以表示为 xxxxxxxxxxxxxxxx00000000,Base64 编码时,拆分为 xxxxxxxxxxxxxxxx00000000,可见前 3 个 Base64 字符含有原始数据,此时就把最后一个不含有原始数据的 Base64 字符替换为 =,即编码后的数据中会有 1 个 =,也代表了补足的字节数为 1。

用 Python 实现 Base64 编码函数

 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
chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'

def base64_encode(binary_data: bytes):
    # 二进制数据字节数不是 3 的倍数时,使用 \x00 填充
    padding_count = 3 - len(binary_data) % 3
    if padding_count == 3:
        padding_count = 0
    encode_data = binary_data + b'\x00' * padding_count

    result = ''
    # 每次取出 3 个字节进行编码
    for index in range(0, len(encode_data), 3):
        piece = encode_data[index:index+3]
        # 将字节数据转换为二进制 bit 数据
        binary_string = bin(int.from_bytes(piece, 'big'))[2:].zfill(24)
        # 每次取出 6 个 bit
        for i in range(0, 24, 6):
            result += chars[int(binary_string[i:i+6], base=2)]

    # 若使用了 \x00 填充过编码前数据,使用等数量的 = 填充编码后数据
    if padding_count:
        result = result[:-padding_count] + '=' * padding_count

    # 输出的格式为 ascii 编码的 bytes
    return result.encode('ascii')

参考链接