101

We are using bcrypt for hashing passwords and data that never needs to be decrypted. What should we do to protect other user information that does need to be decrypted?

For example, let's say that we didn't want a user's real name to be in plain text in case someone was to obtain access to the database. This is somewhat sensitive data but also needs to be called from time to time and displayed in plain text. Is there a simple way to do this?

Steve Chambers
  • 37,270
  • 24
  • 156
  • 208
fancy
  • 48,619
  • 62
  • 153
  • 231
  • 7
    Situations in which an attacker can obtain your database, but not the encryption keys you're also storing on disk are frequently pretty contrived. Are you sure you've thought this through? – Nick Johnson Aug 08 '11 at 04:45
  • 69
    The Internet is so smart and helpful. It's great when people choose to demonstrate their intelligence by insult your approach rather than answering the question or providing substantive guidance. – Secesh May 19 '14 at 18:30
  • 3
    You’re not encrypting your data with bcrypt, because it doesn’t do encryption. You’re hashing it. They’re not the same thing. – Mike Scott Aug 24 '20 at 14:07

10 Answers10

174

You can use the crypto module:

var crypto = require('crypto');
var assert = require('assert');

var algorithm = 'aes256'; // or any other algorithm supported by OpenSSL
var key = 'password';
var text = 'I love kittens';

var cipher = crypto.createCipher(algorithm, key);  
var encrypted = cipher.update(text, 'utf8', 'hex') + cipher.final('hex');
var decipher = crypto.createDecipher(algorithm, key);
var decrypted = decipher.update(encrypted, 'hex', 'utf8') + decipher.final('utf8');

assert.equal(decrypted, text);

Edit

Now createCipher and createDecipher is deprecated instead use createCipheriv and createDecipheriv

mak
  • 13,267
  • 5
  • 41
  • 47
  • 8
    Would you recommend adding an IV to this to make it more secure? If so, how would this be done with `crypto`? – Fizzix Apr 20 '17 at 05:46
  • 3
    @Fizzix, createCipheriv requires an IV if I am correct. – Royal Dec 02 '21 at 08:27
  • Not useful anymore! Once `createCipher` and `createDecipher` are deprecated, this solution won't work. They require more parameters as `IV`. – Willian Oct 24 '22 at 18:26
68

Update on 12-DEC-2019

Unlike some other modes like CBC, GCM mode does not require the IV to be unpredictable. The only requirement is that the IV has to be unique for each invocation with a given key. If it repeats once for a given key, security can be compromised. An easy way to achieve this is to use a random IV from a strong pseudo random number generator as shown below.

Using a sequence or timestamp as IV is also possible, but it may not be as trivial as it may sound. For example, if the system does not correctly keep track of the sequences already used as IV in a persistent store, an invocation may repeat an IV after a system reboot. Likewise, there is no perfect clock. Computer clocks readjusts etc.

Also, the key should be rotated after every 2^32 invocations. For further details on the IV requirement, refer to this answer and the NIST recommendations.

Update on 30-JUL-2019

As the answer is getting more views and votes, I think it is worth mentioning that the code below has used a *Sync method - crypto.scryptSync. Now that is fine if the encryption or decryption is done during application initialization. Otherwise, consider using the asynchronous version of the function to avoid blocking the event loop. (A promise library like bluebird is useful).

Update on 23-JAN-2019

The bug in decryption logic has been fixed. Thanks @AlexisWilke for rightly pointing it out.


The accepted answer is 7 years old and doesn't look secured today. Hence, I'm answering it:

  1. Encryption Algorithm: Block cipher AES with 256 bits key is considered secure enough. To encrypt a complete message, a mode needs to be selected. Authenticated encryption (which provides both confidentiality and integrity) is recommended. GCM, CCM and EAX are most commonly used authenticated encryption modes. GCM is usually preferred and it performs well in Intel architectures which provide dedicated instructions for GCM. All these three modes are CTR-based (counter-based) modes and therefore they do not need padding. As a result they are not vulnerable to padding related attacks

  2. An initialization Vector (IV) is required for GCM. The IV is not a secret. The only requirement being it has to be random or unpredictable. In NodeJs, crypto.randomBytes() is meant to produce cryptographically strong pseudo random numbers.

  3. NIST recommends 96 bit IV for GCM to promote interoperability, efficiency, and simplicity of design

  4. The recipient needs to know the IV to be able to decrypt the cipher text. Therefore the IV needs to be transferred along with the cipher text. Some implementations send the IV as AD (Associated Data) which means that the authentication tag will be calculated on both the cipher text and the IV. However, that is not required. The IV can be simply pre-pended with the cipher text because if the IV is changed during transmission due to a deliberate attack or network/file system error, the authentication tag validation will fail anyway

  5. Strings should not be used to hold the clear text message, password or the key as Strings are immutable which means we cannot clear the strings after use and they will linger in the memory. Thus a memory dump can reveal the sensitive information. For the same reason, the client calling these encryption or decryption methods should clear all the Buffer holding the message, key or the password after they are no longer needed using bufferVal.fill(0).

  6. Finally for transmission over network or storage, the cipher text should be encoded using Base64 encoding. buffer.toString('base64'); can be used to convert the Buffer into Base64 encoded string.

  7. Note that the key derivation scrypt (crypto.scryptSync()) has been used to derive a key from a password. However, this function is available only in Node 10.* and later versions

