Nodejs createDecipher可以用两个不同的密钥解密相同的密文

在使用Nodejs createDecipher时,我似乎能够使用两个不同的密钥解密相同的密文数据有效载荷而没有错误。

var ciphertext = '31c655f86b39fc9ac1dd96d7ae5e9d905e7c977df9ea70e6b87d3504caf03760'; var key1 = 'asdf'; var key2 = '8bc94f258d9aaf509061b5ff52bfeb019ce802959c41eaa188beacd5e33f21db'; function decrypt(data, key) { var decipher = crypto.createDecipher('aes-256-cbc', key); var decrypted = decipher.update(data, 'hex', 'utf8'); decrypted += decipher.final('utf8'); return decrypted; } // 890736.159999999 console.log(decrypt(ciphertext, key1)); //       F      쭳    M2     C < console.log(decrypt(ciphertext, key2)); 

当使用第二个密钥解密时,我期望产生一个EVP_DecryptFinal_ex:bad decrypt错误。 事实上,当我改变第二个键中的单个字符时会产生一个错误:

 crypto.js:153 var ret = this._handle.final(); ^ Error: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt at Error (native) at Decipher.Cipher.final (crypto.js:153:26) at decrypt (/Users/user/decrypt.js:8:27) at Object.<anonymous> (/Users/user/decrypt.js:13:13) at Module._compile (module.js:413:34) at Object.Module._extensions..js (module.js:422:10) at Module.load (module.js:357:32) at Function.Module._load (module.js:314:12) at Function.Module.runMain (module.js:447:10) at startup (node.js:148:18) 

使用第二个键: 8bc94f258d9aaf509061b5ff52bfeb019ce802959c41eaa188beacd5e33f21dd

虽然没有错误发生,第二个密钥产生的解密值是不正确的,预计890736.159999999。

我曾尝试在Mac上使用节点6.10.3,4.4.6和5.10。 我也尝试在运行amazon linux的Docker容器中使用Node 6.10.3。

根据文档 : The implementation of crypto.createDecipher() derives keys using the OpenSSL function EVP_BytesToKey with the digest algorithm set to MD5, one iteration, and no salt. 我可能看到一个MD5碰撞?

由于第二个解密数据不正确,所以没有正确解密。

明文是16个字节将会有16个字节的填充因此加上32个字节的encryption数据encryption的数据是64个hex字符或32个字节。

所以这一切都是有道理的。

现在的错误,我怀疑你得到一个填充错误,不正确的键,即填充是不一致的。 请参阅PKCS#7填充 。

填充错误不是对正确encryption密钥的有效检查。 如果您需要检查encryption是否成功,则需要添加validation。

这与MD5碰撞无关,与node.js.中默认使用PKCS#7填充的填充无关。

解压缩过程的作用是删除所有具有相同值的最后一个字节。 最后一个字节的值直接决定了需要删除多less个字节。 如果它的值为0x02,则删除2个字节。 检查填充中的其他字节是否与最后一个字节具有相同的值。 如果这个检查失败,你会得到一个错误。

如果您使用错误的密钥(或本例中的密码)进行解密,则在解除压缩之前,会产生随机的随​​机字节。 然后,解压缩过程将尝试删除填充并可能失败。 但有些情况下可能不会失败。 最后一个字节可以是一个0x01的值,这意味着它已经是一个有效的填充。 这可能发生在256的概率为1。

不要使用填充程序来检查您的密钥是否正确。 相反,您应该使用身份validation模式(如GCM或EAX)或通过消息身份validation代码(MAC)(如HMAC-SHA256)进行身份validation。