【问题标题】:How can I base64 encode using a custom letter set?如何使用自定义字母集进行 base64 编码?
【发布时间】:2019-11-18 14:53:21
【问题描述】:

我正在尝试使用 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='

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

编辑

我应该明确一点,我不是想在这里只做一种类型的 base64 编码,比如 urlsafe,而是任何可能的字符集。这将是一个功能,用户可以传递他们自己的字符集。我正在寻找一个字符一个字符的映射,而不是字符串切片。

编辑

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

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

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

【问题讨论】:

    标签: python python-3.x string encoding base64


    【解决方案1】:

    如果您要切换的字符只有+\,则可以使用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='
    

    【讨论】:

    • 我应该明确一点,我不是想在这里只做一种类型的 base64 编码,比如 urlsafe,而是任何可能的字符集。我更新了 OP
    • 感谢@CDJB 的更新。但是这种字符串切片并不能解决像 itoa64 这样在字符集开头有一些特殊字符的问题。我正在寻找更多按字符映射的字符
    • 我不清楚为什么这个解决方案不适合你。请问您能用特定的输入和预期的输出更新您的问题吗?
    • 请您也添加您的预期输出 - 我仍然不清楚为什么我的最后一个解决方案不适合您。使用 unix crypt 格式我得到b'QqxhNG/mMKtYPqoz64FVR42=' - 我应该得到什么?
    • 你是对的。该解决方案确实对我有用。我接受它作为答案。很抱歉给您带来麻烦。
    【解决方案2】:

    这不应该工作吗:

    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:])
    

    【讨论】:

    • 很遗憾,altchars 只接受长度为 2 的字符串。
    • 好的,我明白了。文档有点搞笑:可选的 altchars 必须是至少长度为 2 的字节类对象。然后它意味着,所有其他字符都被忽略了。我调整了我的答案
    • 我应该明确一点,我并不是想在这里只做一种类型的 base64 编码,比如 urlsafe,而是任何可能的字符集。
    • 是的,这很好,正如您的示例明确提到的那样可以使用 altchars 更改的字符。我建议在问题中更清楚地说明这一点。所以你真正想要的是做一个字符映射。将为此写另一个答案。
    • @gelonida,字符串切片不是这里的选项,因为这不会解决诸如以./开头的字符的 itoa64 格式之类的问题
    猜你喜欢
    • 2013-01-18
    • 1970-01-01
    • 2014-08-02
    • 1970-01-01
    • 1970-01-01
    • 2011-08-11
    • 1970-01-01
    • 2017-01-22
    • 2018-10-26
    相关资源
    最近更新 更多