javascript - JS Decrypt Laravel Encrypted String

Solution:

This is how you decrypt a text in javascript encoded with Laravel using AES-256-CBC as the cipher.

CryptoJS 4.0 is used...

// Created using Crypt::encryptString('Hello world.') on Laravel.
// If Crypt::encrypt is used the value is PHP serialized so you'll 
// need to "unserialize" it in JS at the end.
var encrypted = 'eyJpdiI6ImRIN3QvRGh5UjhQNVM4Q3lnN21JNFE9PSIsInZhbHVlIjoiYlEvNzQzMnpVZ1dTdG9ETTROdnkyUT09IiwibWFjIjoiM2I4YTg5ZmNhOTgyMzgxYjcyNjY4ZGFkNTc4MDdiZTcyOTIyZjRkY2M5MTM5NTBjMmMyZGMyNTNkMzMwYzY3OCJ9';

// The APP_KEY in .env file. Note that it is base64 encoded binary
var key = 'E2nRP0COW2ohd23+iAW4Xzpk3mFFiPuC8/G2PLPiYDg=';

// Laravel creates a JSON to store iv, value and a mac and base64 encodes it.
// So let's base64 decode the string to get them.
encrypted = atob(encrypted);
encrypted = JSON.parse(encrypted);

console.log('Laravel encryption result', encrypted);



// IV is base64 encoded in Laravel, expected as word array in cryptojs
const iv = CryptoJS.enc.Base64.parse(encrypted.iv);

// Value (chipher text) is also base64 encoded in Laravel, same in cryptojs
const value = encrypted.value;


// Key is base64 encoded in Laravel, word array expected in cryptojs
key = CryptoJS.enc.Base64.parse(key);

// Decrypt the value, providing the IV. 
var decrypted = CryptoJS.AES.decrypt(value, key, {
  iv: iv
});

// CryptoJS returns a word array which can be 
// converted to string like this
decrypted = decrypted.toString(CryptoJS.enc.Utf8);

console.log(decrypted); // Voilà! Prints "Hello world!"

Answer

Solution:

Like @Dusan Malusev already mentioned:

You should not use Laravel APP_KEY in frontend code. NEVER, Laravel uses APP_KEY to encrypt everything including cookies (Session cookie and csrf cookie).

Your application could be hacked if it's in your html code! To answer your question a bit: use Crypt::decrypt($encrypted) on the server side of your application (within Laravel).

Answer

Solution:

Never use your Laravel APP_KEY in frontend. It is a big software vulnerability.

You should create a trait that encrypts and decrypts data before setting and getting data.

To use Laravel Crypt add Encryptable.php

<?PHP
namespace App;

use Illuminate\Support\Facades\Crypt;

trait Encryptable
{
    public function getAttribute($key)
    {
        $value = parent::getAttribute($key);

        if (in_array($key, $this->encryptable)) {
            $value = Crypt::decrypt($value);
        }
        return $value;
    }

    public function setAttribute($key, $value)
    {
        if (in_array($key, $this->encryptable)) {
            $value = Crypt::encrypt($value);
        }

        return parent::setAttribute($key, $value);
    }
}

After that you can use this trait in your models. Add a $encryptable property. Array of columns to be encrypted and decrypted.

class User extends Model
{    
    use Encryptable;
    
    protected $encryptable = [
       'column',
       'anotherColumn',
    ];
}

After that use model as you use before.

Answer

Solution:

I have used in ReactJs

CryptoJS 4.1

let key = process.env.REACT_APP_ENCRYTO_KEY

            let encrypted = atob(response.data)
            encrypted = JSON.parse(encrypted)
            const iv = CryptoJS.enc.Base64.parse(encrypted.iv)
            const value = encrypted.value
            key = CryptoJS.enc.Base64.parse(key)
            let decrypted = CryptoJS.AES.decrypt(value, key, {
                iv
            })
            decrypted = decrypted.toString(CryptoJS.enc.Utf8)
            return {
                ...response,
                data: JSON.parse(decrypted)
            }

Laravel 8.x using Encrypter

$encrypter = new Encrypter(Encrypter::generateKey('supported_any_cipher'));
return response($encrypter->encryptString(json_encode($response)), 200);

The supported cipher algorithms and their properties.

['aes-128-cbc' => ['size' => 16, 'aead' => false],
'aes-256-cbc' => ['size' => 32, 'aead' => false],
'aes-128-gcm' => ['size' => 16, 'aead' => true],
'aes-256-gcm' => ['size' => 32, 'aead' => true]]

Source