I need following encryption decryption, but in java script for client-side.
This code is written in Node-JS and using crypto library, i couldn't find same solution for java script for client side run.
const crypto = require('crypto');
const decrypt = (textBase64, keyBase64, ivBase64) => {
const algorithm = 'aes-256-cbc';
const ivBuffer = Buffer.from(ivBase64, 'base64');
const keyBuffer = Buffer.from(keyBase64, 'base64');
const decipher = crypto.createDecipheriv(algorithm, keyBuffer, ivBuffer);
decipher.setAutoPadding(false);
let decrypted = decipher.update(textBase64, 'base64', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
const encryptedMessage = '';
const key = 'cGFzc3dvcmQxMjM0NTY3ODk=';
const iv = Buffer.from(encryptedMessage, 'base64').slice(0, 16);
// the message comes from the bytes AFTER the IV - this is what you should decrypt
const message = Buffer.from(encryptedMessage, 'base64').slice(16);
const result = decrypt(message, key, iv);
console.log(result);
//console.log(Buffer.from(encryptedMessage, 'base64').slice(0, 16))
First I would say it is not recommended to decrypt on the client side as the key is visible. but you know what you do.
this library is pure JS and should be working in a browser without any pain : ricmoo/aes-js
Related
I am trying to encrypt and decrypt values using node inbuild module crypto. I have followed this tutorial to encrypt the data. They haven't to gave any sample code to decrypt. When I try to use other tutorial code to decrypt the data. It not working out. Please help me out,
Code
const crypto = require('crypto');
// Difining algorithm
const algorithm = 'aes-256-cbc';
// Defining key
const key = crypto.randomBytes(32);
// Defining iv
const iv = crypto.randomBytes(16);
// An encrypt function
function encrypt(text) {
// Creating Cipheriv with its parameter
let cipher = crypto.createCipheriv(
'aes-256-cbc', Buffer.from(key), iv);
// Updating text
let encrypted = cipher.update(text);
// Using concatenation
encrypted = Buffer.concat([encrypted, cipher.final()]);
// Returning iv and encrypted data
return encrypted.toString('hex');
}
var op = encrypt("Hi Hello"); //c9103b8439f8f1412e7c98cef5fa09a1
Since you havent provided the code for decryption, Cant help you what is actually wrong you doing, apart from that you can do this to get decrypted code:
const crypto = require('crypto')
// Defining key
const key = crypto.randomBytes(32)
// Defining iv
const iv = crypto.randomBytes(16)
// An encrypt function
function encrypt(text) {
// Creating Cipheriv with its parameter
const cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(key), iv)
// Updating text
let encrypted = cipher.update(text)
// Using concatenation
encrypted = Buffer.concat([encrypted, cipher.final()])
// Returning iv and encrypted data
return encrypted.toString('hex')
}
var op = encrypt('Hi Hello')
console.log(op)
function decrypt(data) {
// Creating Decipheriv with its parameter
const decipher = crypto.createDecipheriv('aes-256-cbc', Buffer.from(key), iv)
// Updating text
const decryptedText = decipher.update(data, 'hex', 'utf8')
const finalText = decryptedText + decipher.final('utf8')
return finalText
}
var decrptedData = decrypt(op)
console.log(decrptedData)
When I first tested it both the encrypt and decrypt using the aes-256-ctr algorithm worked fine but after I posted it to IPFS and returned it it gave me the following error.
TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received undefined
It all looks up to par for me.
Here is the encryption.js file.
const crypto = require('crypto');
const algorithm = 'aes-256-ctr';
const secretKey = 'vOH6sdmpNWjRRIqCc7rdxs01lwHzfr33';
const iv = crypto.randomBytes(16);
//const file = fs.readFileSync("test.txt");
//console.log(secretKey.length);
const encrypt = (text) => {
const cipher = crypto.createCipheriv(algorithm, secretKey, iv);
const encrypted = Buffer.concat([cipher.update(text), cipher.final()]);
return {
iv: iv.toString('hex'),
content: encrypted.toString('hex')
};
};
const decrypt = (hash) => {
const decipher = crypto.createDecipheriv(algorithm, secretKey, Buffer.from(hash.iv, 'hex'));
const decrypted = Buffer.concat([decipher.update(Buffer.from(hash.content, 'hex')),
decipher.final()]);
return decrypted.toString();
};
It seems to work for me -- but only if you pass the entire object returned by encrypt into decrypt. If you just pass in the hash without the iv, you get that error.
I am using the inbuilt crypto module, and been frustrated for many hours trying to figure out why decipher.update returns a function and not the deciphered text itself.
code:
const file = path.join(__dirname, '../secret.txt');
const fileIV = path.join(__dirname, '../iv.txt');
const at = path.join(__dirname, '../at.txt')
var secret = fs.readFileSync(file, 'utf-8');
const algorithm = 'aes-256-gcm';
var text = 'default'
var encrypted = secret;
const iv = crypto.randomBytes(16);
encrypt(plainText, key, iv) {
const cipher = crypto.createCipheriv(algorithm, key, iv);
return { encrypted: Buffer.concat([cipher.update(plainText), cipher.final()]), authTag: cipher.getAuthTag() }
}
decrypt(encrypted, key, iv, authTag) {
const decipher = crypto.createDecipheriv(algorithm, key, iv).setAuthTag(authTag);
console.log('this worked decrypt');
return Buffer.concat([decipher.update(encrypted), decipher.final()]);
}
SignUp(pass)
{
console.log(pass);
var pair = ec.genKeyPair();
text = pair.getPrivate.toString('hex');
const key = crypto.scryptSync(pass, 'baethrowssalt', 32);
console.log(`The key is:${key}`);
const {encrypted, authTag} = this.encrypt(text, key, iv);
console.log('encrypted: ',encrypted.toString('hex'));
const decrypted = this.decrypt(encrypted, key, iv, authTag);
console.log('Decrypted:', decrypted.toString('utf-8'));
return console.log(`Close and reopen your app to integrate your wallet securely`);
}
in console it prints this when I print out the decrypted result of the private key I initially tried encrypting with scrypt:
Decrypted: function getPrivate(enc) {
if (enc === 'hex')
return this.priv.toString(16, 2);
else
return this.priv;
}
why is
decrypt(encrypted, key, iv, authTag) {
const decipher = crypto.createDecipheriv(algorithm, key, iv).setAuthTag(authTag);
console.log('this worked decrypt');
return Buffer.concat([decipher.update(encrypted), decipher.final()]);
}
not giving me the text in its deciphered form? Additionally, how can I obtain it since I am clearly doing something wrong. Any help would really be appreciated.
The result of the decryption is exactly the same as the plaintext you encrypted!
You can easily verify this by outputting the plaintext, i.e. the contents of text, in SignUp() in the console before encrypting it:
var text = pair.getPrivate.toString('hex');
console.log('Initial plaintext:', text); // Initial plaintext: function getPrivate(enc) {...
The reason for the unexpected content of text is that you simply forgot the pair of parentheses after getPrivate, it should be:
var text = pair.getPrivate().toString('hex');
console.log('Initial plaintext:', text); // Initial plaintext: <the hex encoded private key>
Then the decryption provides the expected result.
It is probably because "decrypted.toString('utf-8')" is not executing the function but turning it into a string to show in the console...
I believe you have to do something like:
let decryptedResult = decrypted.toString('utf-8'); console.log('Decrypted:', decryptedResult.toString('utf-8'));
or but not sure
console.log('Decrypted:', (decrypted).toString('utf-8'));
I am able decrypt AES encrypted message using Node's crypto library as follow
const crypto = require('crypto');
const encryptedData = 'b6ab428efbcb93c2f483178114ac0608530e54428f1378c6d3be108531b730d1888e562044cd3acb8844a04d9d7602d83b96f0a758248ffd07cd9c530b76c91c';
const decryptResponse2 = (data) => {
const key = 'F5:A4:F4:AB:BF:68:CF:86:51:B4:AA';
const iv = Buffer.from(data.substring(0, 32), 'hex');
const payload = data.substring(32);
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv).setAutoPadding(false);
const decipherFinal = decipher.update(payload, 'hex', 'utf8') + decipher.final('utf8');
console.log(decipherFinal);
};
decryptResponse2(encryptedData);
I create a script using crypto-js library as that is available to be used in browser. The code I tried is as follow:
const crypto = require('crypto-js');
const encryptedData = 'b6ab428efbcb93c2f483178114ac0608530e54428f1378c6d3be108531b730d1888e562044cd3acb8844a04d9d7602d83b96f0a758248ffd07cd9c530b76c91c';
const decryptResponse = (data) => {
const key = 'F5:A4:F4:AB:BF:68:CF:86:51:B4:AA';
const iv = Buffer.from(data.substring(0, 32), 'hex');
const payload = data.substring(32);
let decryptedData = crypto.AES.decrypt(
payload,
key,
{
iv: iv,
mode: crypto.mode.CBC,
padding: crypto.pad.NoPadding
});
console.log(decryptedData.toString());
}
decryptResponse(encryptedData);
However, not only is it generating wrong decrypted data, the decrypted message is not even consistent. I don't know what I am doing wrong as I do not know much about encryption and decryption.
Any help will be apriciated.
Thanks to #GrafiCode pointing me to the right place, I was able to solve it using format property of config object.
Following is the code:
const crypto = require('crypto-js');
const encryptedData = 'b6ab428efbcb93c2f483178114ac0608530e54428f1378c6d3be108531b730d1888e562044cd3acb8844a04d9d7602d83b96f0a758248ffd07cd9c530b76c91c';
const decryptResponse = (data) => {
const key = crypto.enc.Utf8.parse('F5:A4:F4:AB:BF:68:CF:86:51:B4:AA');
const iv = crypto.enc.Hex.parse(data.substring(0, 32));
const payload = data.substring(32);
let decryptedData = crypto.AES.decrypt(
payload,
key,
{
iv: iv,
mode: crypto.mode.CBC,
// padding: crypto.pad.NoPadding,
format: crypto.format.Hex
});
console.log(crypto.enc.Utf8.stringify(decryptedData));
}
decryptResponse(encryptedData);
I commented out the padding: crypto.pad.NoPadding as there were non-printable characters at the end of the decryptedData when it was enabled.
I can encrypt/decrypt with Python OR with JavaScript but passing encrypted data generated by Python to my JavaScript code fails.
The base64 encoding/decoding works across languages so that base encoding on Python and decoding on JavaScript retrieves the original encrypted string.
Outside of test functions I am not using Python decrypt or JavaScript encrypt but they are here for completeness as some readers miss text saying they exist.
In Python 2:
import base64
from pyaes import AESModeOfOperationCTR
SECRET_KEY = "This_key_for_demo_purposes_only!"
def encrypt(raw_data, key=SECRET_KEY):
aes = AESModeOfOperationCTR(key)
encrypted_data = aes.encrypt(raw_data)
base64_encrypted_data = base64.b64encode(encrypted_data)
return base64_encrypted_data
def decrypt(base64_encrypted_data, key=SECRET_KEY):
encrypted_data = base64.b64decode(base64_encrypted_data)
aes = AESModeOfOperationCTR(key)
decrypted = aes.decrypt(encrypted_data)
return decrypted
In Javascript (running Server-side, on Parse.com Cloud Code):
var Buffer = require('buffer').Buffer;
var Crypto = require('crypto');
encrypt: function(raw) {
var cryptoAlgorithm = "aes-256-ctr";
var key = "This_key_for_demo_purposes_only!"
var cipher = Crypto.createCipher(cryptoAlgorithm, key);
var encrypted = cipher.update(raw, 'utf8', 'binary');
encrypted += cipher.final('binary');
var base = toBase64(encrypted);
return base;
},
decrypt: function(base64raw) {
var raw = fromBase64(base64raw);
var cryptoAlgorithm = "aes-256-ctr";
var key = "This_key_for_demo_purposes_only!"
var decipher = Crypto.createDecipher(cryptoAlgorithm, key);
var decrypted = decipher.update(raw, 'binary', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
The output of the JavaScript function decrypt() is nonsense.
Where is the mismatch?
The output of the two encrypt functions does not match when given the same raw string.
My guess: in the JavaScript I shouldn't be using 'binary'. The JavaScript decrypt() function chokes if specify 'hex' for the data generated from the Python side.