The code goes here:

const crypto = require('crypto');

var exports = module.exports = {};

const ALGORITHM = {
    
    /**
     * GCM is an authenticated encryption mode that
     * not only provides confidentiality but also 
     * provides integrity in a secured way
     * */  
    BLOCK_CIPHER: 'aes-256-gcm',

    /**
     * 128 bit auth tag is recommended for GCM
     */
    AUTH_TAG_BYTE_LEN: 16,

    /**
     * NIST recommends 96 bits or 12 bytes IV for GCM
     * to promote interoperability, efficiency, and
     * simplicity of design
     */
    IV_BYTE_LEN: 12,

    /**
     * Note: 256 (in algorithm name) is key size. 
     * Block size for AES is always 128
     */
    KEY_BYTE_LEN: 32,

    /**
     * To prevent rainbow table attacks
     * */
    SALT_BYTE_LEN: 16
}

const getIV = () => crypto.randomBytes(ALGORITHM.IV_BYTE_LEN);
exports.getRandomKey = getRandomKey = () => crypto.randomBytes(ALGORITHM.KEY_BYTE_LEN);

/**
 * To prevent rainbow table attacks
 * */
exports.getSalt = getSalt = () => crypto.randomBytes(ALGORITHM.SALT_BYTE_LEN);

/**
 * 
 * @param {Buffer} password - The password to be used for generating key
 * 
 * To be used when key needs to be generated based on password.
 * The caller of this function has the responsibility to clear 
 * the Buffer after the key generation to prevent the password 
 * from lingering in the memory
 */
exports.getKeyFromPassword = getKeyFromPassword = (password, salt) => {
    return crypto.scryptSync(password, salt, ALGORITHM.KEY_BYTE_LEN);
}

/**
 * 
 * @param {Buffer} messagetext - The clear text message to be encrypted
 * @param {Buffer} key - The key to be used for encryption
 * 
 * The caller of this function has the responsibility to clear 
 * the Buffer after the encryption to prevent the message text 
 * and the key from lingering in the memory
 */
exports.encrypt = encrypt = (messagetext, key) => {
    const iv = getIV();
    const cipher = crypto.createCipheriv(
        ALGORITHM.BLOCK_CIPHER, key, iv,
        { 'authTagLength': ALGORITHM.AUTH_TAG_BYTE_LEN });
    let encryptedMessage = cipher.update(messagetext);
    encryptedMessage = Buffer.concat([encryptedMessage, cipher.final()]);
    return Buffer.concat([iv, encryptedMessage, cipher.getAuthTag()]);
}

/**
 * 
 * @param {Buffer} ciphertext - Cipher text
 * @param {Buffer} key - The key to be used for decryption
 * 
 * The caller of this function has the responsibility to clear 
 * the Buffer after the decryption to prevent the message text 
 * and the key from lingering in the memory
 */
exports.decrypt = decrypt = (ciphertext, key) => {
    const authTag = ciphertext.slice(-16);
    const iv = ciphertext.slice(0, 12);
    const encryptedMessage = ciphertext.slice(12, -16);
    const decipher = crypto.createDecipheriv(
        ALGORITHM.BLOCK_CIPHER, key, iv,
        { 'authTagLength': ALGORITHM.AUTH_TAG_BYTE_LEN });
    decipher.setAuthTag(authTag);
    let messagetext = decipher.update(encryptedMessage);
    messagetext = Buffer.concat([messagetext, decipher.final()]);
    return messagetext;
}

And the unit tests are also provided below:

