我有一个nodejs服务,它对一些需要在Python中解密的数据使用AES加密。 无论我做什么,我都无法做到这一点。 NodeJS代码:
const algorithm = 'aes-128-ctr';
function encryptScript(data, key) {
const cipher = crypto.createCipher(algorithm, key);
let crypted = cipher.update(data, 'utf8', 'hex');
crypted += cipher.final('hex');
return crypted;
}
我用Python尝试过:
counter = Counter.new(128)
cipher = AES.new(key, AES.MODE_CTR, counter=counter)
print cipher.decrypt(enc.decode("hex"))
但它不起作用。
我的第一个问题是 Python 代码不接受超过 32 字节的密钥(而 Nodejs 代码可以)。
如果我使用 NodeJS 加密模块,解密正在工作:
function decryptScript(data, key) {
const decipher = crypto.createDecipher(algorithm, key);
let dec = decipher.update(data, 'hex', 'utf8');
dec += decipher.final('utf8');
return dec;
}
我不知道节点在做什么,但它可能与数据的某些填充有关。
我怎样才能让它工作?
(我更喜欢不需要更改 NodeJS 代码而只需要更改 Python 脚本的解决方案)。
-
CreateCipher
使用EVP_BytesToKey
从密码创建密钥和IV(NodeJS代码中所谓的密钥实际上是密码)。这是 Python 中EVP_BytesToKey
的实现。要使用的参数在CreateCipher
的文档中有描述:MD5,无盐,一次迭代。在CTR模式下,IV通常递增,每个块都以要定义的值开头。CreateCipher
使用用EVP_BytesToKey
确定的 IV 作为起始值。因此,CreateCipher
的功能可以在 Python 中实现,如下所示:import hashlib from Crypto.Cipher import AES from Crypto.Util import Counter ... encrypted = '5e99b5190f12143c057f6bdd8625f958682e737c11e138a2f571c050313dbe1008347604c7c7e8bf506a0a' # Example # Generate key and iv keySize = 16 ivSize = 16 digest = hashlib.md5 salt = b'' password = b'123456' # Example iteration = 1 keyiv = EVP_BytesToKey(keySize, ivSize, digest, salt, password, iteration) key = keyiv[0] iv = keyiv[1] # Define counter nbits = 128 initial_value = int.from_bytes(iv, byteorder = 'big'); counter = Counter.new(nbits, initial_value = initial_value) # Decrypt cipher = AES.new(key, AES.MODE_CTR, counter = counter) decrypted = cipher.decrypt(bytes.fromhex(encrypted)) print("Decrypted: " + decrypted.decode('utf8'))
密文是使用以下输入使用 NodeJS 代码生成的:
key = '123456'; data = 'The quick brown fox jumps over the lazy dog';
-
请注意,
CreateCipher
已弃用,不应再使用,尤其是不能与 CTR 模式结合使用。相反,可以使用CreateCipheriv
。在 CTR 模式下,密钥/IV 对仅使用一次非常重要。否则,安全性将丢失,请参阅此处。CreateCipher
不提供随机化,即相同的密码始终生成相同的密钥和IV,因此始终使用相同的密钥流。因此,如果多次使用相同的密码,则会失去安全性。 另一方面,CreateCipheriv
期望一个密钥和一个随机的IV。这里的一把钥匙可以是 只要 IV 的随机化确保键/值对不重复,就会使用多次,请参见此处。