如何对AES加密生成的字节串进行URL编码及解密还原?
AES加密字节串URL编码与解密修复方案
问题原因
你直接对加密后的字节串调用urllib.parse.quote时,Python会将字节串转换为字节的字符串表示(例如b'\x01\x02'变成字符串"b'\\x01\\x02'"),而非对原始二进制数据进行URL编码。后续unquote得到的是这个字符串,不是原始加密字节,传给AES解密函数自然失败——因为解密需要的是二进制字节,不是字符串。
正确解决方案
方法一:使用字节专用的URL编码/解码函数
urllib.parse提供了quote_from_bytes和unquote_to_bytes,专门处理二进制数据的URL编解码:
from Cryptodome.Cipher import AES from Cryptodome.Util.Padding import pad, unpad import urllib.parse key = "00112233445566778899aabbccddeeff".encode("utf8") iv = b'\x0cK\x1c\x82\xf1\xa9w\xfe\xa9\x9a\xd0\xb3\x8c\xec1\x1c' # os.urandom(16) aes = AES.new(key, AES.MODE_CBC, iv) data = pad(b'HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH', 16) encd = aes.encrypt(data) # 对加密字节串直接URL编码 a = urllib.parse.quote_from_bytes(encd) # URL解码转回字节串 b = urllib.parse.unquote_to_bytes(a) # 解密流程 aes_dec = AES.new(key, AES.MODE_CBC, iv) decd = unpad(aes_dec.decrypt(b), 16) print(decd) # 输出原始明文数据
方法二:先转Base64再URL编码(推荐)
二进制数据直接URL编码会产生大量%xx格式字符,先用Base64将其转为纯文本字符串,再进行URL编码,可读性更好且更通用:
from Cryptodome.Cipher import AES from Cryptodome.Util.Padding import pad, unpad import urllib.parse import base64 key = "00112233445566778899aabbccddeeff".encode("utf8") iv = b'\x0cK\x1c\x82\xf1\xa9w\xfe\xa9\x9a\xd0\xb3\x8c\xec1\x1c' # os.urandom(16) aes = AES.new(key, AES.MODE_CBC, iv) data = pad(b'HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH', 16) encd = aes.encrypt(data) # 加密字节串转Base64字符串,再URL编码 b64_enc_str = base64.b64encode(encd).decode('utf8') a = urllib.parse.quote(b64_enc_str) # URL解码后转回Base64字节,再解密 b = urllib.parse.unquote(a) encd_bytes = base64.b64decode(b) aes_dec = AES.new(key, AES.MODE_CBC, iv) decd = unpad(aes_dec.decrypt(encd_bytes), 16) print(decd) # 输出原始明文数据
内容的提问来源于stack exchange,提问作者Raymond Seger
相关产品推荐
相关产品推荐