const assert = require('assert');
const cryptoUtils = require('../lib/crypto_utils');
describe('CryptoUtils', function() {
  describe('decrypt()', function() {
    it('should return the same mesage text after decryption of text encrypted with a '
     + 'randomly generated key', function() {
      let plaintext = 'my message text';
      let key = cryptoUtils.getRandomKey();
      let ciphertext = cryptoUtils.encrypt(plaintext, key);

      let decryptOutput = cryptoUtils.decrypt(ciphertext, key);

      assert.equal(decryptOutput.toString('utf8'), plaintext);
    });

    it('should return the same mesage text after decryption of text excrypted with a '
     + 'key generated from a password', function() {
      let plaintext = 'my message text';
      /**
       * Ideally the password would be read from a file and will be in a Buffer
       */
      let key = cryptoUtils.getKeyFromPassword(
              Buffer.from('mysecretpassword'), cryptoUtils.getSalt());
      let ciphertext = cryptoUtils.encrypt(plaintext, key);

      let decryptOutput = cryptoUtils.decrypt(ciphertext, key);

      assert.equal(decryptOutput.toString('utf8'), plaintext);
    });
  });
});
Steve Chambers
  • 37,270
  • 24
  • 156
  • 208
Saptarshi Basu
  • 8,640
  • 4
  • 39
  • 58
  • 3
    I know you have a test and you probably ran a special case (small input)... but it looks like you have a bug in the `decrypt()` as you do nothing with the output of `decipher.final()`. It should be concatenated, right? – Alexis Wilke Jan 23 '19 at 06:36
  • @AlexisWilke, This is fixed now. Thank you for pointing it out. – Saptarshi Basu Jan 25 '19 at 05:06
  • Excellent and informative answer! Can you please ellaborate on (or perhaps put into practice in your test cases) your point in number 6? How should someone use the information without storing the value in a string as you have in the test cases as well? I feel this is great for academic purposes, but wouldn't it be better to use an open source library in production? ex: [Themis](https://github.com/cossacklabs/themis) – Matthew Sanders May 18 '19 at 18:12
  • 1
    @MatthewSanders The tests could have been written using buffers. But still you're right. There may be scenarios where you can't avoid using strings. However, such usages should be minimal for reasons mentioned above. There is no harm in using a battle-tested library. The problem happens when we assume that a library is always correct and forget the fact that it may have bugs or issues as well. We should know the science behind and peek into the library code to appreciate the security of the library code and be able to find work arounds when we do run into bugs and issues. – Saptarshi Basu May 19 '19 at 01:36
  • I agree completely! The majority of my career has been at Startups. Wearing many hats you typically need to excel at being a generalist which implies you can't be a specialist at everything. Knowing the high level approach does indeed help if you need to dig into the implementation details for some reason. As for avoiding strings I figured you would use the buffer interface, but as I thought there are situations you may need to expose to a string. Perhaps Wasm could avoid some of the GC uncertainty in some cases. However, there are unavoidable situations when communicating with clients. – Matthew Sanders May 20 '19 at 17:03
  • 4
    I am getting `Error: Unsupported state or unable to authenticate data`, does anyone have a fix for this? – Abana Clara Nov 19 '19 at 08:26
  • Not practical at all. As soon as the program stops running IV is lost along with all your data. – Philip Rego Oct 26 '20 at 00:10
  • @PhilipRego IV is not needed to be stored. You don't know that because you don't have the patience to read. Moreover, even if it were required, this is meant to show the best practices of encryption and not write an entire application with persistence. – Saptarshi Basu Oct 26 '20 at 02:06
  • 1
    I see now you're storing the iv in the encrypted value. – Philip Rego Oct 27 '20 at 05:10
  • 2
    In case anyone tries to port this to Typescript... there is a small problem with type interference and you will have to change one line: ` BLOCK_CIPHER: 'aes-256-gcm' as crypto.CipherCCMTypes,` This should solve your problem :) – pa1nd Nov 18 '20 at 00:49
  • I am getting `TypeError: decipher.setAuthTag is not a function`, does anyone have a fix for this? – Miko Chu Dec 19 '20 at 04:42
  • Silly me, I was using `createCipheriv` instead of `createDecipheriv` haha – Miko Chu Dec 19 '20 at 05:07
  • 1
    What are some best practices for rotating the key and saving it for existing encrypted records? The example here auto-creates the key but this would disappear after the unit test execution is complete – AliAvci Mar 02 '22 at 23:15
  • My question isn't directly related. It's discussed here: https://security.stackexchange.com/questions/198324/rotating-encryption-keys-how-does-it-work – AliAvci Mar 02 '22 at 23:23
  • I'm not good about this but ... Is the numbers `-16`, and `12` in `.slice()` calls can be replaced with `ALGORITHM.AUTH_TAG_BYTE_LEN`, and `ALGORITHM.IV_BYTE_LEN`? – vee Feb 06 '23 at 01:19
