encrypt long string with node js module crypto - node.js

i am trying to encrypt long tokens but i get error
Error: Trying to add data in unsupported state
import * as crypto from 'crypto';
import { APP_CONFIG } from "#app-config";
const algorithm = 'aes-256-cbc';
const cipher = crypto.createCipheriv(algorithm, Buffer.from(APP_CONFIG.ENCRYPTION.ENCRYPTION_KEY), APP_CONFIG.ENCRYPTION.IV);
const decipher = crypto.createDecipheriv(algorithm, Buffer.from(APP_CONFIG.ENCRYPTION.ENCRYPTION_KEY), APP_CONFIG.ENCRYPTION.IV);
class cryptoHelper {
constructor() {
}
encrypt(text) {
let encrypted = cipher.update(text);
encrypted = Buffer.concat([encrypted, cipher.final()]);
return encrypted.toString('hex');
}
decrypt(encryptedData) {
let encryptedText = Buffer.from(encryptedData, 'hex');
let decrypted = decipher.update(encryptedText);
decrypted = Buffer.concat([decrypted, decipher.final()]);
return decrypted.toString();
}
}
export const CryptoHelper = new cryptoHelper();
CryptoHelper.encrypt("long string"); // 1200 length for example
// encrypt will fail
i am trying to encrypt google auth tokens(access_token and refresh_token)
is there any way to encrypt long strings?

Related

NodeJS crypto for encrypt/decrypt

I'm working on a database with some encrypted data that was generated in ColdFusion using the code below:
key = "nQw7y6QejwGFh/SNrul20Q==";
encrypt(myText, key, "AES/CBC/PKCS5Padding", "HEX");
It generates an encrypted string like: 6F795025756EC54D60808EA98AC163D9143C2FCFEC1065FCCAB7AB0CD577E535. I can decrypt it using my code below
I managed to create my NodeJS class to decrypt this data.
const crypto = require('crypto');
const key = Buffer.from('nQw7y6QejwGFh/SNrul20Q==', 'base64');
module.exports = class Encrypt {
decryptText(text) {
try {
const ivCiphertext = Buffer.from(text, 'hex');
const iv = ivCiphertext.slice(0, 16);
const ciphertext = ivCiphertext.slice(16);
var decipher = crypto.createDecipheriv('AES-128-CBC', key, iv);
var value =
decipher.update(ciphertext, '', 'utf8') +
decipher.final('utf8');
return value;
} catch (err) {
console.log(err);
}
}
};
I'm trying to create a encrypt method in this class, to encrypt the data in the same format that it was being generated in ColdFusion.
encrypt(text) {
const iv = crypto.randomBytes(16);
let cipher = crypto.createCipheriv(
'AES-128-CBC', key, iv);
let encrypted = cipher.update(text);
encrypted = Buffer.concat([encrypted, cipher.final()]);
return encrypted.toString('hex');
}
I did the following test:
const encrypt = new Encrypt();
const test = encrypt.encrypt('803315808');
console.log(test);
console.log(encrypt.decryptText(test));
First log:
fdcec1c7098c0fc91a11ada1e849b543
Second log:
Error: error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length

encrypt data using aes-128-ecb in nodejs

