当 IV 和值分别提供时,Python 中的 AES 解密

问题描述

我有一个基于 this SO answer 的加密/解密类设置。我已经测试过了,它工作正常。它不适用于我从中提取信息的新 API。新 API 是用 PHP 构建的,并使用以下包来加密信息:https://laravel.com/docs/8.x/encryption 使用 Laravel Crypt() 命令。所有加密值均使用 OpenSSL 和 AES-256-CBC 密码进行加密。

解密方法第一行后的enc

def decrypt(self,enc):
    enc = base64.b64decode(enc)
    iv = enc[:AES.block_size]
    cipher = AES.new(self.key,AES.MODE_CBC,iv)
    return self._unpad(cipher.decrypt(enc[AES.block_size:])).decode('utf-8')

看起来像这样(别担心,这只是非敏感的演示数据):

b"{'iv': 'Ld2pjRJqoKcWnW1P3tiO9Q==','value': 'M9QeHtbybeUxAVuIRcQ3bA==','mac': 'xxxxxx......'}"

,它基本上看起来像一个字节串 JSON。测试加密密钥为 base64:69GnnXWsW1qnW+soLXOVd8Mi4AdXKBFfkw88/7F2kSg=

我知道我可以把它变成这样的字典

import json
d = json.loads(enc)

我应该如何操作此字典中的值以准备像此类可以成功解密的其他加密文本一样对其进行解密?

更新:

根据评论,我尝试将方法修改为如下所示:

def decrypt(self,encrypted):
    enc = base64.b64decode(encrypted)
    if b'{"iv":' == enc[:6]:
        d = json.loads(enc)
        iv = base64.b64decode(d['iv'])
        val = base64.b64decode(d['value'])
    else:
        iv = enc[:AES.block_size]
        val = enc[AES.block_size:]
    cipher = AES.new(self.key,iv)
    return self._unpad(cipher.decrypt(val)).decode('utf-8')

这仍然不起作用。它没有崩溃,但我得到一个空白字符串 (''),我知道那不是加密的。答案应该是'Demo'

解决方法

问题“更新”部分中的代码无需任何更改即可运行。您只需要确保删除提供的加密密钥中的“base64:”前缀。删除后,它将按预期工作。