我想对字符串进行AES加密和解密。但是键和消息必须以字节为单位,所以我通过执行以下操作将消息转换为字节:
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进行解码:起始字节无效
我需要将这些字节转换回一个可读的字符串。如果你能帮上忙,我将不胜感激。
发布于 2018-05-23 15:59:55
您的代码的主要问题是没有向AES.new()提供现时值。OCB需要一个nonce;如果您不提供nonce,那么每次创建新的AES对象时都会创建一个随机nonce,因此解密将失败。
在docs中:
字节串(
nonce):不可重复的值,长度在1到15字节之间..如果不存在,将创建建议长度(15字节)的随机nonce。
您有两个选择,要么创建一个现时值并将其传递给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块。nonce和mac值不是秘密的,将它们存储在密文旁边是安全的。
最后,如果您计划从密码短语派生密钥,则应该使用基于密码的KDF。KDF创建强密钥,使用salt和迭代,并且它们非常能抵抗强制攻击。您可以在Crypto.Protocol.KDF中找到KDF函数。
发布于 2018-05-23 14:42:05
您不能将二进制数据转换为字符串,因为它本质上是而不是a string。这是二进制数据。您的加密的输出碰巧是一个格式正确的UTF8字符串的可能性很小。
您应该改为使用base64。它增加了数据(3个字节到4个字符),但更适合您的用例。
编辑:。我的错,我误解了你的问题。您的输出不正确,UTF8中的第一个字节不是“1”。这可能是加密/解密的问题。
发布于 2019-06-26 22:01:54
我想你的编码是"ISO-8859-1“。所以你可以这样做:
plaintext.decode("ISO-8859-1")https://stackoverflow.com/questions/50481366
复制相似问题