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上使用Node 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 字节的加密数据 加密数据为 64 个十六进制字符或 32 个字节。

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

现在对于错误,我怀疑您遇到带有不正确键的填充错误,即填充不一致。请参阅 PKCS#7 填充。

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

这与MD5冲突无关,而与node.js中默认为PKCS#7填充的填充有关。

取消填充过程的工作原理是删除所有具有相同值的最后一个字节。最后一个字节的值直接决定了需要删除多少字节。如果它的值为 0x02则删除 2 个字节。检查填充中的其他字节是否与最后一个字节具有相同的值。如果此检查失败,则会收到错误。

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

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

最新更新