31

An update to @mak answer, crypto.createCipher and crypto.createDecipher has been deprecated. Latest working code would be:

var crypto = require("crypto");
var algorithm = "aes-192-cbc"; //algorithm to use
var secret = "your-secret-key";
const key = crypto.scryptSync(secret, 'salt', 24); //create key
var text= "this is the text to be encrypted"; //text to be encrypted

const iv = crypto.randomBytes(16); // generate different ciphertext everytime
const cipher = crypto.createCipheriv(algorithm, key, iv);
var encrypted = cipher.update(text, 'utf8', 'hex') + cipher.final('hex'); // encrypted text

const decipher = crypto.createDecipheriv(algorithm, key, iv);
var decrypted = decipher.update(encrypted, 'hex', 'utf8') + decipher.final('utf8'); //deciphered text
console.log(decrypted);
Willian
  • 3,011
  • 1
  • 15
  • 38
Bhumij Gupta
  • 369
  • 3
  • 6
  • Hi good day, is var text = '...' is the secret key right? – Aljohn Yamaro Aug 11 '20 at 05:42
  • @AljohnYamaro text refers to the plain text string that needs to be encrypted. The secret key is `key` generated using `password` as base – Bhumij Gupta Aug 11 '20 at 12:58
  • Great, helpful answer! I'd like to add that a random IV can be used instead of the static one. So, `iv = Buffer.alloc(...)` can be changed to `iv = crypto.randomBytes(16)`, for a different hash each time, hence defending against any rainbow-table attack. – roshnet Aug 24 '20 at 09:40
  • 2
    Not practical because you're not saving iv for each encrypted value. – Philip Rego Oct 26 '20 at 00:12
  • 1
    If you are storing `encrypted` and `iv` for later decryption, you also need to store the `authTag`. Fetch it via `authTag = cipher.getAuthTag()` and apply it via `decipher.setAuthTag(authTag)`. Without this piece, I was getting failures on `decipher.final('utf8')`. See: https://github.com/nodejs/help/issues/1034 – WGriffing Mar 10 '21 at 20:07
19

While this has been answered correctly, a good pattern to use the crypto library is within a class wrapper, which I have copy/pasted over the years into various projects.

const crypto = require("crypto");

class Encrypter {
  constructor(encryptionKey) {
    this.algorithm = "aes-192-cbc";
    this.key = crypto.scryptSync(encryptionKey, "salt", 24);
  }

  encrypt(clearText) {
    const iv = crypto.randomBytes(16);
    const cipher = crypto.createCipheriv(this.algorithm, this.key, iv);
    const encrypted = cipher.update(clearText, "utf8", "hex");
    return [
      encrypted + cipher.final("hex"),
      Buffer.from(iv).toString("hex"),
    ].join("|");
  }

  dencrypt(encryptedText) {
    const [encrypted, iv] = encryptedText.split("|");
    if (!iv) throw new Error("IV not found");
    const decipher = crypto.createDecipheriv(
      this.algorithm,
      this.key,
      Buffer.from(iv, "hex")
    );
    return decipher.update(encrypted, "hex", "utf8") + decipher.final("utf8");
  }
}
// Usage

const encrypter = new Encrypter("secret");

const clearText = "adventure time";
const encrypted = encrypter.encrypt(clearText);
const dencrypted = encrypter.dencrypt(encrypted);

console.log({ worked: clearText === dencrypted });
expelledboy
  • 2,033
  • 18
  • 18
  • Hello Expelledboy. Im using your code, but every time I run it it generates a different result when encrypting, which makes it difficult to encrypt again when saving a password encrypted. Any suggestions? Thanks. – Danielle Apr 13 '21 at 03:00
  • @Danielle The purpose of the IV is to randomize the generated result, this is desired. If you want to compare the generated result you need to decrypt it, else look into hashing, or the now depreciated `crypto.createCipher/2` used in the top answer – expelledboy Apr 22 '21 at 20:25
  • Hey, I am using your code but I am getting `Invalid key length` error. – TheWhiteFang Aug 15 '21 at 05:31
  • @TheWhiteFang inspect your encrypted text, its likely being modified. You could also print the variable `encrypted` and `iv` in the `decrypt/1` function to debug – expelledboy Aug 17 '21 at 12:37
  • I was using `aes256` and when I switched to `aes-192-cbc` it worked. From what I've read in the documentation I could use any method that is supported by OpenSSL. Do I have to add some more code for `aes256`? – TheWhiteFang Aug 17 '21 at 14:21
  • 1
    @TheWhiteFang If you are using `aes256`, you likely need to change the key length specified in scryptSync to 32. – CookieEater Dec 24 '21 at 13:36
