pyaes和Python 3中字节和str之间的关系?

时间:2016-10-06 15:03:36

标签: python encryption

我正在尝试在Python 3中使用pyaes(https://github.com/ricmoo/pyaes/blob/master/README.md)来使用pya来加密和解密文本。当我加密文本时,我给pya一个str值,即

plaintext = 'plain text'
key = os.urandom(16)
aes = pyaes.AESModeOfOperationCTR(key)
ciphertext = aes.encrypt(plaintext)

当我解密时,我得到了bytes类型:

aes = pyaes.AESModeOfOperationCTR(key)
decrypted_plaintext = aes.decrypt(ciphertext)

打印decrypted_plaintext会产生以下输出,该输出似乎包含原始文本:

b'plain text'

但它并不完全相同;一个是str,另一个是bytes

plaintext == decrypted_plaintext # False

我正在努力理解bytes与Python 3的str内部表示之间的关系。如何将bytes类型转换为str以获取我的纯文本?

我已经确认在pyaes自述文件页面上运行示例会遇到同样的问题。我猜这将与编码有关。

3 个答案:

答案 0 :(得分:1)

在Python 3 str中,type表示unicode格式的字符串。它由相对抽象的代码点组成,即数字编码字符。 有几种方法可以将这些代码点转换(编码)为实际字节,这些字节称为“编码”。 utf-8和utf-16是一些允许编码unicode字符的编码。

请注意,某些编码(如ASCII)允许对unicode字符进行编码。

在Python中编码str字符串时,您将获得类型为bytes的字节列表。然后,您可以解码此字节列表以获取str字符串。

要记住的一点是,您必须指定一个编码来编码str字符串,并且您必须知道bytes字符串的编码才能对其进行解码。如果您没有指定编码,Python将尝试使用其默认编码进行编码和解码,您可以获得“随机”结果。

在特定情况下,差异是不可见的,因为字符串的所有字符都是ASCII字符,幸运的是,unicode的128个第一个代码点与ASCII表匹配。

尝试在字符串中引入一些'exeotic'字符(如é,ç或Ë),你会看到差异。

现在,pyaes不会加密/解密unicode代码点,而是加密/解密字节。 因此,您必须对加密的字符串进行编码,并且必须知道使用的编码来解码解密的字符串。

Python doc中的更多信息:

答案 1 :(得分:0)

decrypted_plaintext.decode()会给你一个str,这很可能就是你想要的。 bytes对象是未指定编码的原始字节字符串。要将其转换为str,您必须告诉Python使用decode()对其进行解码。 decode()默认为UTF-8,但您可以告诉它使用哪种编码。

我只是看了source,我看不到特定于编码的内容,因此解密后的字符串的编码应该与加密字符串的编码匹配。

答案 2 :(得分:0)

对于所有其他人,这可以帮助您:如果 decrypted.decode('utf-8') ==明文:

    # A 256 bit (32 byte) key
key = b"This_key_for_demo_purposes_only!"

aes = pyaes.AESModeOfOperationCTR(key)
plaintext = "Text may be any length you wish, no padding is required"
ciphertext = aes.encrypt(plaintext)

# '''\xb6\x99\x10=\xa4\x96\x88\xd1\x89\x1co\xe6\x1d\xef;\x11\x03\xe3\xee
#    \xa9V?wY\xbfe\xcdO\xe3\xdf\x9dV\x19\xe5\x8dk\x9fh\xb87>\xdb\xa3\xd6
#    \x86\xf4\xbd\xb0\x97\xf1\t\x02\xe9 \xed'''
print (repr(ciphertext))

# The counter mode of operation maintains state, so decryption requires
# a new instance be created
aes = pyaes.AESModeOfOperationCTR(key)
decrypted = aes.decrypt(ciphertext)

print(type(decrypted))
print(type(plaintext))

# True
if decrypted.decode('utf-8') == plaintext:
    print(plaintext)
    print(True)
    print(decrypted.decode('utf-8'))


# '''WZ\x844\x02\xbfoY\x1f\x12\xa6\xce\x03\x82Ei)\xf6\x97mX\x86\xe3\x9d
#    _1\xdd\xbd\x87\xb5\xccEM_4\x01$\xa6\x81\x0b\xd5\x04\xd7Al\x07\xe5
#    \xb2\x0e\\\x0f\x00\x13,\x07'''
print (repr(ciphertext))