Search code examples
javascriptreactjslaravelreact-nativecryptojs

Crypt in laravel Decrypt in react native Error


I am creating an app with reactnative and laravel,

so my code in laravel is creating a Qr code with a crypted data and send it to my front end (Reactjs),

When i try o decrypted in react native using Crypto js it adds a few caractere that i didn't add in my back end ,

I will show all function and exmeples ,

//Code in laravel crypt my QR info

 $unix =time();     
 $unix_hashed =  Crypt::encrypt($unix);
 return  QrCode::size(100)->generate($unix_hashed);

// Code in react native with cryptojs for the decrypt

var key = '6AhFLqwlExB9tn2Twql62EtbFDqBEv+S7tXW3h6a/0o=';
let  encrypted = atob(data);
encrypted = JSON.parse(encrypted);
const iv = CryptoJS.enc.Base64.parse(encrypted.iv);
const value = encrypted.value;
key = CryptoJS.enc.Base64.parse(key);
var decrypted = CryptoJS.AES.decrypt(value, key, {
    iv: iv
  });
decrypted = decrypted.toString(CryptoJS.enc.Utf8);

// exemple of the output in console :

this is my output

but the problem it should be like this :

i:1634986874;

the " " & i & : & ; is extra

Can some one help me

Thanks


Solution

  • Crypt::encrypt() uses AES-256 in CBC mode by default, s. here.

    Before encryption, the plaintext is serialized by calling the PHP function serialize() generating a storable representation of the value. For instance, serialize(1635015182) returns i:1635015182; and serialize('Hello world') returns s:11: "Hello world";. In the serialized data, i denotes an integer, s:11 denotes an 11 character string.

    If decryption is performed with Crypt::decrypt(), unserialize() is called after decryption, which deserializes the data and restores the original plaintext.

    When decrypting with another library, such as CryptoJS, the deserialization is not performed, so the serialized plaintexts are returned. Therefore, deserialization must be done manually here.

    Fortunately, there is the locutus library that provides ports of PHP functionalities to JavaScript, so unserialize() can also be executed under JavaScript/NodeJS without much effort:

    var CryptoJS = require('crypto-js');
    var atob = require('atob');
    var unserialize = require('locutus/php/var/unserialize')
    
    // ciphertext from Crypt::encrypt()
    var data = "eyJpdiI6IkYyaDhxenFJM0FjaW56TW83NkpuNHc9PSIsInZhbHVlIjoiNzhSeUs5em1WblpaRWk2OVBWVURnUT09IiwibWFjIjoiODg1NGFkOTk0MGVjMjIxODAyNzExOTgxYjhiMDM4YjliMmM5NzE5Mjc0YzFmNDVlMWU1MWRkMTQ2N2Q5ODdmNCJ9"
    
    var key = '6AhFLqwlExB9tn2Twql62EtbFDqBEv+S7tXW3h6a/0o=';
    let  encrypted = atob(data);
    encrypted = JSON.parse(encrypted);
    const iv = CryptoJS.enc.Base64.parse(encrypted.iv);
    const value = encrypted.value;
    key = CryptoJS.enc.Base64.parse(key);
    var decrypted = CryptoJS.AES.decrypt(value, key, {
        iv: iv
      });
    decrypted = decrypted.toString(CryptoJS.enc.Utf8);
    
    // unserialize
    console.log(decrypted); // i:1635015182;
    console.log(unserialize(decrypted)); // 1635015182 
    

    The unserialize() call in the last line restores the original plaintext.


    Please note that encrypted.mac contains a MAC for checking data integrity. Here you can find a PHP implementation for Crypt::encrypt().