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