Use node crypto in angular 9

10,082

Solution 1

After 3-4 days I am finally able to resolve this.

  1. I installed crypto-browserify.
  2. Delete node_modules folder and then again installed all dependencies by using npm-install

crypto-browserify provides same features as crypto

Solution 2

I recently acheived this in my MEAN Stack app. After installing crypto-js with following command:

npm i crypto-js --save

Following service in Angular-9 which can be used through out the project for encryption and decryption.

import { Injectable } from '@angular/core';
import * as CryptoJS from 'crypto-js';
import { environment } from 'src/environments/environment';

@Injectable({
  providedIn: 'root'
})
export class CryptoJsService {

  constructor() { }

  get jsonFormatter() {
    return {
      stringify: (cipherParams: any) => {
        const jsonObj = { ct: cipherParams.ciphertext.toString(CryptoJS.enc.Base64), iv: null, s: null };
        if (cipherParams.iv) {
          jsonObj.iv = cipherParams.iv.toString();
        }
        if (cipherParams.salt) {
          jsonObj.s = cipherParams.salt.toString();
        }
        return JSON.stringify(jsonObj);
      },
      parse: (jsonStr) => {
        const jsonObj = JSON.parse(jsonStr);
        // extract ciphertext from json object, and create cipher params object
        const cipherParams = CryptoJS.lib.CipherParams.create({
          ciphertext: CryptoJS.enc.Base64.parse(jsonObj.ct)
        });
        if (jsonObj.iv) {
          cipherParams.iv = CryptoJS.enc.Hex.parse(jsonObj.iv);
        }
        if (jsonObj.s) {
          cipherParams.salt = CryptoJS.enc.Hex.parse(jsonObj.s);
        }
        return cipherParams;
      }
    };
  }
  /* Method for Encryption */
  encrypt(value: any) {
    const key =  environment.crypto_js_key; // SECRET KEY FOR ENCRYPTION 
    value = value instanceof String ? value : JSON.stringify(value);
    const encrypted = CryptoJS.AES.encrypt(value,key, 
      { format: this.jsonFormatter, mode: CryptoJS.mode.CBC }).toString();
    return encrypted;
  }

  /* Method for Decryption */
  decrypt(value: any): any {
    const key = environment.crypto_js_key; //SECRET KEY FOR ENCRYPTION
    const decrypted = CryptoJS.AES.decrypt(value, key, {format: this.jsonFormatter }).toString(CryptoJS.enc.Utf8);
    return JSON.parse(decrypted);
  }
}

In Nodejs, following utility could be used through out the app:

var CryptoJS = require('crypto-js');
var config = require('../config/environment');

module.exports.encrypt = function(value){
  var JsonFormatter = {
    stringify: function(cipherParams){
      var jsonObj = { ct: cipherParams.ciphertext.toString(CryptoJS.enc.Base64) };
      if (cipherParams.iv) {
        jsonObj.iv = cipherParams.iv.toString();
      }
      if (cipherParams.salt) {
        jsonObj.s = cipherParams.salt.toString();
      }
      return JSON.stringify(jsonObj);
    },
    parse: function(jsonStr) {
      var jsonObj = JSON.parse(jsonStr);
      // extract ciphertext from json object, and create cipher params object
      var cipherParams = CryptoJS.lib.CipherParams.create({
        ciphertext: CryptoJS.enc.Base64.parse(jsonObj.ct)
      });
      if (jsonObj.iv) {
        cipherParams.iv = CryptoJS.enc.Hex.parse(jsonObj.iv);
      }
      if (jsonObj.s) {
        cipherParams.salt = CryptoJS.enc.Hex.parse(jsonObj.s);
      }
      return cipherParams;
    }
  }
  value = value instanceof String ? value: JSON.stringify(value);
  var encrypted = CryptoJS.AES.encrypt(value, config.crypto_js_key, {
    format: JsonFormatter, mode: CryptoJS.mode.CBC
  }).toString();
  return encrypted;
}

module.exports.decrypt = function(value) {
  return CryptoJS.AES.decrypt(value, config.crypto_js_key, {format: JsonFormatter }).toString(CryptoJS.enc.Utf8);
}
Share:
10,082
Kenny
Author by

Kenny

Updated on June 04, 2022

Comments

  • Kenny
    Kenny almost 2 years

    My project was in Angular 6 and it had following lines of code

    const crypto = require('crypto-js');
    const Buffer = require('buffer').Buffer;
    const decrypt = new Buffer(data.result.encr, 'base64');
    const privatekey = Buffer.from(data.result.pk, 'base64');
    this.decrypted = crypto.privateDecrypt(privatekey, decrypt).toString('utf-8');
    return this.decrypted;
    

    Which was working fine.

    Now I migrated my code to Angular 9. And I find out that crypto has no longer support from NPM

    https://www.npmjs.com/package/crypto

    It says that I have to use inbuild library of crypto. But I have no idea how to use it.

    I thought crypto-js would help me. But it didn't.

    If someone knows how to use crypto in Angular 9 or how to convert upper lines for crypto-js then it would be great.

    Note: Encryption is happening on server side using crypto only as they have nodejs.

    Thanks in advance.

    • LogicBlower
      LogicBlower almost 4 years
      what is your node and npm version ?
    • Kenny
      Kenny almost 4 years
      @LogicBlower node version12.14.1 & npm version 6.13.4
    • Ivaylo Ivanov
      Ivaylo Ivanov almost 4 years
      The nodejs crypto.privateDecrypt uses RSA and crypto-js has no support for RSA. You might need to have a look at npm libraries like js-crypto-rsa or node-rsa
    • Kenny
      Kenny almost 4 years
      @IvayloIvanov Thanks for your input will check and revert back
  • Yonz
    Yonz over 3 years
    For Angular 11, this worked but needed this to be added below devDependencies: ``` "browser": { "crypto": false } ``` Otherwise you will get the error: Warning: ./node_modules/crypto-js/core.js Module not found: Error: Can't resolve 'crypto' in '/Users/Innov8/x/i8/git/allspark/spark-fe/node_modules/crypt‌​o-js'
  • Yonz
    Yonz over 3 years
    Tried multiple times but this doesn't work for Angular 11. After Angular 6 process, browser and main were removed. Even after adding a script tag, the pdkf2 ends up importing process.version.split which doesn't exits. You can try continuing down this rabbit hole but it comes down with the package trying to operate as server mode. in pbkdf2/lib/default-ecoding.js thinks its running in server mode: {code}var defaultEncoding /* istanbul ignore next */ if (process.browser) { ... } else if (process.version) { var pVersionMajor = parseInt(process.version.split('.')[0].slice(1), 10)
  • Gurnard
    Gurnard about 3 years
    so @yfeleke what solution did you come up with when working with 11? I am facing the same issue
  • Yonz
    Yonz about 3 years
    ended up using crypto js: import * as CryptoJS from 'crypto-js'; and then in package.json "browser": { "crypto": false }