Search code examples
javascriptnode.jscryptographycryptojsnode-crypto

Encryption on crypto-js and decryption on node crypto using CTR mode issue


I am trying to encrypt data using crypto-js javascript library and trying to decrypt the same encrypted text on nodejs side using node crypto library. I am using AES 256 encryption algo with CTR mode with no padding. I am able to encrypt properly but the description on nodejs crypto module is not producing same plain text.

If I try to encrypt or decrypt using the same crypto-js and node crypto library, it works fine but encryption on crypto-js and description on crypto is not working as expected. I have tried to confirm if I encrypt and decrypt in the same library than it works or not and it works perfectly fine. Can someone please check what mistake I am making here?

Please find below code samples.

Encryption:

var key =  CryptoJS.enc.Hex.parse('F29BA22B55F9B229CC9C250E11FD4384');
var iv  =  CryptoJS.enc.Hex.parse('C160C947CD9FC273');


function encrypt(plainText) {

  return CryptoJS.AES.encrypt(                                               
                                plainText,                                           
                                key,
                                { 
                                    iv: iv,
                                    padding: CryptoJS.pad.NoPadding,
                                    mode:  CryptoJS.mode.CTR
                                }
                              );                             
}

Descryption using NodeJS crypo module:

var algorithm = 'aes-256-ctr';
var key = 'F29BA22B55F9B229CC9C250E11FD4384';
var iv = 'C160C947CD9FC273';

var outputEncoding = 'hex';
var inputEncoding = 'hex';

const decipher = crypto.createDecipheriv(algorithm, key, iv);
let decrypted = decipher.update('8df5e11f521cf492437a95', inputEncoding, 'utf8');
decrypted += decipher.final('utf8');

console.log(decrypted);

As I have mentioned above, I have JavaScript crypo-js and NodeJS crypo module sessions working fine if I encrypt and decrypt using the same lib but doesn't work otherwise. Please check the working code as below.

JavaScript: http://jsfiddle.net/usr_r/2qwt8jsh/2/

NodeJS: https://repl.it/repls/AchingRegalPhp


Solution

  • In contrast to the NodeJS-code (Crypto), the JavaScript-code (CryptoJS) interprets keys and IV as hexadecimal strings. Therefore, in the JavaScript-Code AES-128 is used and in the NodeJS-Code AES-256. To solve the problem, both codes must use the same encryption.

    Option 1: Change the JavaScript-code to AES-256: Replace in the JavaScript-code

    var key = CryptoJS.enc.Hex.parse('F18AB33A57F9B229CC9C250D00FC3273');
    var iv = CryptoJS.enc.Hex.parse('D959B836CD9FB162');
    

    by

    var key = CryptoJS.enc.Utf8.parse('F18AB33A57F9B229CC9C250D00FC3273');
    var iv = CryptoJS.enc.Utf8.parse('D959B836CD9FB162');
    

    Option 2: Change the NodeJS-code to AES-128: Replace in the NodeJS-code

    var algorithm = 'aes-256-ctr';    
    var key = 'F18AB33A57F9B229CC9C250D00FC3273';
    var iv = 'D959B836CD9FB162';
    

    by

    var algorithm = 'aes-128-ctr';
    var key = Buffer.from('F18AB33A57F9B229CC9C250D00FC3273', 'hex');
    var iv = Buffer.from('D959B836CD9FB1620000000000000000', 'hex');
    

    With one of each of the two changes, the codes of both links produce the same result.


    If AES-256 should be used and key and IV should be specified as hexadecimal strings, a correspondingly large key and IV must be used, e.g. on the JavaScript-side:

    var key = CryptoJS.enc.Hex.parse('F18AB33A57F9B229CC9C250D00FC3273F18AB33A57F9B229CC9C250D00FC3273');
    var iv = CryptoJS.enc.Hex.parse('D959B836CD9FB16200000000000000'); 
    

    and on the NodeJS-side:

    var algorithm = 'aes-256-ctr';
    var key = Buffer.from('F18AB33A57F9B229CC9C250D00FC3273F18AB33A57F9B229CC9C250D00FC3273', 'hex');
    var iv = Buffer.from('D959B836CD9FB1620000000000000000', 'hex');