将 AES 解密从 CryptoJS 移植到 PyCrypto

Porting AES decryption from CryptoJS to PyCrypto

这是一个 JavaScript 部分,它使用 AES 加密对字符串进行解码

var p = 'some large string'
var s = 'Q05WTmhPSjlXM1BmeFd0UEtiOGg=' 
var y = CryptoJS.AES.decrypt({
    ciphertext: CryptoJS.enc.Base64.parse(p)
}, CryptoJS.enc.Base64.parse(s), {
    iv  CryptoJS.enc.Hex.parse("random")
});
var v = y.toString(CryptoJS.enc.Utf8)

我正在尝试通过导入 AES 在 python 中编写类似的解码函数。

谁能帮我解决这个问题。我无法找出 js 的所有等效代码 python.

我查了这个页面 Python AES Decryption Routine (Code Help)

AES - Encryption with Crypto (node-js) / decryption with Pycrypto (python)

不确定他们是否有类似于我这里的js的代码

"y.toString(CryptoJS.enc.Utf8)"

这在python是什么意思

我从其他来源尝试过类似的东西

from base64 import b64decode
from Crypto.Cipher import AES

iv = 'random'
key = 'Q05WTmhPSjlXM1BmeFd0UEtiOGg='
encoded = b64decode('some large string')

dec = AES.new(key=key, mode=AES.MODE_CBC, IV=iv)
value = dec.decrypt(encoded)

您的 CryptoJS 代码和 Python 代码存在多个问题。

密钥大小错误

您的密钥 s 仅包含 20 个字节(160 位),不构成 AES 的任何有效密钥大小,即 128 (10)、192 (12) 和 256 位(14 轮) ). CryptoJS 将默默地 运行 11 轮的 160 位密钥的密钥计划,PyCrypto 不支持 (参见 AES.c)。

您可以在 CryptoJS 中将密钥减少到 128 位:

var key = CryptoJS.enc.Base64.parse('Q05WTmhPSjlXM1BmeFd0UEtiOGg=');
key.sigBytes = 16;
key.clamp();

或 Python:

key = b64decode('Q05WTmhPSjlXM1BmeFd0UEtiOGg=')[:16]

错误的字符编码

您忘记从 Python 中的 Base64 字符串解码密钥,并且您忘记从十六进制解码 IV。字符 '0' 和字节 0x00 完全不同。有一种更简单的方法来定义全零 IV:

iv = "[=12=]"*16

没有取消填充

CryptoJS 默认使用 PKCS#7 填充,但 PyCrypto 不实现任何填充,仅将数据处理为块大小的倍数。解密后,您需要自己删除 Python:

中的填充
value = value[:value[-1]]

(最后一个字节决定了有多少字节是填充字节)。更多关于 here.


其他注意事项:

您真的不应该将 IV 设置为静态值。应该为使用相同密钥的每次加密随机生成 IV。否则,您将失去语义安全性。由于IV不必是秘密的,你可以把它放在密文前面,然后在解密之前把它切掉。