Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symmetric encryption with NodeJS

I am totally confused why this isn't working, I am getting Error: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt

var crypto = require('crypto');
var key = "ciw7p02f70000ysjon7gztjn7";
var pt = "72721827b4b4ee493ac09c635827c15ce014c3c3";

var encrypt = crypto.createCipher('aes256', key);
encrypt.update(pt, 'utf8', 'hex');
var encrypted = encrypt.final('hex')

var decrypt = crypto.createDecipher('aes256', key);
decrypt.update(encrypted, 'hex', 'utf8')
decrypt.final()

You can see it action using RunKit ... https://runkit.com/fredyc/bidirectional-encryption-with-nodejs

like image 363
FredyC Avatar asked Dec 08 '16 16:12

FredyC


1 Answers

Solution via https://github.com/nodejs/node-v0.x-archive/issues/6386

// https://github.com/nodejs/node-v0.x-archive/issues/6386#issuecomment-31817919
// with createCipher / createDecipher (both deprecated) replaced with
// createCipheriv / createDecipheriv and a generated IV passed along.
var assert = require('assert');
var crypto = require('crypto');

var algorithm = 'aes256';
var inputEncoding = 'utf8';
var outputEncoding = 'hex';
var ivlength = 16  // AES blocksize

var key = Buffer.from('ciw7p02f70000ysjon7gztjn7c2x7GfJ', 'latin1'); // key must be 32 bytes for aes256
var iv = crypto.randomBytes(ivlength);

var text = '72721827b4b4ee493ac09c635827c15ce014c3c3';

console.log('Ciphering "%s" with key "%s" using %s', text, key, algorithm);

var cipher = crypto.createCipheriv(algorithm, key, iv);
var ciphered = cipher.update(text, inputEncoding, outputEncoding);
ciphered += cipher.final(outputEncoding);
var ciphertext = iv.toString(outputEncoding) + ':' + ciphered

console.log('Result in %s is "%s"', outputEncoding, ciphertext);

var components = ciphertext.split(':');
var iv_from_ciphertext = Buffer.from(components.shift(), outputEncoding);
var decipher = crypto.createDecipheriv(algorithm, key, iv_from_ciphertext);
var deciphered = decipher.update(components.join(':'), outputEncoding, inputEncoding);
deciphered += decipher.final(inputEncoding);

console.log(deciphered);
assert.equal(deciphered, text, 'Deciphered text does not match!');

the usage error is here:

// yours (incorrect)
var encrypt = crypto.createCipher('aes256', key);
encrypt.update(pt, 'utf8', 'hex');
var encrypted = encrypt.final('hex')

// correct
var encrypt = crypto.createCipher('aes256', key);
var encrypted = encrypt.update(pt, 'utf8', 'hex');
encrypted += encrypt.final('hex')



// yours (incorrect)
var decrypt = crypto.createDecipher('aes256', key);
decrypt.update(encrypted, 'hex', 'utf8')
decrypt.final()

// correct
var decrypt = crypto.createDecipher('aes256', key);
var decrypted = decrypt.update(encrypted, 'hex', 'utf8')
decrypted += decrypt.final()

but because cipher.createCipher() and cipher.createDecipher() are now deprecated and insecure, the solution above uses cipher.createCipheriv() and cipher.createDecipheriv(), instead.

The addition of a random IV protects you from leaking information if you encrypt multiple plaintexts that share the first same 16 bytes (or multiple of 16 bytes) at the start of the message. See Encrypting using AES 256, do I need IV?

like image 120
Tomalak Avatar answered Nov 11 '22 22:11

Tomalak