I have To encrypt data using aes-128-ecb in nodejs my code is
I am using Crypto to encrypt data
const crypto = require('crypto');
const secret = '1000060000000000';
const cipher = crypto.createCipher('aes-128-ecb', secret);
const ciphertext = cipher.update('9', 'utf8', 'base64')+cipher.final('base64');
console.log("Cipher text is: " + ciphertext);
the output should be EtgITaHs6lEvEHBipj08Kg==
but the output is coming as nNzqejauQBnfiDqznGhZ0Q==
The problem here is the use of crypto.createCipher, it doesn't use the key directly, but rather a digest.
To quote the documentation:
The implementation of crypto.createCipher() derives keys using the OpenSSL function EVP_BytesToKey with the digest algorithm set to MD5, one iteration, and no salt.
If we use cipher.createCipheriv on the other hand, we can specify the key directly and it will give us the expected output.
Here's an example:
const crypto = require("crypto");
function encrypt(plainText, key, outputEncoding = "base64") {
const cipher = crypto.createCipheriv("aes-128-ecb", key, null);
return Buffer.concat([cipher.update(plainText), cipher.final()]).toString(outputEncoding);
}
function decrypt(cipherText, key, outputEncoding = "utf8") {
const cipher = crypto.createDecipheriv("aes-128-ecb", key, null);
return Buffer.concat([cipher.update(cipherText), cipher.final()]).toString(outputEncoding);
}
const key = "1000060000000000";
const plainText = "9";
const encrypted = encrypt(plainText, key, "base64");
console.log("Encrypted string (base64):", encrypted);
const decrypted = decrypt(Buffer.from(encrypted, "base64"), key, "utf8")
console.log("Decrypted string:", decrypted);
The output will be
EtgITaHs6lEvEHBipj08Kg==
It is late but will help others
You can pass any Algorithm i.e. aes-128-cbc , aes-128-ecb
Create a new file and name it as aes-service.js in service folder or anywhere in Node.js application
aes-service.js
const crypto = require('crypto');
const cryptkey = 'C51GH00SE8499727';
const iv = 'BDA30EGDH1578F81';
async function encrypt(text){
try {
var cipher = crypto.createCipheriv('aes-128-cbc',cryptkey,iv);
var crypted = cipher.update(text,'utf8','base64'); //base64 , hex
crypted += cipher.final('base64');
return crypted;
} catch (err) {
console.error('encrypt error',err);
return null;
}
}
async function decrypt(encryptdata){
//Check all Algorithms
console.log(crypto.getCiphers()); // ['aes-128-cbc', 'aes-128-ccm', ...]
try {
let decipher = crypto.createDecipheriv('aes-128-cbc',cryptkey,iv)
decipher.setAutoPadding(false)
let decoded = decipher.update(encryptdata,'base64','utf8') //base64 , hex
decoded += decipher.final('utf8')
return decoded
} catch (err) {
console.error('decrypt error',err)
return null
}
}
const AesService = {
encrypt:encrypt,
decrypt:decrypt,
}
module.exports = AesService
Node.js contorller i.e abc.controller.js
//Get aes encrypted data from node.js request
const AesService = require("./services/aes-service")
exports.getAesEncryptedDatafromReq= async (req, res) => {
try{
let decryptData = ''
try{
const buffers = [];
for await (const chunk of req) {
buffers.push(chunk);
}
const dataBuffer = Buffer.concat(buffers).toString();
const jsonParsedData = JSON.parse(dataBuffer)
decryptData = jsonParsedData.data
}catch(err){}
let decryptedData = await AesService.decrypt(decryptData)
console.log('decrypted data',decryptedData)
let sendbackdata = {
"status": 0,
"anotehr_key":[
{ "dec":"0", "asc":"1"}
]
}
sendbackdata = JSON.stringify(sendbackdata)
let encryptedData = await AesService.encrypt(sendbackdata)
//Check if encrypted performed well
// let decryptedDataAgain = await AesService.decrypt(encryptedData)
//console.log('decryptedDataAgain ',decryptedDataAgain)
return res.status(201).send({"data":encryptedData})
}catch(err){
return res.status(500)
}
}
Add route
router.post("/get/aes/encrypted/data/from/req", controller.getAesEncryptedDatafromReq)

While doing decryption using crypto, getting bad decrypt error using Node.js

