从 Nodejs 加密时解密 Python 中的 AES-256-CTR 有效负载

Decrypt AES-256-CTR payloads in Python when encrypted from Nodejs

我在 Nodejs 中编写了一个使用 AES-256-CTR 加密用户密码的应用程序:

const crypto = require('crypto')
const masterkey = 'azertyuiopazertyuiopazertyuiopaz'
const cipher = crypto.createCipher('aes-256-ctr', masterkey)
console.log(cipher.update('antoine', 'utf8', 'hex') + cipher.final('hex')) //=> 6415bc70ad76c6

然后它会保存到数据库中,现在我正尝试使用 PyCrypto 从 Python 脚本中破译它,如下所示:

masterkey = 'azertyuiopazertyuiopazertyuiopaz'
password = '6415bc70ad76c6'

from Crypto.Cipher import AES
import os
import binascii
counter = os.urandom(16)
# counter = bytes(16) # does not work
# counter = masterkey[0:16].encode() # does not work
cipher = AES.new(masterkey, AES.MODE_CTR, counter=lambda: counter)
print(cipher.decrypt(binascii.a2b_hex(password)))

但它给了我完全错误的结果。

你知道我错过了什么吗?

编辑

感谢 zaph,我的 Javascript 代码加密数据的方式似乎不安全。我仍然需要弄清楚 Node.js 内部使用的是什么 IV。我试了很多都没有成功

masterkey[0:16].encode()
bytes(16)

根据问题中的新信息进行更新:最好的选择是 Nodejs 使用默认计数器值。

加密和解密必须使用相同的计数器值。但是加密时没有提供计数器值,解密时使用的是随机值,因此它永远无法工作。

使用:crypto.createCipheriv(algorithm, key, iv) 其中 iv 是随机计数器初始值。

有必要在加密时创建一个随机计数器值并保存它,以便在解密时可以使用相同的初始计数器值。一种选择是在加密数据前加上计数器值,它不需要保密。然后在解密时,它可以从加密数据中分离出来并使用。

此外,当使用 CTR 模式时,相同的初始计数器值绝不能再次用于相同的密钥。

CTR mode

PyCrypto documentation CTR mode:

MODE_CBC
Cipher-Block Chaining (CBC). Each of the ciphertext blocks depends on the current and all previous plaintext blocks. An Initialization Vector (IV) is required.

The IV is a data block to be transmitted to the receiver. The IV can be made public, but it must be authenticated by the receiver and it should be picked randomly.)

IV 是初始计数器值。

[Nodejs dociumewnrtation: Class: Cipher:

crypto.createCipheriv(algorithm, key, iv)
    algorithm <string>  
    key <string> | <Buffer> | <TypedArray> | <DataView>
    iv <string> | <Buffer> | <TypedArray> | <DataView>

Creates and returns a Cipher object, with the given algorithm, key and initialization vector (iv).