Python中AES加密URL时遇到结果不一致的情况,如何解决?

key 是 3c837d501a8f49b1 原始字符串是 http://172.19.38.84/xwado/ 我用 Python 通过 AES128 加密后转 base64 的结果是:3O6CsFgm69Jg9l_I-MpEpE_FMPrDrIBFmfbOY78S0zU= 但是对方提供的正确加密后的结果是: 3O6CsFgm69Jg9l/I+MpEpHsIZ5h2dSWcZNMvAKVSCDQ

找了一圈,如果我用普通字符串加密能和对方对得上,但一涉及到 URL 如“ http://127.0.0.1/xxxx/” 之类的就直接不一致了,请教下各位大神是什么原因?


Python中AES加密URL时遇到结果不一致的情况,如何解决?

8 回复
  1. 你的 base64 结果中出现了 _ ,这是非标准 base64 字符
    2. 你给出的正确加密结果根本就不是合法的 base64 结果,连 base64 decode 都无法完成。。。

我遇到过类似问题,通常是因为编码或填充方式不一致导致的。AES加密URL时需要特别注意字符编码和URL安全处理。

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import base64
import urllib.parse

class URLAESCipher:
    def __init__(self, key, iv=None):
        self.key = key.ljust(32)[:32].encode('utf-8')  # 确保32字节
        self.iv = (iv or '0123456789ABCDEF').encode('utf-8')[:16]
        
    def encrypt(self, plaintext):
        # 创建AES cipher对象
        cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
        
        # 填充并加密
        padded_data = pad(plaintext.encode('utf-8'), AES.block_size)
        encrypted = cipher.encrypt(padded_data)
        
        # Base64编码并URL安全处理
        encrypted_b64 = base64.b64encode(encrypted).decode('utf-8')
        url_safe = urllib.parse.quote(encrypted_b64, safe='')
        
        return url_safe
    
    def decrypt(self, encrypted_text):
        # URL解码
        decoded_url = urllib.parse.unquote(encrypted_text)
        
        # Base64解码
        encrypted_data = base64.b64decode(decoded_url)
        
        # 解密
        cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
        decrypted_padded = cipher.decrypt(encrypted_data)
        
        # 去除填充
        plaintext = unpad(decrypted_padded, AES.block_size).decode('utf-8')
        
        return plaintext

# 使用示例
if __name__ == "__main__":
    # 测试数据
    key = "mysecretkey123"
    data = "https://example.com/api?param=value"
    
    cipher = URLAESCipher(key)
    
    # 加密
    encrypted = cipher.encrypt(data)
    print(f"加密结果: {encrypted}")
    
    # 解密
    decrypted = cipher.decrypt(encrypted)
    print(f"解密结果: {decrypted}")

主要注意这几点:

  1. 编码一致性:确保加密前和解密后使用相同的字符编码(通常UTF-8)
  2. 密钥处理:AES-256需要32字节密钥,不够时要填充
  3. 填充模式:使用标准的PKCS7填充
  4. URL安全:Base64结果中的+/=要URL编码或替换

如果还是不一致,检查两边是否使用相同的IV、模式和填充方案。

总结:确保加解密两端参数完全一致。

解密看下呗。

我猜测,楼主最重要的一点可能没有提,就是加密后的密文,是通过 url 传输的,你需要 urlencode。
而且,这个 encode 不是随便拿一个就能用,你自己仔细研究一下区别吧。

由于你用的是 ECB 的加密模式,对比你们双方的密文:
3O6CsFgm69Jg9l/I+MpEp E/FMPrDrIBFmfbOY78S0zU=
3O6CsFgm69Jg9l/I+MpEp HsIZ5h2dSWcZNMvAKVSCDQ

可以看出你的加密前半段是完全没有问题的,所谓的正确解密结果少了一位。也就是说,你们双方加密的明文后半段出现了差错。看看是不是什么不可见字符或者错误吧。
按照你给出的原始字符"http://172.19.38.84/xwado/" 和 key “3c837d501a8f49b1” (均不包含引号),正确的 ECB 加密结果应该是

3O6CsFgm69Jg9l/I+MpEpE/FMPrDrIBFmfbOY78S0zU=

加密模式,填充,偏移

#5 另外还有可能末尾的 \0。

3O6CsFgm69Jg9l/I+MpEpIQ1j0ON8Auk1KcfTNMGNmk=

3O6CsFgm69Jg9l/I+MpEpE/FMPrDrIBFmfbOY78S0zU=

填充方式不同,结果不同。。。

http://tool.chacuo.net/cryptaes

回到顶部