python - Python 3中AES加密解密中的字节转字符串

标签 python python-3.x encryption type-conversion

我想对字符串进行 AES 加密和解密。但是 key 和消息必须以字节为单位,所以我通过这样做将消息转换为字节:

b"string"

这是我的 AES 代码:

# Encryption
encryption_suite = AES.new(b'1234567812345678', AES.MODE_OCB)
cipher_text = encryption_suite.encrypt(b"A really secret message. Not for prying eyes.")

# Decryption
decryption_suite = AES.new(b'1234567812345678', AES.MODE_OCB)
plaintext = decryption_suite.decrypt(cipher_text)

但是我需要将解密的纯文本转回字符串以便阅读。 目前明文看起来是这样的:

b'x\x85\x92\x9d\xe6\x0bJ\xfe\x9b(\x10G\x8e\x05\xc5\xf4\xcdA9\xc18\xb8_\xf9vbmK\x16\xf8\xa3\xb6'

我试过用

plaintext.decode(encoding='windows-1252')

plaintext.decode("utf-8").strip('\x00')

但我得到的只是这个:

UnicodeDecodeError: 'charmap' 编解码器无法解码位置 3 中的字节 0x9d:字符映射到

或者这个:

UnicodeDecodeError: 'utf-8' 编解码器无法解码位置 1 中的字节 0xb1:起始字节无效

我需要将这些字节转换回可读字符串。如果您能提供帮助,我们将不胜感激。

最佳答案

您的代码的主要问题是您没有为 AES.new() 提供随机数。 OCB 需要随机数;如果您不提供一个随机数,则每次您创建一个新的 AES 对象时都会创建一个随机数,因此解密将失败。

来自docs :

nonce (byte string): a non-repeatable value, of length between 1 and 15 bytes.. If not present, a random nonce of the recommended length (15 bytes) will be created.

您有两个选择,要么创建一个随机数并将其传递给 AES.new()(在加密和解密中),要么使用 AES 在加密和解密过程中创建的随机数加密。

接下来,OCB 是一种经过身份验证的加密算法,但您似乎没有检查 MAC。这很重要,因为 MAC 会验证密文的完整性。

AES 的加密和解密方法接受和返回字节。您可以使用 .decode() 将明文(如果是文本)转换为字符串。如果您想将密文转换为字符串,您必须先对其进行 base64 编码,以便将原始字节编码为 ASCII 字符(请记住在解密前解码)。 b64encode() 也返回字节,但可以轻松转换为字符串。

一个例子,

from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from base64 import b64encode

key = get_random_bytes(16) # A 16 byte key for AES-128
nonce = get_random_bytes(15)
message = "A really secret message. Not for prying eyes.".encode()

cipher = AES.new(key, AES.MODE_OCB, nonce=nonce)
ciphertext, mac = cipher.encrypt_and_digest(message)

cipher = AES.new(key, AES.MODE_OCB, nonce=nonce)
plaintext = cipher.decrypt_and_verify(ciphertext, mac)

print(b64encode(ciphertext).decode())
#CSwHy3ir3MZ7yvZ4CzHbgYOsKgzhMqjq6wEuutU7vJJTJ0c38ExWkAY1QkLO
print(plaintext.decode())
#A really secret message. Not for prying eyes.

请注意,如果 .decrypt_and_verify() 无法验证 MAC,则会引发 ValueError 异常,因此您可能需要使用 try-except block 。 noncemac 值不是 secret 的,将它们存储在密文旁边是安全的。

最后,如果您打算从密码短语中派生 key ,您应该使用基于密码的 KDF。 KDF 创建强键,使用 salt 和迭代,并且它们非常能抵抗 fruteforce 攻击。您将在 Crypto.Protocol.KDF 中找到 KDF 函数.

关于python - Python 3中AES加密解密中的字节转字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50481366/

相关文章:

Python 不按顺序打印消息

django - 名称错误 : name PositiveSmallIntegerField is not defined

python-3.x - 带有花式堆叠功能的 Pandas 数据透视表

c# - System.Security.Cryptography 与 Windows.Security.Cryptography

python - Pandas new Column 具有列表理解和引用现有列的 if 语句

python - Telegram bot 记录错误代码 409,即使有单个实例正在运行

python - PyQt5无法在Qlabel中居中对齐文本

python - 断言错误-Pyalgotrade

相当于 OpenSSL AES CBC 加密的 Java

c - 如何修复这个简单的加密程序中的段错误?