使用 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'
请记住,需要随机选择一个密钥。您可以生成随机密钥并将其以编码形式保存在源代码中(即十六进制)。如果这样做,则不得将源代码或字节码提供给您不信任密钥的任何人。
好的,所以基本上我在使用 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'
请记住,需要随机选择一个密钥。您可以生成随机密钥并将其以编码形式保存在源代码中(即十六进制)。如果这样做,则不得将源代码或字节码提供给您不信任密钥的任何人。