这里的背景故事有点冗长,但基本上我想采用像b'\x04\x0e\x1d'
这样的字符串并将其转换回字节数组。
我正在研究一次性填充的基本实现,我在其中使用明文A
和共享密钥B
来生成符合等式{{1}的密文C
}}。然后我用等式A⊕B=C
反转过程。
我已经发现了很多python3函数来将字符串编码为字节,然后xor字节,如下所示:
C⊕B=A
调用def xor_strings(xs, ys):
return "".join(chr(ord(x) ^ ord(y)) for x, y in zip(xs, ys)).encode()
然后返回一个bytearray:
xor_strings()
但是当我将它打印到屏幕上时,我显示的实际上是一个字符串。所以我假设python只是在bytearray上调用了一些print( xor_strings("foo", "bar"))
函数,我得到的内容如下所示:
str()
这就是问题所在。我想从该字符串创建一个新的bytearray。通常我会在bytearray上调用b'\x04\x0e\x1d'
。但是如果输入'b'\ x04 \ x0e \ x1d'作为输入,python会将其视为字符串,而不是字节数组!
如何将decode()
之类的字符串作为用户输入并将其强制转换为bytearray?
答案 0 :(得分:2)
如评论中所述,使用base64以文本形式发送二进制数据。
import base64
def xor_strings(xs, ys):
return "".join(chr(ord(x) ^ ord(y)) for x, y in zip(xs, ys)).encode()
# ciphertext is bytes
ciphertext = xor_strings("foo", "bar")
# >>> b'\x04\x0e\x1d'
# ciphertext_b64 is *still* bytes, but only "safe" ones (in the printable ASCII range)
ciphertext_b64 = base64.encodebytes(ciphertext)
# >>> b'BA4d\n'
现在我们可以传输字节:
# ...we could interpret them as ASCII and print them somewhere
safe_string = ciphertext_b64.decode('ascii')
# >>> BA4d
# ...or write them to a file (or a network socket)
with open('/tmp/output', 'wb') as f:
f.write(ciphertext_b64)
收件人可以通过以下方式检索原始邮件:
# ...reading bytes from a file (or a network socket)
with open('/tmp/output', 'rb') as f:
ciphertext_b64_2 = f.read()
# ...or by reading bytes from a string
ciphertext_b64_2 = safe_string.encode('ascii')
# >>> b'BA4d\n'
# and finally decoding them into the original nessage
ciphertext_2 = base64.decodestring(ciphertext_b64_2)
# >>> b'\x04\x0e\x1d'
当然,在将字节写入文件或网络时,首先将它们编码为base64是多余的。如果它是唯一的文件内容,您可以直接写/读密文。只有当密文成为更高结构(JSON,XML,配置文件...)的一部分时,才需要再次将其编码为base64。
使用单词" decode"和"编码"。
要编码字符串意味着将其从抽象含义("字符列表")转换为可存储的表示形式("列表字节&#34)。此操作的确切结果取决于正在使用的字节编码。例如:
要解码字节数组意味着将其从"字节列表"回到"一个字符列表"再次。这当然需要事先知道字节编码最初是什么。
ciphertext_b64
是一个字节列表,在Python控制台上表示为b'BA4d\n'
。
由于base64是ASCII的子集,因此当打印到控制台时,其等效字符串safe_string
看起来非常相似'BA4d\n'
。
数据类型然而仍然根本不同。不要让控制台输出欺骗你。
答案 1 :(得分:1)
仅回答最后一个问题。
>>> type(b'\x04\x0e\x1d')
<class 'bytes'>
>>> bytearray(b'\x04\x0e\x1d')
bytearray(b'\x04\x0e\x1d')
>>> type(bytearray(b'\x04\x0e\x1d'))
<class 'bytearray'>