6

Accepted ansewr was right but there are few changes as createCipher and createDecipher is deprecated.

In new methods createCipheriv and createDecipheriv iv value is require and iv value length must be 128 bit and key must be 256 bit.

code sample

const crypto = require('crypto');
const assert = require('assert');

let algorithm = 'aes256'; // or any other algorithm supported by OpenSSL
let key = 'ExchangePasswordPasswordExchange'; // or any key from .env
let text = 'I love kittens';
let iv = crypto.randomBytes(8).toString('hex'); // or you can add static value from .env

let cipher = crypto.createCipheriv(algorithm, key, iv);  
let encrypted = cipher.update(text, 'utf8', 'hex') + cipher.final('hex');
let decipher = crypto.createDecipheriv(algorithm, key, iv);
let decrypted = decipher.update(encrypted, 'hex', 'utf8') + decipher.final('utf8');

assert.equal(decrypted, text);
Amir Achhodi
  • 707
  • 7
  • 12
3

Here's a simplified version of the answer posted by Saptarshi Basu:

Changes:

  • Explicitly import Buffer from the buffer module
  • Remove unnecessary variable declarations
  • Convert once modified let variables into const variables (or omit them altogether)
  • Convert module.exports into a single object
  • Move exports.x = x = (...) declarations to the module.exports object
  • Simplify and/or reduce documentation for the ALGORITHM object

Code:

const crypto = require("crypto");
const { Buffer } = require("buffer");

const ALGORITHM = {
  // GCM is an authenticated encryption mode that not only provides confidentiality but also provides integrity in a secured way
  BLOCK_CIPHER: "aes-256-gcm",
  // 128 bit auth tag is recommended for GCM
  AUTH_TAG_BYTE_LEN: 16,
  // NIST recommends 96 bits or 12 bytes IV for GCM to promote interoperability, efficiency, and simplicity of design
  IV_BYTE_LEN: 12,
  // NOTE: 256 (in algorithm name) is key size (block size for AES is always 128)
  KEY_BYTE_LEN: 32,
  // to prevent rainbow table attacks
  SALT_BYTE_LEN: 16
};

module.exports = {
  getRandomKey() {
    return crypto.randomBytes(ALGORITHM.KEY_BYTE_LEN);
  },

  // to prevent rainbow table attacks
  getSalt() {
    return crypto.randomBytes(ALGORITHM.SALT_BYTE_LEN);
  },

  /**
   *
   * @param {Buffer} password - The password to be used for generating key
   *
   * To be used when key needs to be generated based on password.
   * The caller of this function has the responsibility to clear
   * the Buffer after the key generation to prevent the password
   * from lingering in the memory
   */
  getKeyFromPassword(password, salt) {
    return crypto.scryptSync(password, salt, ALGORITHM.KEY_BYTE_LEN);
  },

  /**
   *
   * @param {Buffer} messagetext - The clear text message to be encrypted
   * @param {Buffer} key - The key to be used for encryption
   *
   * The caller of this function has the responsibility to clear
   * the Buffer after the encryption to prevent the message text
   * and the key from lingering in the memory
   */
  encrypt(messagetext, key) {
    const iv = crypto.randomBytes(ALGORITHM.IV_BYTE_LEN);
    const cipher = crypto.createCipheriv(ALGORITHM.BLOCK_CIPHER, key, iv, {
      authTagLength: ALGORITHM.AUTH_TAG_BYTE_LEN
    });
    let encryptedMessage = cipher.update(messagetext);
    encryptedMessage = Buffer.concat([encryptedMessage, cipher.final()]);
    return Buffer.concat([iv, encryptedMessage, cipher.getAuthTag()]);
  },

  /**
   *
   * @param {Buffer} ciphertext - Cipher text
   * @param {Buffer} key - The key to be used for decryption
   *
   * The caller of this function has the responsibility to clear
   * the Buffer after the decryption to prevent the message text
   * and the key from lingering in the memory
   */
  decrypt(ciphertext, key) {
    const authTag = ciphertext.slice(-16);
    const iv = ciphertext.slice(0, 12);
    const encryptedMessage = ciphertext.slice(12, -16);
    const decipher = crypto.createDecipheriv(ALGORITHM.BLOCK_CIPHER, key, iv, {
      authTagLength: ALGORITHM.AUTH_TAG_BYTE_LEN
    });
    decipher.setAuthTag(authTag);
    const messagetext = decipher.update(encryptedMessage);
    return Buffer.concat([messagetext, decipher.final()]);
  }
};

