Encrypt data on angular decrypt on Nodejs - node.js

What's the way of doing this? I tried using CryptoJS on angular and Crypto Module on node, without success I keep getting description error
Angular encrypt method :
_rsaEnc(p) {
var e = new JSEncrypt();
const key = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDlOJu6TyygqxfWT7eLtGDwajtNFOb9I5XRb6khyfD1Yt3YiCgQWMNW649887VGJiGr/L5i2osbl8C9+WJTeucF+S76xFxdU6jE0NQ+Z+zEdhUTooNRaY5nZiu5PgDB0ED/kaskaskKAS';
e.setPublicKey(key);
return e.encrypt(p);
}
Node decrypt method
privK = {
key: fs.readFileSync('./app/services/private.pem').toString(),
passphrase: 'xxxxxx'
};
var buf = Buffer.from(base64Data, 'base64');
origData = crypto.privateDecrypt(privK, buf);
return origData.toString('utf-8');
error:
Error: error:040A1079:rsa
routines:RSA_padding_check_PKCS1_OAEP_mgf1:oaep decoding error

Ended up changing the angular lib to jsencrypt, CryptoJS doesnt support RSA, and changed node lib to node-rsa to set the encryption scheme to pkcs1 with
myDecrypter.setOptions({encryptionScheme: 'pkcs1'});

Related

I am trying to convert this crypto encrypt and decrypt js code into typescript for an Angular project

I am using crypto in node.js for encryption and decryption of user credentials, which works fine. On the other hand, I have to use the same approach to getting the exact result of encryption and decryption in Angular. As it's confirmed that crypto is not working in Angular. I would like to know any way to achieve the required result.
I added npm i --save-dev #types/node but this is not working for me. Also added crypto but the module was not found. I also use npm crypto-js encryption is done but not the same as my js method.
This is my js file code, I need to implement the same method in my Angular project:
'use strict';
const crypto = require('crypto');
const IV_LENGTH = 16;
encrypt(text: any, key: any) {
console.log('Before Encrption Data is-->', text, key)
let iv = crypto.randomBytes(this.IV_LENGTH);
let cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(key), iv);
let encrypted = cipher.update(text);
encrypted = Buffer.concat([encrypted, cipher.final()]);
let returnable = iv.toString('hex') + ':' + encrypted.toString('hex');
return returnable;
}
decrypt(text: any, key: any) {
let textParts = text.split(':');
let iv = Buffer.from(textParts.shift(), 'hex');
let encryptedText = Buffer.from(textParts.join(':'), 'hex');
let decipher = crypto.createDecipheriv('aes-256-cbc', Buffer.from(key), iv);
let decrypted = decipher.update(encryptedText);
decrypted = Buffer.concat([decrypted, decipher.final()]);
return decrypted.toString();
}
When I added crypto this type of error occurred:

How to decrypt a value in frontend which is encrypted in the backend (nodejs)?

