11

使用以下节点 js:

var crypto = require('crypto');
var encrypt = function (input, password, callback) {
    var m = crypto.createHash('md5');
    m.update(password);
    var key = m.digest('hex');

    m = crypto.createHash('md5');
    m.update(password + key);
    var iv = m.digest('hex');
    console.log(iv);

    var data = new Buffer(input, 'utf8').toString('binary');

    var cipher = crypto.createCipheriv('aes-256-cbc', key, iv.slice(0,16));
    var encrypted = cipher.update(data, 'binary') + cipher.final('binary');
    var encoded = new Buffer(encrypted, 'binary').toString('base64');
    callback(encoded);
};

var decrypt = function (input, password, callback) {
    // Convert urlsafe base64 to normal base64
    input = input.replace(/\-/g, '+').replace(/_/g, '/');
    // Convert from base64 to binary string
    var edata = new Buffer(input, 'base64').toString('binary');

    // Create key from password
    var m = crypto.createHash('md5');
    m.update(password);
    var key = m.digest('hex');

    // Create iv from password and key
    m = crypto.createHash('md5');
    m.update(password + key);
    var iv = m.digest('hex');

    // Decipher encrypted data
    var decipher = crypto.createDecipheriv('aes-256-cbc', key, iv.slice(0,16));
    var decrypted = decipher.update(edata, 'binary') + decipher.final('binary');
    var plaintext = new Buffer(decrypted, 'binary').toString('utf8');

    callback(plaintext);
};

为了执行,我运行了这个:

encrypt("uWeShxRrCKyK4pcs", "secret", function (encoded) {
    console.log(encoded);
    decrypt(encoded, "secret", function (output) {
        console.log(output);
    });
});

加密似乎工作正常,但是当我尝试解密时,我收到以下错误:

错误:错误:06065064:数字信封例程:EVP_DecryptFinal_ex:Decipheriv.Cipher.final (crypto.js:202:26) 错误(本机)错误解密

我对密码学很陌生,所以真的不知道为什么我会收到这个错误。我现在只需要修复它。

4

3 回答 3

9

您混合了两种不同的编码。看

cipher.update(data[, input_encoding][, output_encoding])

cipher.final([output_encoding])

现在看看

var encrypted = cipher.update(data, 'binary') + cipher.final('binary');

但应该是

var encrypted = cipher.update(data, 'binary', 'binary') + cipher.final('binary');

问题是cipher.update(data, 'binary')输出一个缓冲区,该缓冲区会自动字符串化为十六进制编码字符串而不是“二进制”字符串。


无论如何,这段代码有很多错误,你应该重新开始,简单地使用一个高度自以为是的现有库。

  • 为了达到语义安全,您必须有一个随机 IV 附加到密文中。

  • 密码具有低熵,不能用作密钥。单个 MD5 调用不会改变这一事实。从密码导出密钥应该很慢,因此请使用具有高迭代次数/成本因素的已知方案,例如 PBKDF2、bcrypt、scrypt 或 Argon2(提高安全性)。别忘了盐。

  • 使用 encrypt-then-MAC 方案中的消息验证码(例如 HMAC-SHA256)验证您的密文。否则,攻击者可能会操纵密文,您甚至无法检测到更改。使用填充预言攻击丢失数据的第一步。

于 2016-06-27T18:31:56.463 回答
1

由于这个问题是第一个出现在 Google 上的问题,所以这里有另一个解决方案。

救星坏解密

如果链接断开,就我而言,我必须更新解密功能以添加

function decrypt(text) {
    let iv = Buffer.from((text.split(':')[1]).split('=')[0], 'hex')//will return iv;
    let enKey = Buffer.from(text.split('=')[1], 'hex')//will return key;
    let encryptedText = Buffer.from(text.split(':')[0], 'hex');//returns encrypted Data
    let decipher = crypto.createDecipheriv('aes-256-cbc', Buffer.from(enKey), iv);
// Added this line here
    decipher.setAutoPadding(false);
    let decrypted = decipher.update(encryptedText);
    decrypted = Buffer.concat([decrypted, decipher.final()]);
    return decrypted.toString();
    //returns decryptedData
}
于 2021-06-14T07:29:33.127 回答
-1

我发现了这个原因,是使用不同的密钥或 iv进行加密和解密。我们必须使用用于加密和解密内容的相同密钥 & iv。唯一的解决方法是将iv 和密钥保存在加密数据期间使用的数组中,或在分隔符的帮助下将 iv 和密钥与加密数据连接起来

示例一:

function encrypt(text) {
    let cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(key), iv);
    let encrypted = cipher.update(text);
    encrypted = Buffer.concat([encrypted, cipher.final()]);
    return encrypted.toString('hex') + ':' + iv.toString('hex') + '=' + 
    key.toString('hex');
    //returns encryptedData:iv=key
}

function decrypt(text) {
    let iv = Buffer.from((text.split(':')[1]).split('=')[0], 'hex')//will return iv;
    let enKey = Buffer.from(text.split('=')[1], 'hex')//will return key;
    let encryptedText = Buffer.from(text.split(':')[0], 'hex');//returns encrypted Data
    let decipher = crypto.createDecipheriv('aes-256-cbc', Buffer.from(enKey), iv);
    let decrypted = decipher.update(encryptedText);
    decrypted = Buffer.concat([decrypted, decipher.final()]);
    return decrypted.toString();
    //returns decryptedData
}

示例二:

function encrypt(text) {
    let cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(key), iv);
    let encrypted = cipher.update(text);
    encrypted = Buffer.concat([encrypted, cipher.final()]);
    return { 
        "encryptedData": encrypted.toString('hex'),
        "iv" : iv.toString('hex'),
        "key" : key.toString('hex');
    //returns an Array of key, iv & encryptedData
  }
}

function decrypt(text) {
    let iv = Buffer.from((text.iv, 'hex')//will return iv;
    let enKey = Buffer.from(text.key, 'hex')//will return key;
    let encryptedText = Buffer.from(text.encryptedData, 'hex');//returns encrypted Data
    let decipher = crypto.createDecipheriv('aes-256-cbc', Buffer.from(enKey), iv);
    let decrypted = decipher.update(encryptedText);
    decrypted = Buffer.concat([decrypted, decipher.final()]);
    return decrypted.toString();
    //returns decryptedData
}
于 2019-05-27T03:27:06.137 回答