RSA library with angular

2019-01-28 04:09发布

问题:

Hello I am trying to implement encryption in my application. I am using angular (angular-4) for the frontend and node js for the backend. Communication is done through socket.io through custom commands. But basically what I am stuck at is finding an appropriate library for RSA encryption in client side. client will first request server for an RSA public key. Server responds with key but now I cannot find any library suitable to encrypt data with RSA using this public key. I have tried node-rsa. Following is a code sn

import * as NodeRSA from 'node-rsa';

@Injectable()

export class SecurityService {
    RSA: any
    initializeRSA(key: string) {
        this.RSA = new NodeRSA();
        this.RSA.importKey(key)
        console.log(this.RSA.encrypt('Hello World'));
    }

But I am receiving this error.

Error during encryption. Original error: TypeError: crypt.createHash is not a function
at NodeRSA.webpackJsonp.../../../../node-rsa/src/NodeRSA.js.module.exports.NodeRSA.$$encrypt

Help would be very much appreciated.

回答1:

Please Find Solution Plunker here:

JSEncrypt with angular

https://plnkr.co/edit/sEPK1DcynMphJnGziUVX

I have used JSEncrypt v2.3.0 Lib for same.

Implementation

Add JSEncrypt Lib javascript file in Asset Folder of Angular Project. Add script in index.html

<script src="jsencrypt.js"></script>

So, It will available at all Component.

declare JSEncrypt at your component file where you want to use it.

declare var JSEncrypt: any;

Inside class declare variable

decrypt = new JSEncrypt();
const privatekey = Private Key goes here;
const publickey = Public key goes here;
const decryptDataRow = Decrypted data string;
this.decrypt.setPrivateKey(privatekey);
this.decryptdata = this.decrypt.decrypt(decryptDataRow);

decryptdata contain result string



回答2:

What you can do if you want to stay with the very good node-rsa library it to eject ng-cli from your project and configure webpack to automatically polyfill the nodejs crypto module with the crypto-browserify library.

First, eject ng-cli from your project (you will need to run yarn build or npm run build to build your project and you won't be able anymore to use ng build) :

ng eject

Then you need to add this data to the webpack.config.js file created by the ejection process :

"node": {
    ...
    "crypto": true,
    ...
}

This will tell webpack to polyfill the crypto module.

I will soon dive into how to keep ng-cli and have a correct polyfilling behavior...



回答3:

I used CryptoJS for AES encoding. And, node-forge for RSA encoding.

Part 1: npm install --save node-forge npm install --save crypto-js npm install --save @types/crypto-js npm install --save @types/node-forge

import { Injectable } from '@angular/core';
import * as forge from 'node-forge';
import * as CryptoJS from 'crypto-js';

/*
* forge: For RSA encryption
* CryptoJS: For AES encryption
*/
export interface AESKeys {
    iv: string;
    key: string;
}

@Injectable()
export class MyEncryptService {

    constructor() {}
    /**
     * @param randomWordArray
     * AES Key or IV generated in this service as Hex string
     * @param pemKey
     * the Public Key from "get_rsa_key" endpoint (separate http service)
     * @returns
     * a RSA encrypted random key/iv
     */
    public getBase64Encrypted(randomWordArray, pemKey): string {
        const pk = forge.pki.publicKeyFromPem(pemKey);
        return forge.util.encode64(pk.encrypt(forge.util.hexToBytes(randomWordArray)));
    }

    /**
     * @param text
     * field input text
     * @param randomKey
     * random key generated from word array
     * @param randomIv
     * random iv generated from word array
     * @returns
     * encrypted text
     */
    public encrypted(text, randomKey, randomIv): string {
        const cipherText: any = CryptoJS.AES.encrypt(text, randomKey, {
            iv: randomIv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.NoPadding
        });
        return cipherText.toString();
    }

    /**
     * @param wordLength
     * normally: IV = 16 or Key = 32
     * @returns
     * randomly generated 128bit (IV) or 256bit (Key) word array
     */
    public getWordArray(wordLength): string {
        return CryptoJS.lib.WordArray.random(wordLength);
    }

}