Backend developers have encrypted a value in nodejs using crypto module. The code is shown below:
const _encrypt = async function(text){
var cipher = crypto.createCipher('aes-256-cbc','123|a123123123123123#&12')
var crypted = cipher.update(text,'utf8','hex')
crypted += cipher.final('hex');
console.log("in generic function....encrpted val", crypted)
return crypted;
}
I need to decrypt this value in the front end (Angular). So I tried decrypting like below:
let bytes = CryptoJS.AES.decrypt("e0912c26238f29604f5998fa1fbc78f6",'123|a123123123123123#&12');
if(bytes.toString()){
let m = JSON.parse(bytes.toString(CryptoJS.enc.Utf8));
console.log("data ",m);
}
using hardcoded value. But Im getting Error: Malformed UTF-8 data error. Can anybody please tell me how to decrypt this in angular side?
This is a tricky enough one.. the crypto.createCipher function creates a key and IV from the password you provide (See the createCipher documentation for details).
This is implemented using the OpenSSL function EVP_BytesToKey.
A JavaScript implementation is available here: openssl-file.. we'll use this to get a key and IV from the password.
So there are two steps here:
Get a key and IV from your password.
Use these with Crypto.js to decode your encoded string.
Step 1: Get key and IV (Run in Node.js )
const EVP_BytesToKey = require('openssl-file').EVP_BytesToKey;
const result = EVP_BytesToKey(
'123|a123123123123123#&12',
null,
32,
'MD5',
16
);
console.log('key:', result.key.toString('hex'));
console.log('iv:', result.iv.toString('hex'));
Step 2: Decrypt string:
const encryptedValues = ['e0912c26238f29604f5998fa1fbc78f6', '0888e0558c3bce328cd7cda17e045769'];
// The results of putting the password '123|a123123123123123#&12' through EVP_BytesToKey
const key = '18bcd0b950de300fb873788958fde988fec9b478a936a3061575b16f79977d5b';
const IV = '2e11075e7b38fa20e192bc7089ccf32b';
for(let encrypted of encryptedValues) {
const decrypted = CryptoJS.AES.decrypt({ ciphertext: CryptoJS.enc.Hex.parse(encrypted) }, CryptoJS.enc.Hex.parse(key), {
iv: CryptoJS.enc.Hex.parse(IV),
mode: CryptoJS.mode.CBC
});
console.log('Ciphertext:', encrypted);
console.log('Plain text:', decrypted.toString(CryptoJS.enc.Utf8));
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.min.js"></script>
Note that if you change the password you need to generate a new key and iv using EVP_BytesToKey.
I should note that createCipher is now deprecated, so use with caution. The same applies to EVP_BytesToKey.

NodeJS crypto RSA, not compatible with Elixir/Erlang PublicKey?

I’m having trouble trying to decrypt in Elixir (using ExCrypto - which is a only a wrapper around crypto and public_key) encrypted by NodeJS Crypto.
Here’s what works :
encrypt_public in NodeJS -> decrypt_private NodeJS (Works)
encrypt_public in Elixir -> decrypt_pricate in Elixir (Works)
But :
encrypt_public in NodeJS -> decrypt_private in Elixir (Does Not Work)
It seems that an encrypt_public from Node, can’t be decrypted by a decrypt_private in Elixir.
I even tried the hard way directly with the Erlang module public_key, it gives me the same result.
Here’s what I tried :
var fs = require("fs")
var crypto = require("crypto")
var rsa_key = fs.readFileSync('./priv/public.key').toString()
var rsa_priv = fs.readFileSync('./priv/private.key').toString()
var buffer = Buffer.from("Hello world")
var encrypted_auth = crypto.publicEncrypt({key: rsa_key}, buffer)
console.log("copy/paste this in iex: ", encrypted_auth.toString("Base64"))
var crypted_buffer = Buffer.from(encrypted_auth)
var decrypted_auth = crypto.privateDecrypt({key: rsa_priv, passphrase: "my_pass_phrase"}, crypted_buffer)
console.log("--- Res: ", decrypted_auth.toString())
But as soon as you copy/paste the Base64 generated in Node Here’s what I get :
key = ExPublicKey.load!("./priv/private.key", "my_pass_phrase")
cipher = "PASTED BASE64 FROM NODE"
ExPublicKey.decrypt_private(cipher, key)
returns :error
I have suspected the rsa padding to be different, but it doesn’t seems to be that… Does anyone have a clue ?
There were 2 issues
The padding by default in Node is : RSA_PKCS1_OAEP_PADDING
while the default one is erlang is : rsa_pkcs1_padding
the solution is to modify the padding in Node :
var encrypted_auth = crypto.publicEncrypt({key: rsa_key, padding: crypto.constants.RSA_PKCS1_PADDING}, buffer)
The second issue, was that EXPublicKey was trying to Base.url_decode64 while the Base64 generated by Node is not url safe
To fix that :
ExPublicKey.decrypt_private(cipher, key, url_safe: false)

Using asymmetric algorithm in angular

I need to apply asymmetric encryption for large JSON files on client-side to transfer them to the cloud. These files can include images in the base64 format. I'm working with Angular-cli and tried to use the library crypto-browserify but can't encrypt large files. Then I tried the node-rsa library and my program works in the console, but does not work in Angular.
const NodeRSA = require('node-rsa');
let key = new NodeRSA('-----BEGIN PUBLIC KEY-----\n'+
'-----END PUBLIC KEY-----');
let f = '{"data":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAA ..."}';
let encrypt_data = key.encrypt(f, 'base64');
console.log(encrypt_data);
A solution is found in using node-rsa through browserify:
browserify -r node-rsa --standalone CryptRSA > rsa-brow.js
Then added to index.html
<script src="assets/js/rsa-brow.js"></script>
Then using in Angular
declare var CryptRSA: any;
#Injectable()
export class MyService {
encrypt(file_content: string){
let key = new CryptRSA(publicKey);
let buffer = Buffer.from(file_content, 'utf-8');
return key.encrypt(buffer, 'base64');
}
}

Encrypting data with a public key in Node.js

I need to encrypt a string using a public key (.pem file), and then sign it using a private key (also a .pem).
I am loading the .pem files fine:
publicCert = fs.readFileSync(publicCertFile).toString();
But after hours of scouring Google, I can't seem to find a way to encrypt data using the public key. In PHP I simply call openssl_public_encrypt(), but I don't see any corresponding function in Node.js or in any modules.
A library is not necessary. Enter crypto.
Here's a janky little module you could use to encrypt/decrypt strings with RSA keys:
var crypto = require("crypto");
var path = require("path");
var fs = require("fs");
var encryptStringWithRsaPublicKey = function(toEncrypt, relativeOrAbsolutePathToPublicKey) {
var absolutePath = path.resolve(relativeOrAbsolutePathToPublicKey);
var publicKey = fs.readFileSync(absolutePath, "utf8");
var buffer = Buffer.from(toEncrypt);
var encrypted = crypto.publicEncrypt(publicKey, buffer);
return encrypted.toString("base64");
};
var decryptStringWithRsaPrivateKey = function(toDecrypt, relativeOrAbsolutePathtoPrivateKey) {
var absolutePath = path.resolve(relativeOrAbsolutePathtoPrivateKey);
var privateKey = fs.readFileSync(absolutePath, "utf8");
var buffer = Buffer.from(toDecrypt, "base64");
var decrypted = crypto.privateDecrypt(privateKey, buffer);
return decrypted.toString("utf8");
};
module.exports = {
encryptStringWithRsaPublicKey: encryptStringWithRsaPublicKey,
decryptStringWithRsaPrivateKey: decryptStringWithRsaPrivateKey
}
I would recommend not using synchronous fs methods where possible, and you could use promises to make this better, but for simple use cases this is the approach that I have seen work and would take.
I tested this in Node.js 10, you can use encrypt/decrypt functions (small changes on Jacob's answer):
const crypto = require('crypto')
const path = require('path')
const fs = require('fs')
function encrypt(toEncrypt, relativeOrAbsolutePathToPublicKey) {
const absolutePath = path.resolve(relativeOrAbsolutePathToPublicKey)
const publicKey = fs.readFileSync(absolutePath, 'utf8')
const buffer = Buffer.from(toEncrypt, 'utf8')
const encrypted = crypto.publicEncrypt(publicKey, buffer)
return encrypted.toString('base64')
}
function decrypt(toDecrypt, relativeOrAbsolutePathtoPrivateKey) {
const absolutePath = path.resolve(relativeOrAbsolutePathtoPrivateKey)
const privateKey = fs.readFileSync(absolutePath, 'utf8')
const buffer = Buffer.from(toDecrypt, 'base64')
const decrypted = crypto.privateDecrypt(
{
key: privateKey.toString(),
passphrase: '',
},
buffer,
)
return decrypted.toString('utf8')
}
const enc = encrypt('hello', `public.pem`)
console.log('enc', enc)
const dec = decrypt(enc, `private.pem`)
console.log('dec', dec)
For the keys you can generate them with
const { writeFileSync } = require('fs')
const { generateKeyPairSync } = require('crypto')
function generateKeys() {
const { privateKey, publicKey } = generateKeyPairSync('rsa', {
modulusLength: 4096,
publicKeyEncoding: {
type: 'pkcs1',
format: 'pem',
},
privateKeyEncoding: {
type: 'pkcs1',
format: 'pem',
cipher: 'aes-256-cbc',
passphrase: '',
},
})
writeFileSync('private.pem', privateKey)
writeFileSync('public.pem', publicKey)
}
The updated public/private decrypt and encryption module is URSA. The node-rsa module is outdated.
This Node module provides a fairly complete set of wrappers for the
RSA public/private key crypto functionality of OpenSSL.
npm install ursa
Use the node-rsa module. Here's a link to the test.js file that demonstrates usage.
TL;DR: URSA is your best bet. It's really funky that this doesn't come standard with Node.js' crypto.
Every other solutions I found either doesn't work in Windows or aren't actually encryption libraries. URSA, recommended by Louie, looks like the best bet. If you don't care about Windows, you're even more golden.
Note on Ursa: I had to install OpenSSL along with something called "Visual C++ 2008 Redistributables" in order to get the npm install to work. Get that junk here: http://slproweb.com/products/Win32OpenSSL.html
The breakdown:
Annoying additional manual installation steps for Windows
https://github.com/Obvious/ursa - probably the best of the lot
Not compatible with Windows
https://npmjs.org/package/rsautl - says BADPLATFORM
https://github.com/katyo/node-rsa - node-waf isn't available on Windows
https://github.com/paspao/simple_rsa_encrypt - unistd.h isn't on windows
https://npmjs.org/package/pripub - large amounts of linker errors, also not on GitHub
Not encryption libraries
https://github.com/substack/secure-peer
https://github.com/substack/rsa-json - just generates keys, but doesn't use them
https://github.com/substack/rsa-unpack - just unpacks PEM strings
This is literally all I could find.
This is not supported natively by Node.js version v0.11.13 or below, but it seems that next version of Node.js (a.k.a v0.12) will support this.
Here is the clue: https://github.com/joyent/node/blob/v0.12/lib/crypto.js#L358
See crypto.publicEncrypt and crypto.privateDecrypt
Here is the future documentation for this
https://github.com/joyent/node/blob/7c0419730b237dbfa0ec4e6fb33a99ff01825a8f/doc/api/crypto.markdown#cryptopublicencryptpublic_key-buffer

Resources