Python上的AES256:多重传递错误?
我在Python中使用AES256加密进行多次加密时遇到问题 以下是我迄今为止一直在使用的函数: 加密:Python上的AES256:多重传递错误?,python,encryption,encoding,utf-8,aes,Python,Encryption,Encoding,Utf 8,Aes,我在Python中使用AES256加密进行多次加密时遇到问题 以下是我迄今为止一直在使用的函数: 加密: def AESEncrypt(plaintext, password, passes = 1): try: salt = Random.get_random_bytes(32) iv = Random.get_random_bytes(16) hmacsha256 = get_prf("hmac-sha256") ke
def AESEncrypt(plaintext, password, passes = 1):
try:
salt = Random.get_random_bytes(32)
iv = Random.get_random_bytes(16)
hmacsha256 = get_prf("hmac-sha256")
key = KDF.PBKDF2(password, salt, 32, 4096, hmacsha256[0])
aesManaged = AES.new(key, AES.MODE_CBC,iv)
padlength = 0
padByte = chr(0)
if len(plaintext) < 16:
padlength = 16 - len(plaintext)
padByte = chr(padlength)
else:
padlength = 16 - (len(plaintext) % 16)
padByte = chr(padlength)
for i in range(padlength):
plaintext = plaintext + b"\x00"
countByte = chr(passes)
if passes == 1:
ciphertext = countByte + padByte + iv + salt + aesManaged.encrypt(plaintext)
elif passes >= 2:
ciphertext = aesManaged.encrypt(plaintext)
for i in range(passes - 1):
ciphertext = aesManaged.encrypt(ciphertext)
ciphertext = countByte + padByte + iv + salt + ciphertext
return ciphertext
except:
print str(sys.exc_info()[1])
return None
def AESDecrypt(ciphertext, password):
try:
base_cipher = ciphertext
passes = ord(base_cipher[0])
padLength = ord(base_cipher[1])
iv = base_cipher[2:18]
salt = base_cipher[18:50]
hmacsha256 = get_prf("hmac-sha256")
key = KDF.PBKDF2(password, salt, 32, 4096, hmacsha256[0])
aesManaged = AES.new(key, AES.MODE_CBC,iv)
msg_cipher = base_cipher[50:]
if passes == 1:
plaintext_bytes = aesManaged.decrypt(msg_cipher)
elif passes >= 2:
plaintext_bytes = aesManaged.decrypt(msg_cipher)
for i in range(passes - 1):
plaintext_bytes = aesManaged.decrypt(plaintext_bytes)
if padLength > 0:
ptLength = len(plaintext_bytes)
plaintext_bytes = plaintext_bytes[:ptLength - padLength]
return plaintext_bytes
except:
print str(sys.exc_info()[1])
return None
就写二进制数据而言,它可以很好地使用单通道和多通道加密。当涉及到加密文本数据(如文本文件或消息)时,当我在解密时使用传递的值大于1时,它就开始出错
例如,如果我在上述过程或UTF-16中仅使用纯文本,如“Hello World!”
,则多通道加密将为我提供一堆损坏的文本(最多使消息的一半乱码),其余消息将正确解密
当我使用UTF-8编码,如“Hello World.encode('UTF-8')
时,同样使用相同的过程,我会得到一个错误,即(尽管每次运行时字节数和位置都会发生变化):
“utf8”编解码器无法解码位置0中的字节0xf7:无效的开始字节
是不是我做错了什么
更新:
def AESEncrypt(plaintext, password, passes = 1):
try:
salt = Random.get_random_bytes(32)
iv = Random.get_random_bytes(16)
hmacsha256 = get_prf("hmac-sha256")
key = KDF.PBKDF2(password, salt, 32, 4096, hmacsha256[0])
aesManaged = AES.new(key, AES.MODE_CBC,iv)
padlength = 0
padByte = chr(0)
if len(plaintext) < 16:
padlength = 16 - len(plaintext)
padByte = chr(padlength)
else:
padlength = 16 - (len(plaintext) % 16)
padByte = chr(padlength)
for i in range(padlength):
plaintext = plaintext + b"\x00"
countByte = chr(passes)
if passes == 1:
ciphertext = countByte + padByte + iv + salt + aesManaged.encrypt(plaintext)
elif passes >= 2:
ciphertext = aesManaged.encrypt(plaintext)
for i in range(passes - 1):
ciphertext = aesManaged.encrypt(ciphertext)
ciphertext = countByte + padByte + iv + salt + ciphertext
return ciphertext
except:
print str(sys.exc_info()[1])
return None
def AESDecrypt(ciphertext, password):
try:
base_cipher = ciphertext
passes = ord(base_cipher[0])
padLength = ord(base_cipher[1])
iv = base_cipher[2:18]
salt = base_cipher[18:50]
hmacsha256 = get_prf("hmac-sha256")
key = KDF.PBKDF2(password, salt, 32, 4096, hmacsha256[0])
aesManaged = AES.new(key, AES.MODE_CBC,iv)
msg_cipher = base_cipher[50:]
if passes == 1:
plaintext_bytes = aesManaged.decrypt(msg_cipher)
elif passes >= 2:
plaintext_bytes = aesManaged.decrypt(msg_cipher)
for i in range(passes - 1):
plaintext_bytes = aesManaged.decrypt(plaintext_bytes)
if padLength > 0:
ptLength = len(plaintext_bytes)
plaintext_bytes = plaintext_bytes[:ptLength - padLength]
return plaintext_bytes
except:
print str(sys.exc_info()[1])
return None
在查看了Python文档中的字节
和字节数组
类型后,我尝试转换应被视为字节数组的部分:
(我计划在获得正确的加密后进行解密和类型检测部分)
def AESENSCRYPT(明文、密码、密码=1):
尝试:
纯文本=字节数组(纯文本)
salt=字节(随机。获取随机字节(32))
iv=字节(随机。获取随机字节(16))
hmacsha256=获取prf(“hmac-sha256”)
key=KDF.PBKDF2(密码,salt,324096,hmacsha256[0])
AES管理=AES.新建(键,AES.模式\u CBC,iv)
焊盘长度=0
padByte=chr(0)
如果len(纯文本)<16:
焊盘长度=16-长度(纯文本)
padByte=chr(焊盘长度)
其他:
padlength=16-(长度(明文)%16)
padByte=chr(焊盘长度)
对于范围内的i(焊盘长度):
纯文本。附加(b“\x00”)
countByte=chr(通过)
如果通过==1:
密文=字节(countByte+padByte+iv+salt+aesManaged.encrypt(明文))
elif通过次数>=2:
密文=bytearray(AES托管.加密(明文))
对于范围内的i(通过-1):
ciphertext=aesManaged.encrypt(密文)
密文插入(0,salt)
密文插入(0,iv)
密文插入(0,padByte)
密文.插入(0,countByte)
返回密文
除:
打印“第%d行错误:%s”%(sys.exc\u traceback.tb\u行号,str(sys.exc\u info()[1]))
一无所获
现在我得到的是参数必须是字符串或只读缓冲区,而不是bytearray
错误,这些错误应该是字节数组,但要求字符串。在当前示例中,它位于elif passs>=2
之后的一行,将密文转换为字节数组。至少存在两个问题:
sys.getdefaultencoding()
在Python2环境中返回utf-8
,而不是ascii
。它可能会在某些输入上以静默方式中断某些Python库。这是一种创建难以调试的数据相关bug的方法。在站点
、站点自定义
、用户自定义
模块中查找sys.setdefaultencoding
bytestring.encode('utf-8')
相当于bytestring.decode(sys.getdefaultencodeding()).encode('utf-8')
。不要在bytestring上调用.encode(char\u encoding)
,而是在Unicode字符串上使用它
不要混合使用字节和Unicode字符串。为简单起见,从只处理字节的API开始,即拒绝Unicode字符串,并确保代码不会意外返回它们(这适用于加密/解密方法)
bytearray()
是一个可变的字节序列。您几乎可以在字节
(不可变的字节序列)或(更一般地)任何支持的对象可以使用的任何地方使用它
似乎aesManaged.encrypt(明文)
在plaintext
是字节数组时引发异常。除了可以用基于.rjust
的代码替换的.append
调用之外,您的代码不会在原地修改明文。直到AES
模块更新为支持bytearray
;在这种情况下,不要使用bytearray
,也不要在将其传递给不直接支持bytearray
的AES
方法之前对其进行转换(尝试buffer(明文)
)
代码中存在不必要的类型转换。删除它们。当你说“仅适用于字节”时,这正是我的想法——我希望我的函数能够加密/解密字节。但是如何将Unicode字符串转换为字节数组?@ki2ne:bytestring=Unicode\u string.encode(character\u encoding)
在查找Python文档后,我可以使用bytearray
类型(并使用bytearray()
转换字符串)为了避免混淆和/或混淆字符串和字节数组?@ki2ne:bytearray()
只是一个可变的字节序列。您几乎可以在任何可以使用字节的地方使用它。参数必须是字符串或只读缓冲区,而不是bytearray
。