CryptoJS encryption and decryption using PHP

On the client side (mobile device), I encrypt the user password using CryptoJS:

var lib_crypt = require('aes'); $.loginButton.addEventListener('click', function(e){ var key = lib_crypt.CryptoJS.enc.Hex.parse('bcb04b7e103a0cd8b54763051cef08bc55abe029fdebae5e1d417e2ffb2a00a3'); var iv = lib_crypt.CryptoJS.enc.Hex.parse('101112131415161718191a1b1c1d1e1f'); var encrypted = lib_crypt.CryptoJS.AES.encrypt($.passwordInput.value, key, { iv: iv }); var password_base64 = encrypted.ciphertext.toString(lib_crypt.CryptoJS.enc.Base64); return password_base64; }); 

On the server side, I want to decrypt it using mcrypt_decrypt:

 function decryptPassword($password) { $key = pack('H*', "bcb04b7e103a0cd8b54763051cef08bc55abe029fdebae5e1d417e2ffb2a00a3"); $ciphertext_dec = base64_decode($password); $iv_dec = "101112131415161718191a1b1c1d1e1f"; $ciphertext_dec = substr($ciphertext_dec, 16); $decryptedPassword = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec); return trim($decryptedPassword); } 

I use the same key and IV, what am I doing wrong?

+5
source share
2 answers

You do not do the same on both sides.

IV

You parsed IV in CryptoJS, but forgot to do it in PHP:

 $iv_dec = pack('H*', "101112131415161718191a1b1c1d1e1f"); 

To understand that your IV is wrong, you probably noticed that the first 16 bytes are gibberish. This happens when IV is wrong. Please note that CryptoJS uses CBC mode by default, therefore IV only affects the first block during decryption. Remove :

 $ciphertext_dec = substr($ciphertext_dec, 16); 

Hauling

You have probably noticed that most plaintexts do not come out correctly. They end with some strange repeated characters at the end. This is the add-on PKCS # 7, which is used by default in CryptoJS. You must remove the add-on in PHP. Good thing Maarten Bodewes provided the right solution for copying this here .

trim() may be suitable for ZeroPadding, but not when using the correct padding scheme, such as that defined in PKCS # 7. You can even remove the trim() call because it is not useful and can lead to unexpected open text since zero bytes and spaces are truncated from the beginning and the end.

0
source

Hello,

To achieve this, you should consider the use of the key and iv with 32 hexadecimal digits each, I had to solve exactly this by doing my things, and that's how it is.

 <script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"> </script> <script type="text/javascript"> //The key and iv should be 32 hex digits each, any hex digits you want, but it needs to be 32 on length each var key = CryptoJS.enc.Hex.parse("0123456789abcdef0123456789abcdef"); var iv = CryptoJS.enc.Hex.parse("abcdef9876543210abcdef9876543210"); /* if you wish to have a more friendly key, you can convert letters to Hex this way: var a = "D"; var hex_D = a.charCodeAt(0).toString(16); just to mention, if it were to binary, it would be: var binary_D = a.charCodeAt(0).toString(2); */ var secret = "Hi, this will be seen uncrypted later on"; //crypted var encrypted = CryptoJS.AES.encrypt(secret, key, {iv:iv}); //and the ciphertext put to base64 encrypted = encrypted.ciphertext.toString(CryptoJS.enc.Base64); //Assuming you have control on the server side, and know the key and iv hexes(we do), //the encrypted var is all you need to pass through ajax, //Let follow with welcomed pure JS style, to reinforce one and other concept if needed var xh = new XMLHttpRequest(); xh.open("POST", "decrypt_in_php.php", true); xh.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xh.send("encrypted="+encodeURIComponent(encrypted)); </script> 

And now getting and decrypting in PHP

 <?php //Here we have the key and iv which we know, because we have just chosen them on the JS, //the pack acts just like the parse Hex from JS $key = pack("H*", "0123456789abcdef0123456789abcdef"); $iv = pack("H*", "abcdef9876543210abcdef9876543210"); //Now we receive the encrypted from the post, we should decode it from base64, $encrypted = base64_decode($_POST["encrypted"]); $shown = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $encrypted, MCRYPT_MODE_CBC, $iv); echo $shown; //Although the decrypted is shown, there may be needed to trim and str_replace some \r \n \x06 \x05, if there is not a better "trim" way to do it though ?> 

With this we will return "Hello, this will be seen later :)

+11
source

All Articles