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

时间:2017-06-22 04:12:51

标签: node.js encryption openssl

使用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。

根据docsThe 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碰撞?

2 个答案:

答案 0 :(得分:2)

由于第二个解密数据不正确,因此正确解密。

明文是16个字节 将添加16个字节的填充,从而添加32个字节的加密数据 加密数据为64个十六进制字符或32个字节。

所以这一切都有道理。

现在出现错误,我怀疑你的错误键出现填充错误,即填充不一致。请参阅PKCS#7 padding

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

答案 1 :(得分:1)

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

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

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

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