好吧,基本上我在使用 Python 解密时遇到了问题。
我已经成功地使用 Node.js 加密/解密数据 - 使用“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模式,那么你必须使用crypto.createCipheriv
。如果您使用相同的密钥,则每次都必须使用不同的 IV。这就是为什么这实际上被称为 CTR 模式的随机数。对于 AES-CTR,96 位随机数是安全性和可能可加密明文大小之间的良好折衷方案。
var plaintext = 'asasasa'
var key = "1234567890123456" # don't use this one!
var nonce = crypto.randomBytes(12)
var iv = Buffer.concat([nonce, Buffer.alloc(4, 0)])
var cipher = crypto.createCipheriv("aes-128-ctr", key, iv)
var ciphertext = nonce.toString('hex') + cipher.update(plaintext,'utf8','hex') + cipher.final('hex')
console.log(ciphertext)
输出示例:
5b88aeb265712b6c8bfa8dbd63012d1e52eb42
IV 不是秘密的,解密时必须使用完全相同的 IV。通常,它通过添加前缀与密文一起发送。然后在解密之前将其切掉:
ct = codecs.decode('5b88aeb265712b6c8bfa8dbd63012d1e52eb42', '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[12:])
输出:
b'asasasa'