I am storing information in the database in an encrypted format. When I am retrieving it from the database and applying decrypt on it, I am getting error like "bad decrypt"
Here is my code:
const crypto = require("crypto");
const key = crypto.randomBytes(32);
const iv = crypto.randomBytes(16);
function encrypt(text) {
let cipher = crypto.createCipheriv("aes-256-cbc", Buffer.from(key), iv);
let encrypted = cipher.update(text);
encrypted = Buffer.concat([encrypted, cipher.final()]);
return { iv: iv.toString("hex"), encryptedData: encrypted.toString("hex") };
}
function decrypt(text) {
let iv = Buffer.from(text.iv, "hex");
let encryptedText = Buffer.from(text.encryptedData, "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();
}
/********** following is the api **************/
exports.viewTrade = async (req, res) => {
console.log("viewTrade api ", req.query);
let maindData = [];
var hw = {
iv: "fc4ca9a17d97d7a7772449cfea3a99b8",
encryptedData: "e966509fd17785b4fe8304ef2f531806",
};
console.log(decrypt(hw));
const tradeList = await trade.find({
createdBy: req.query.id,
});
if (tradeList.length) {
for (tradeInfo of tradeList) {
// let nameInfo = tradeInfo.name;
// // let value = decrypt(nameInfo);
// console.log("name info.. ", nameInfo);
// // console.log("value.. ", value);
}
}
};
By calling the above API, it is throwing error.
When I try out your code I'm getting a error like this: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt.
This probably means that the key used to decrypt is not the same as the encryption key.
I suspect this is because the code above re-creates the key on each run.
I would suggest you use a fixed key, maybe coming from an environment variable, or secure secrets store. To test this you can just initialize your key like so:
const key = Buffer.from("232f150296ffd446fc0b39fa32d1c1d42c2e232ccd3203df729b7f3c3c63a5da2", "hex");
Then encrypt a message and see that it will decrypt correctly like so:
const encrypted = encrypt("We love Stack Overflow");
const decrypted = decrypt(encrypted);
console.log("encrypted data:", encrypted);
console.log("decrypted data:", decrypted);
You'll notice that if you copy the encrypted data from one run of the program to the next, it should work with a fixed key, but give you the bad_decrypt error if you generate the key on each run.
Key Generation code:
const key = crypto.randomBytes(32).toString("hex");

Cant decrypt data after encryption with crypto

I want to encrypt data and write it in my database. This works fine. After I get the data back from my database I want to decrypt this data, but the decryption doesn't work correctly.
I saved the string "test" in the database. The encryption works correctly and the encrypted string is
3ac5d5d6beeb44c5a58ac54e7fc0ad07ea3c819ff6489aae16d490667a309751378ae10800c072551e3a97596f3a2ae0
after i run the decrypt function i get back this:
8ea2e28e0086ef2ad22c2d7805a34111
but it should be "test"
const crypto = require("crypto");
const algorithm = "aes-256-cbc";
const key = new Buffer("11111111111111111111111111111111");
const iv = new Buffer("12345678");
module.exports = {
//my encyrpt function
encrypt(text) {
let ivstring = iv.toString("hex");
let cipher = crypto.createCipheriv(algorithm, key, ivstring);
let encrypted = cipher.update(text);
encrypted = Buffer.concat([encrypted, cipher.final()]);
// return { iv: iv.toString("hex"), encryptedData: encrypted.toString("hex") };
return encrypted.toString("hex");
},
// my decrypt data
decrypt(text) {
let ivstring = iv.toString("hex");
let encryptedText = Buffer.from(text, "hex");
let decipher = crypto.createDecipheriv(algorithm, key, ivstring);
let decrypted = decipher.update(encryptedText);
decrypted = Buffer.concat([decrypted, decipher.final()]);
return decrypted.toString();
}
};
It seems that you have applied the encryption twice:
encrypt(encrypt('test'))
// returns '3ac5d5d6beeb44c5a58ac54e7fc0ad07ea3c819ff6489aae16d490667a309751378ae10800c072551e3a97596f3a2ae0'
So you can decipher it by calling decrypt twice on the ciphertext:
const cipherText = '3ac5d5d6beeb44c5a58ac54e7fc0ad07ea3c819ff6489aae16d490667a309751378ae10800c072551e3a97596f3a2ae0'
decrypt(decrypt(cipherText))
// returns 'test'

How to encrypt and decrypt string/object in nodejs

I would like to encrypt an object then decrypt it. The encryption works very well but the decryption fails. Below my code :
crypto_ext.js
const crypto = require("crypto")
const password = "shared_key"
const algorithm = "aes256"
export const encrypt = (text) => {
if(!text) return ''
const cipher = crypto.createCipher(algorithm, password);
let crypted = cipher.update(text, 'utf-8', 'base64');
crypted += cipher.final('base64');
return crypted;
}
export const decrypt = (text) => {
if(!text) return ''
const decipher = crypto.createDecipher(algorithm, password);
let decrypted = decipher.update(text, 'base64', 'utf-8');
decrypted += decipher.final('utf-8');
return decrypted;
}
and in my test.js, I have :
import {encrypt, decrypt} from './crypto_ext.js'
let test = {key1: val1, key2: val2}
test = encrypt(JSON.stringify(test)) || test
console.log("Encrypt : ", test)
console.log("Decrypt : ", decrypt(test)) // I should have my object as string here
And this is what I'm getting as error :
Uncaught Error: unable to decrypt data
at unpad (decrypter.js:83)
at Decipher.webpackJsonp../node_modules/browserify-aes/decrypter.js.Decipher._final (decrypter.js:38)
at Decipher.webpackJsonp../node_modules/cipher-base/index.js.CipherBase._finalOrDigest (index.js:76)
at decrypt (crypto_ext.js:17)
...
Can you please tell me what I'm doing wrong ?
Method createCipher deprecated. Use createCipheriv instead.
Try to use aes192 algorithm.
Dependencies: crypto package
You can achieve encoding and decoding with below codes:-
const crypto = require('crypto');
var password = 'ojisdasjdsjabdjs';
var iv = 'kiamdksndn';
function sha1(input) {
return crypto.createHash('sha1').update(input).digest();
}
function password_derive_bytes(password, salt, iterations, len) {
var key = Buffer.from(password + salt);
for (var i = 0; i < iterations; i++) {
key = sha1(key);
}
if (key.length < len) {
var hx = password_derive_bytes(password, salt, iterations - 1, 20);
for (var counter = 1; key.length < len; ++counter) {
key = Buffer.concat([key, sha1(Buffer.concat([Buffer.from(counter.toString()), hx]))]);
}
}
return Buffer.alloc(len, key);
}
async function encode(string) {
var key = password_derive_bytes(password, '', 100, 32);
var cipher = crypto.createCipheriv('aes-256-cbc', key, Buffer.from(iv));
var part1 = cipher.update(string, 'utf8');
var part2 = cipher.final();
const encrypted = Buffer.concat([part1, part2]).toString('base64');
return encrypted;
}
async function decode(string) {
var key = password_derive_bytes(password, '', 100, 32);
var decipher = crypto.createDecipheriv('aes-256-cbc', key, Buffer.from(iv));
var decrypted = decipher.update(string, 'base64', 'utf8');
decrypted += decipher.final();
return decrypted;
}
And then call below functions for encode and decode
For encode
await encode(JSON.stringify({'title': 'some text'}));
For decode
await decode('encoded_string_to_decode');
Try to use 'bcrypt' package it will help you in the encryption for passwords.
If you want to encryption for Data. Then use crypto or node-rsa
Link npm bcrypt package
Node-RSA

Resources