如何使用自定义字母集进行 base64 编码?

How can I base64 encode using a custom letter set?

我正在尝试使用 python3 中的自定义字符集进行 base64 编码。我在 SO 中看到的大多数示例都与 Python 2 有关,因此我不得不对代码进行一些小的调整。我面临的问题是,我将字符 / 替换为 _,但它仍在打印 /。我的代码是:这只是一个例子,我不是想只使用 urlsafe 字符的 base64。 custom 可以是任何长度正确的东西。

import base64

data = 'some random? data'
print(base64.b64encode(data.encode()))

std_base64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
custom = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"

data = data.translate(str.maketrans(custom, std_base64chars)).encode()

print(base64.b64encode(data))

# Both prints
b'c29tZSByYW5kb20/IGRhdGE='
b'c29tZSByYW5kb20/IGRhdGE='

我怎样才能使翻译正常工作,以便将出现的 / 正确替换为 _

编辑

我应该说清楚,我不是想在这里像 urlsafe 那样只做一种类型的 base64 编码,而是任何可能的字符集。如果用户可以传递他们自己的字符集,这将是一个函数。我正在通过字符映射查找字符,而不是字符串切片。

编辑

由于围绕我的问题的清晰度存在一些混淆,我尝试添加更多详细信息。

我正在尝试编写一个函数,该函数可以从用户那里获取任意字符集,然后在 base64 编码之前单独映射它们。大多数答案都围绕着操作 altchars 或字符串切片和替换,但这并不能解决所有需求。

例如,itoa64 字符集是: ./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz= 或 unix crypt 格式为 ./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz。答案虽然正确,但并未解决这些情况。

如果您要切换的字符只有+\,您可以使用base64.urlsafe_b64encode分别替换为-_

>>> base64.urlsafe_b64encode(data.encode())
b'c29tZSByYW5kb20_IGRhdGE='

或者,您可以使用 base64.b64encode 的可选参数将这些字符替换为您自己选择的字符:

>>> base64.b64encode(data.encode(), '*&'.encode())
b'c29tZSByYW5kb20&IGRhdGE='

如果您需要使用全新的字母表,您可以这样做

import base64

data = 'some random? data'
print(base64.b64encode(data.encode()))

std_base64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
custom = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"


x = base64.b64encode(data.encode())
print(bytes(str(x)[2:-1].translate(str(x)[2:-1].maketrans(std_base64chars, custom)), 'utf-8'))

输出:

b'c29tZSByYW5kb20/IGRhdGE='
b'C29TzsbYyw5KB20_igrHDge='

这不应该工作:

import base64


data = 'some random? data'

custom = b"-_"

rslt = base64.b64encode(data)
print(rslt)

rslt = base64.b64encode(data, altchars=custom)
print(rslt)

我得到以下输出:

c29tZSByYW5kb20/IGRhdGE=
c29tZSByYW5kb20_IGRhdGE=

或者如果您坚持,该习俗包含:

custom = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"

然后使用:

rslt = base64.b64encode(data, altchars=custom[-2:])