这是 passlib base64 编码中的错误吗?

问题描述

我正在尝试使用 passlib 的 base64 编码对重新编码的字节串进行解码:

from passlib.utils import binary

engine = binary.Base64Engine(binary.HASH64_CHARS)
s2 = engine.encode_bytes(engine.decode_bytes(b"1111111111111111111111w"))

print(s2)

这会打印 b'1111111111111111111111A',这当然不是我所期望的。最后一个字符不同。

我的错误在哪里?这是一个错误吗?

解决方法

不,这不是错误。

在 Base64 的所有变体中,每个编码字符仅表示 6 位,根据编码的字节数,您可以在末尾得到 0、2 或 4 个无意义的位。
在这种情况下,编码字符串 1111111111111111111111w 的长度为 23 个字符,这意味着 23*6 = 138 位,可以解码为 17 个字节(136 位)+ 2 个无关紧要的位。

您在这里使用的编码不是 Base64 而是 Hash64

许多散列格式使用的Base64字符映射;排序与标准 base64 字符映射大不相同。

在人物图中
HASH64_CHARS = u("./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
我们在索引 12 (A) 上找到 001100,在索引 60 (w) 上找到 111100

现在的“诀窍”是,
binary.Base64Engine(binary.HASH64_CHARS) 有一个默认参数 big=False,表示默认以小端格式进行编码。

在您的示例中,这意味着 w001111,而 A001100。在解码期间,最后两位被切断,因为它们如上所述不需要。再次编码时,将A作为字符映射中第一个可以使用两次编码的字符0011加上两个无关紧要的位。