使用 Node.js AES CTR 加密并使用 PyCrypto 解密

Encrypt with Node.js AES CTR and decrypt with PyCrypto

好的,所以基本上我在使用 Python 解密时遇到问题。

我已经使用 Node.js 成功地 encrypt/decrypt 数据 - 使用 "aes-128-ctr",PyCrypto 也是如此,但是当我尝试使用 Node.js 加密并解密时使用 Python 我得到无效的解密文本。

Node.js代码:

var key = "1234567890123456";
var cipher = crypto.createCipher("aes-128-ctr",key)
var ctext = cipher.update('asasasa','utf8','hex') +  cipher.final('hex')
console.log(ctext) // outputs: "f2cf6ecd8f"

Python代码:

counter = Counter.new(128)
cipher = AES.new("1234567890123456", AES.MODE_CTR, counter=counter)
cipher.decrypt("f2cf6ecd8f") // outputs: weird encoding characters

顺便说一句,我不关心这种加密的安全级别,我更关心性能。

crypto.createCipher 接受密码,EVP_BytesToKey 从中导出密钥和 IV,但 pycrypto 直接需要密钥和 IV。您需要使用完全相同的程序。

crypto.createCipher 绝不能与 CTR 模式一起使用,因为密钥和 IV 的生成不是随机的。由于 CTR 模式是一种流模式,它总是会产生相同的密钥流,这可能使 观察到使用相同密码加密的多个密文的攻击者能够推断出明文。这是可能的,因为由此产生的多次键盘问题。

如果一定要用CTR-mode,那你就得用crypto.createCipheriv。如果您使用相同的密钥,则每次都必须使用不同的 IV。这就是为什么这实际上被称为 CTR 模式的随机数。对于 AES-CTR,96 位随机数是安全性和可能加密明文大小之间的良好折衷。

var key = "1234567890123456"
var iv = Buffer.concat([crypto.randomBytes(12), Buffer.alloc(4, 0)])
var cipher = crypto.createCipheriv("aes-128-ctr", key, iv)
var ctext = iv.toString('hex') + cipher.update('asasasa','utf8','hex') +  cipher.final('hex')
console.log(ctext)

示例输出:

5b88aeb265712b6c8bfa8dbd0000000063012d1e52eb42

IV 不是秘密的,您必须在解密过程中使用完全相同的 IV。通常,它通过在密文前加前缀与密文一起发送。然后在解密之前将其切掉:

ct = codecs.decode('5b88aeb265712b6c8bfa8dbd0000000063012d1e52eb42', 'hex') # I'm using Python 3
counter = Counter.new(32, prefix=ct[:12], initial_value=0)
cipher = AES.new("1234567890123456", AES.MODE_CTR, counter=counter)
cipher.decrypt(ct[16:])

输出:

b'asasasa'

请记住,需要随机选择一个密钥。您可以生成随机密钥并将其以编码形式保存在源代码中(即十六进制)。如果这样做,则不得将源代码或字节码提供给您不信任密钥的任何人。