Encrypt with CryptoJS and decrypt with PHP

client side encryption and server side decryption in php
best encryption decryption algorithm php
php encrypt
react encrypt decrypt
encryption in php 7
php decrypt aes-128
encrypt and decrypt number in php
encrypt and decrypt string in jquery

On the client side (mobile device) I encrypt a users password with 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 with 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 do I do wrong?

You're not doing the same thing on both sides.

IV

You did parse the IV in CryptoJS, but forgot to do it in PHP:

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

To fix that your IV is wrong, you probably noticed that the first 16 bytes are gibberish. That happens when the IV is wrong. Note that CryptoJS uses CBC mode by default, so the IV has only influence on the first block during decryption. Remove this:

$ciphertext_dec = substr($ciphertext_dec, 16);
Padding

You probably noticed that most plaintexts don't come out right. They end with some strange repeated characters at the end. This is the PKCS#7 padding that is applied by default in CryptoJS. You have to remove the padding yourself in PHP. Good thing is that Maarten Bodewes has provided a proper copy paste solution for this here.

trim() might be appropriate for ZeroPadding, but not when a proper padding scheme like the one defined in PKCS#7 is used. You may remove the trim() call altogether, because it is not useful and may result in unexpected plaintext, becauses zero bytes and whitespace is trimmed from the beginning and end.

Encrypt with CryptoJS and decrypt with PHP, I've required the same thing and i wrote a short library that works for CryptoJS 3.x and PHP with openssl support. Hope this helps, source plus example files here  This tutorial help to encrypt and decrypt string using cryptojs and php. Cryptojs is very popular library which is used to convert string data into encrypted text and vise versa. I am using Angularjs/javascript Cryptojs library for encryption data. You can encrypt and decrypt string, forms data or any header parameters.You can create your own …

Hello,

in order to achieve this it should be considered to use the key and iv with 32 hex digits each, i had to solve exactly this doing my stuff and here is the way it goes

<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's 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 receiving 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 have back the "Hi, this will be seen uncrypted later on" :)

Encrypt with PHP, Decrypt with Javascript (cryptojs), parse('101112131415161718191a1b1c1d1e1f'); var encrypted = CryptoJS.AES.​encrypt("Message", key, { iv: iv });. I can achieve the same way in  The salt is generated during encryption in CryptoJS and needs to be sent to php with the ciphertext. Before invoking evpKDF the salt has to be converted to a binary string from hex.

Here is a solution based on this comment, using openssl_decrypt from PHP.

The JavaScript part (development with NodeJS for browsers) — first, install CryptoJS with npm install crypto-js, then your JS code:

import aes from 'crypto-js/aes'
import encHex from 'crypto-js/enc-hex'
import padZeroPadding from 'crypto-js/pad-zeropadding'

// message to encrypt
let msg = "Hello world";

// the key and iv should be 32 hex digits each, any hex digits you want, but it needs to be 32 on length each
let key = encHex.parse("0123456789abcdef0123456789abcdef");
let iv =  encHex.parse("abcdef9876543210abcdef9876543210");

// encrypt the message
let encrypted = aes.encrypt(msg, key, {iv:iv, padding:padZeroPadding}).toString();

// and finally, send this "encrypted" string to your server

On the PHP side, your code will look like that:

// we use the same key and IV
$key = hex2bin("0123456789abcdef0123456789abcdef");
$iv =  hex2bin("abcdef9876543210abcdef9876543210");

// we receive the encrypted string from the post
$encrypted = $_POST['decrypt'];
$decrypted = openssl_decrypt($encrypted, 'AES-128-CBC', $key, OPENSSL_ZERO_PADDING, $iv);
// finally we trim to get our original string
$decrypted = trim($decrypted);

How to AES encrypt with php and AES decrypt with javascript , I found some information about js encryption and php decryption, but it is still not very clear. The general idea is that the foreground sends a  var decrypted = CryptoJS.AES.decrypt(encrypted, key); "oijhd981727783hy18274" is treated as a passphrase to create a key and not as the actual key. Passing an IV works like this:

About using crypto-js AES to encrypt PHP backend decryption , Looked for some information about JS encrypted PHP decryption data, but still not very clear,? Probably the idea is to get a key by sending a request from the  PHP AES CryptoJS. AES Encryption/Decryption between PHP server and CryptoJS 3.x client. FEATURES. It's a simple implementation of handing encryption and decryption with AES symmetric-key algorithm between two side, PHP server and Javascript client.

What about using crypto-js AES to encrypt PHP back-end decryption , -I will be encrypting in php, decrypting with cryptojs for a small layer of security. <​script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js">  @maulvi The nonce value must be match or the same because it is the key. If you had run my test files (test-js.php, test-php.php) without any modification and it work properly then it means it is working, the trouble maybe from key changed.

Encrypt with PHP, Decrypt with Javascript (cryptojs), project, mainly using js encryption in the front end and php decryption in the back end. AES.encrypt(str, key, { iv: iv, mode: CryptoJS.mode. This has worked without issue for years now from systems running ASP/JAVA/PHP, but we now have a client who has no choice but to use CryptoJS to perform the encryption and for the life of me I cannot work out why this won't decrypt in Coldfusion.

Comments
  • You might want to add examples of what problems you experience. I currently just assumed in my answer judging from the code.
  • Thanks for the quick response Artjom, what is better to use for removing the padding: the solution of Maarten Bodewes or trim()? Thanks
  • trim() only works in one time in sixteen. One should never trim(), because that might result in unforseen consequences if the plaintext contains zero bytes or whitespace at the beginning or end.
  • How to change this into using string key instead?
  • mcrypt_decrypt function will be removed on php v7.2. Any alternative? how would it be ?
  • How to do openssl_encrypt if we have to get same encrypted text on php side too.
  • what was important for me -> the lenght of the password. I tried to use custom password, just string like "xyz" and it doesn't work. It must be password encoded like in this example. thx