Keep in mind that although simplified, this code is supposed to be functionally identical to Saptarshi Basu's code.

Good luck.

Malekai
  • 4,765
  • 5
  • 25
  • 60
1

The simplest way to achieve this is by using a package called cryptr.

It can be done very quick, like:

// npm install cryptr

const Cryptr = require('cryptr');
const cryptr = new Cryptr('myTotallySecretKey');

const encryptedString = cryptr.encrypt('bacon');
const decryptedString = cryptr.decrypt(encryptedString);

console.log(encryptedString); // 2a3260f5ac4754b8ee3021ad413ddbc11f04138d01fe0c5889a0dd7b4a97e342a4f43bb43f3c83033626a76f7ace2479705ec7579e4c151f2e2196455be09b29bfc9055f82cdc92a1fe735825af1f75cfb9c94ad765c06a8abe9668fca5c42d45a7ec233f0
console.log(decryptedString); // bacon

Credits for Maurice Butler that built this lib.

Willian
  • 3,011
  • 1
  • 15
  • 38
0

For multiple value encriptions in same page, we need to create separate Cipheriv like below with static iv:

const iv = 'xxxx';   /* replace with your iv */

const cipher1 = crypto.createCipheriv(algorithm, key, iv);
var encrypted1 = cipher1.update(val1, 'utf8', 'hex') + cipher1.final('hex');            // encrypted text
                    
const cipher2 = crypto.createCipheriv(algorithm, key, iv);
var encrypted2 = cipher2.update(val2, 'utf8', 'hex') + cipher2.final('hex');        // encrypted text
                    
const cipher3 = crypto.createCipheriv(algorithm, key, iv);
var encrypted3 = cipher3.update(val3, 'utf8', 'hex') + cipher3.final('hex');        // encrypted text
Roopak A Nelliat
  • 2,009
  • 3
  • 19
  • 26
0

This helped me for TypeScript and aes256 using createCipheriv. Ref.

Encrypt.ts

import * as crypto from "crypto";

export class Encrypter {
  static algorithm = "aes256";
  static key = crypto.scryptSync("<Your-Secret-Key>", "salt", 32);

  static encrypt(clearText) {
    const iv = crypto.randomBytes(16);
    try {
      const cipher = crypto.createCipheriv(
        Encrypter.algorithm,
        Encrypter.key,
        iv
      );
      const encrypted = cipher.update(clearText, "utf8", "hex");
      return [
        encrypted + cipher.final("hex"),
        Buffer.from(iv).toString("hex"),
      ].join("|");
    } catch (error) {
      return error;
    }
  }

  static decrypt(encryptedText) {
    try {
      const [encrypted, iv] = encryptedText.split("|");
      if (!iv) throw new Error("IV not found");
      const decipher = crypto.createDecipheriv(
        Encrypter.algorithm,
        Encrypter.key,
        Buffer.from(iv, "hex")
      );
      return decipher.update(encrypted, "hex", "utf8") + decipher.final("utf8");
    } catch (error) {
      return error;
    }
  }
}

Usage:

//Encrypt
const encryptedPassword = Encrypter.encrypt("Password");

//Decrypt, Note: Here you need to provide encrypted value, to decrypt it
const decryptedPassword = Encrypter.decrypt(encryptedPassword);
Mohammad Zaid Pathan
  • 16,304
  • 7
  • 99
  • 130
-3
var crypto = require('crypto'),
algorithm = 'aes-256-ctr',
password = 'RJ23edrf';

//Here "aes-256-cbc" is the advance encryption standard we are using for encryption.

function encrypt(text){
    var cipher = crypto.createCipher(algorithm,password)
    var crypted = cipher.update(text,'utf8','hex')
    crypted += cipher.final('hex');
    return crypted;
}


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

var salt = uuid.v4()

var e = encrypt();
console.log(e);
var d = decrypt(e);
console.log(d);
Shashwat Gupta
  • 5,071
  • 41
  • 33