37

I am using following functions to encrypt/decrypt strings in 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;
}

(password is stored separately from encoded text). New version of nodejs/crypt package complains:

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

How do I rewrite this to upgrade my source code?

3 Answers 3

64

So lets say it like:

Replace deprecated crypto.createDecipher usage with crypto.createDecipheriv

why? because:

according to the deprecation docs it was due to security concerns.

Using crypto.createCipher() and crypto.createDecipher() should be avoided as they use a weak key derivation function (MD5 with no salt) and static initialization vectors. It is recommended to derive a key using crypto.pbkdf2() or crypto.scrypt() and to use crypto.createCipheriv() and crypto.createDecipheriv() to obtain the Cipher and Decipher objects respectively.

Link to the above reference: Click Here

Someone also said:

As per crypto_crypto_createdecipher_algorithm_password_options, one now need to switch to crypto.createDecipheriv.

Sample Code:

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();
}

For complete running example clone node-cheat and run node crypto-create-cipheriv.js.

Sign up to request clarification or add additional context in comments.

6 Comments

alright, see the updated answer now it has both code and node-cheat link. @StepanYakovenko
It will fire error (node:28641) UnhandledPromiseRejectionWarning: Error: Invalid key length
@Codebrekers that means you're not providing the correct ENCRYPTION_KEY. Please read this line carefully to make it work: github.com/zishon89us/node-cheat/blob/master/…
@Codebrekers The problem is that the key needs to be 32 bytes long. To achieve this (pad or shrink to 32 bytes regardless of the size of ENCRYPTION_KEY) you can use Buffer.concat([Buffer.from(ENCRYPTION_KEY), Buffer.alloc(32)], 32) as second argument to createCipheriv() and createDecipheriv()
You can use scrypt(secret, salt, 24, (err, key) => { // cipher/decipher here }) to ensure you have a key that is of the correct length for your algorithm. E.g. aes192 = 24 bytes (192 bits). You should use a unique salt if possible.
|
4

createDecipheriv is now Deprecated. Stability: 0 - Deprecated: Use crypto.createCipheriv() instead. One can easily replace it with 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);

2 Comments

Your code uses cbc, but I need ctr.
Have you checked replacing the algorithm with const ALGO = "aes-256-ctr". For me it is working for both ctr and cbc
0

You can use also createCipheriv:

const crypto = require('crypto');
var encryptionDecryption = {};

encryptionDecryption.Encryption = async (data, key) => {
  const iv = crypto.randomBytes(16);
  const cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(key), iv);
  let encrypted = cipher.update(data, 'utf8', 'base64');
  encrypted += cipher.final('base64');
  return {
    iv: iv.toString('base64'),
    encryptedData: encrypted
  };
}

encryptionDecryption.Decryption = async (encryptedData, key, iv) => {
  const decipher = crypto.createDecipheriv('aes-256-cbc', Buffer.from(key), Buffer.from(iv, 'base64'));
  let decrypted = decipher.update(encryptedData, 'base64', 'utf8');
  decrypted += decipher.final('utf8');
  return decrypted;
}

module.exports = encryptionDecryption;

// driver code
// calling this function MENU use this function in API if you call here then //it says cyclic dependencies

const encrypted = encrypt(data, key);
console.log('Encrypted:', encrypted);

const decrypted = decrypt(encrypted.encryptedData, key, encrypted.iv);
console.log('Decrypted:', decrypted);

for execute this make this as a function in any node/javascript compiler

Output

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.