在Node.js中如何替换已弃用的crypto.createCipher?

33

我正在使用以下函数在Node.js中加密/解密字符串:

var crypto = require('crypto');
var algorithm = 'aes-256-ctr';
function encrypt(text) {
    var cipher = crypto.createCipher(algorithm, password);
    try {
        var crypted = cipher.update(text, 'utf8', 'hex');
        crypted += cipher.final('hex');
    } catch (e) {
        return;
    }
    return crypted;
}

function decrypt(text) {
    var decipher = crypto.createDecipher(algorithm, password);
    try {
        var dec = decipher.update(text, 'hex', 'utf8');
        dec += decipher.final('utf8');
    } catch (e) {
        return;
    }
    return dec;
}

(密码被单独存储,与编码文本分开)。Nodejs / crypt包的新版本抱怨:

(node:5212) [DEP0106] DeprecationWarning: crypto.createDecipher is deprecated.

我该如何重写代码以升级我的源代码?

2个回答

56

那么,我们可以这样说:

将已弃用的 crypto.createDecipher 替换为 crypto.createDecipheriv

为什么?因为:

根据弃用文档 ,这是因为存在安全问题。

使用 crypto.createCipher()crypto.createDecipher() 应避免使用,因为它们使用了弱的密钥派生函数(没有盐的 MD5)和静态初始化向量。建议使用 crypto.pbkdf2()crypto.scrypt() 派生密钥,并分别使用 crypto.createCipheriv()crypto.createDecipheriv() 来获取 Cipher 和 Decipher 对象。

上述引用的链接:点击此处

有人也说过:

根据crypto_crypto_createdecipher_algorithm_password_options,现在需要切换到 crypto.createDecipheriv

示例代码:

const crypto = require('crypto');
const algorithm = 'aes-256-ctr';
const ENCRYPTION_KEY = 'Put_Your_Password_Here'; // or generate sample key Buffer.from('FoCKvdLslUuB4y3EZlKate7XGottHski1LmyqJHvUhs=', 'base64');
const IV_LENGTH = 16;

function encrypt(text) {
    let iv = crypto.randomBytes(IV_LENGTH);
    let cipher = crypto.createCipheriv(algorithm, Buffer.from(ENCRYPTION_KEY, 'hex'), iv);
    let encrypted = cipher.update(text);
    encrypted = Buffer.concat([encrypted, cipher.final()]);
    return iv.toString('hex') + ':' + encrypted.toString('hex');
}

function decrypt(text) {
    let textParts = text.split(':');
    let iv = Buffer.from(textParts.shift(), 'hex');
    let encryptedText = Buffer.from(textParts.join(':'), 'hex');
    let decipher = crypto.createDecipheriv(algorithm, Buffer.from(ENCRYPTION_KEY, 'hex'), iv);
    let decrypted = decipher.update(encryptedText);
    decrypted = Buffer.concat([decrypted, decipher.final()]);
    return decrypted.toString();
}

要获取完整的运行示例,请克隆node-cheat并运行node crypto-create-cipheriv.js


好的,现在请查看更新后的答案,它包含了代码和node-cheat链接。@StepanYakovenko - Zeeshan Hassan Memon
1
它将会触发错误 (node:28641) UnhandledPromiseRejectionWarning: Error: Invalid key length - Codebrekers
@Codebrekers 这意味着您没有提供正确的ENCRYPTION_KEY。请仔细阅读此行以使其正常工作:https://github.com/zishon89us/node-cheat/blob/master/stackoverflow_answers/crypto-create-cipheriv.js#L9 - Zeeshan Hassan Memon
11
问题在于密钥需要为32个字节长。为了实现这一点(无论ENCRYPTION_KEY的大小如何),您可以使用Buffer.concat([Buffer.from(ENCRYPTION_KEY), Buffer.alloc(32)], 32)作为createCipheriv()createDecipheriv()的第二个参数来填充或缩小到32个字节。 - Thalis K.
你可以使用 scrypt(secret, salt, 24, (err, key) => { // cipher/decipher here }) 来确保你拥有一个适合你算法的正确长度的密钥。例如,aes192 = 24字节(192位)。如果可能的话,你应该使用一个唯一的盐。 - Learner
将IV与加密值一起存储是安全的吗? - Learner

2

createDecipheriv 现在已废弃。稳定性:0 - 已废弃:请使用 crypto.createCipheriv()。可以轻松地用 createCipheriv 替换它。

const crypto = require('crypto');
const ENC= 'bf3c199c2470cb477d907b1e0917c17b';
const IV = "5183666c72eec9e4";
const ALGO = "aes-256-cbc"

const encrypt = ((text) => 
{
   let cipher = crypto.createCipheriv(ALGO, ENC, IV);
   let encrypted = cipher.update(text, 'utf8', 'base64');
   encrypted += cipher.final('base64');
   return encrypted;
});

const decrypt = ((text) => 
{
   let decipher = crypto.createDecipheriv(ALGO, ENC, IV);
   let decrypted = decipher.update(text, 'base64', 'utf8');
   return (decrypted + decipher.final('utf8'));
});

const encrypted_key = encrypt("HelloWorld");
const decrypted_key = decrypt(encrypted_key);

1
你的代码使用了cbc,但我需要ctr。 - Stepan Yakovenko
1
你有尝试将算法替换为const ALGO = "aes-256-ctr"吗? 对我来说,无论是ctr还是cbc都可以正常工作。 - Jyotirmoy Upadhaya

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接