python - 自定义 Base64 编码器无法正确编码
问题描述
我决定制作自己的 Base64 编码器和解码器,尽管标准库中已经有一个模块。这只是一个有趣的项目。但是,由于某种原因,编码器对某些字符进行了错误的编码,而且我调试时运气不佳。我试图按照维基百科上的模型进行操作。我相信问题与底层转换为二进制格式有关,但我不确定。
代码:
def encode_base64(data):
raw_bits = ''.join('0' + bin(i)[2:] for i in data)
# First bit is usually (always??) 0 in ascii characters
split_by_six = [raw_bits[i: i + 6] for i in range(0, len(raw_bits), 6)]
if len(split_by_six[-1]) < 6: # Add extra zeroes if necessary
split_by_six[-1] = split_by_six[-1] + ((6 - len(split_by_six[-1])) * '0')
padding = 2 if len(split_by_six) % 2 == 0 else 1
if len(split_by_six) % 4 == 0: # See if padding is necessary
padding = 0
indexer = ([chr(i) for i in range(65, 91)] # Base64 Table
+ [chr(i) for i in range(97, 123)]
+ [chr(i) for i in range(48, 58)]
+ ['+', '/'])
return ''.join(indexer[int(i, base=2)] for i in split_by_six) + ('=' * padding)
当我运行以下示例代码时,我得到了不正确的值,您可以在下面看到:
print(base_64(b'any carnal pleasure'))
# OUTPUT: YW55QMbC5NzC2IHBsZWFzdXJl=
# What I should be outputting: YW55IGNhcm5hbCBwbGVhc3VyZS4=
出于某种奇怪的原因,前几个字符是正确的,而其余的则不是。我很乐意回答任何问题!
解决方案
Python 的bin()
函数不包含前导零,因此二进制表示的长度会有所不同:
>>> bin(1)
'0b1'
>>> bin(255)
'0b11111111'
>>> bin(ord("a"))
'0b1100001'
>>> bin(ord(" "))
'0b100000'
在您的输入中a
,n
、 和y
都在其二进制表示中具有一个前导零,因此 的长度bin(i)
是一致的。但是 的二进制表示' '
有两个前导零,因此bin(i)
比您预期的短一点,其余部分raw_bits
未对齐。
要解决此问题,请确保使用前导零填充二进制表示,直到它达到 8 个字符。我认为没有特别优雅的方法可以做到这一点,但您可以使用format(ord(i), "#010b")[2:]
确保完整表示为 10 个字符,然后丢弃0b
,留下您关心的 8 个字符。