Problems using AES crypto between Node and CryptoJS in a browser

I want to encrypt a string using Node and decrypt a string using CryptoJS in a browser.

Encryption:

var crypto = require('crypto'); function encrypt(txt, cryptkey) { var cipher = crypto.createCipher('aes-256-cbc', cryptkey); var crypted = cipher.update(txt, 'utf8', 'hex'); crypted += cipher.final('hex'); return crypted; } encrypt('1', 'key'); // 83684beb6c8cf063caf45cb7fad04a50 

Include:

 <script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"></script> 

Decrypt:

 var decrypted = CryptoJS.AES.decrypt('83684beb6c8cf063caf45cb7fad04a50', 'key'); console.log(decrypted.toString(CryptoJS.enc.Utf8)); // empty string 

The actual result is an empty string.

What is the correct way to decrypt data from node?

0
source share
1 answer

CryptoJS supports the same password-based encryption mode that the crypto module in node.js supports, which is implemented as the equivalent of EVP_BytesToKey. CryptoJS generates a random default salt, but node.js does not use and uses an empty salt. Empty salt is bad and should not be used. In addition, it is not protected in order to obtain the password key using this method. You need to use PBKDF2 (supported by CryptoJS and node.js) or similarly with a lot of iterations and random salt.

 var ctHex = '83684beb6c8cf063caf45cb7fad04a50'; var ct = CryptoJS.enc.Hex.parse(ctHex); var salt = CryptoJS.lib.WordArray.create(0); // empty array var decrypted = CryptoJS.AES.decrypt({ciphertext: ct, salt: salt}, 'key'); document.querySelector("#dec").innerHTML = decrypted.toString(CryptoJS.enc.Utf8); 
 <script src="https://cdn.rawgit.com/CryptoStore/crypto-js/3.1.2/build/rollups/aes.js"></script> Expected: "1"<br/>Got: "<span id="dec"></span>" 

You said that this will be done through HTTP.

If you want to use transport security without user intervention, this is completely unsafe, because the key must be transmitted together with encrypted text, which makes it confusing at best.

If the user and the server both know the password before the message, then this is still not enough, because the key output that provides both CryptoJS and node.js is insufficient and something like PBKDF2. MD5 is easy to do.

You will need to use asymmetric cryptography to protect this message from a passive attacker (who cannot inject arbitrary packets into the stream between the server and the client). I suggest you create an RSA key pair and send the public key to the client so that the client can encrypt the message on the server. You can use forge for this.


Encryption will look like this:

 var salt = CryptoJS.lib.WordArray.create(0); // empty array var params = CryptoJS.kdf.OpenSSL.execute('key', 256/32, 128/32, salt); var pt = '1'; var encrypted = CryptoJS.AES.encrypt(pt, params.key, {iv: params.iv}); document.querySelector("#enc").innerHTML = encrypted.ciphertext.toString(); 
 <script src="https://cdn.rawgit.com/CryptoStore/crypto-js/3.1.2/build/rollups/aes.js"></script> Expected: "83684beb6c8cf063caf45cb7fad04a50"<br/>Got: "<span id="enc"></span>" 
+2
source

Source: https://habr.com/ru/post/1243285/


All Articles