Elvin Bayramov
Elvin Bayramov

Reputation: 107

CryptoJS AES-128-ECB and PHP openssl_encrypt don't match

I have some code on PHP, which can't be edited and a database full of encrypted this way messages.

$key = '297796CCB81D2553B07B379D78D87618'
return $encrypted = openssl_encrypt($data, 'AES-128-ECB', $key);

I have to write some JS code to encrypt and decrypt these messages. I'm using CryptoJS for this purpose.

const key = '297796CCB81D2553B07B379D78D87618'
let k = CryptoJS.enc.Base64.parse(key)
let cypher = CryptoJS.AES.encrypt(this.text, k, {mode: CryptoJS.mode.ECB})
this.cypher = CryptoJS.enc.Base64.stringify(cypher.ciphertext)

I can not get these codes to produce the same results. For 'test' string i got following results: JS: H1AG6j/i/iSqifSNCG5JKw==, PHP: Nqrur4UMEicEMwJC39qq0A==

I'm trying to work this out for 3 days, but I cannot find the issue. The only code I can edit is JS.

Upvotes: 3

Views: 2767

Answers (2)

Starboy
Starboy

Reputation: 117

If you change the method to AES-256-ECB in your PHP part, than it will work with the same key (length). It is because of the CryptoJS.AES, that chooses the method by length of the key by itself.

https://cryptojs.gitbook.io/docs/#the-cipher-algorithms

AES-256-CBC EXAMPLE

/*
    CryptoJS (JS) chooses the AES method by size of the key,
    for AES-256 you need 256 bit key (32 1-byte chars).
    For AES-128 you have to change substr() from "32" to "16" in this script below (in both PHP and JS part) and change $method in PHP part to "AES-128-CBC".
    Default CryptoJS mode is CBC.

    Openssl (PHP) AES-CBC cipher expects 128 bit iv (16 1-byte chars).
*/


/* JS */


// Substances
var data = "Data",
    salt = CryptoJS.SHA256( "Salt" ),
    iv   = CryptoJS.SHA1( "Vector" ),
    key  = CryptoJS.SHA256( "Key" );

// Prepare substances
salt = salt.toString( CryptoJS.enc.Base64 );
iv   = iv.toString( CryptoJS.enc.Base64 ).substr( 0, 16 );
iv   = CryptoJS.enc.Utf8.parse( iv );
key  = key.toString( CryptoJS.enc.Base64 ).substr( 0, 32 );
key  = CryptoJS.enc.Utf8.parse( key );

// Cipher
var encrypted = CryptoJS.AES.encrypt( salt + data, key, { iv: iv });

// Results
console.log( "SALT\n"       + salt );
console.log( "IV\n"         + encrypted.iv.toString( CryptoJS.enc.Utf8 ));
console.log( "KEY\n"        + encrypted.key.toString( CryptoJS.enc.Utf8 ));
console.log( "ENCRYPTED\n"  + encrypted.toString());


/* PHP */


// Substances
$data   = "Data";
$salt   = openssl_digest( "Salt",   "SHA256" );
$iv     = openssl_digest( "Vector", "SHA1" );
$key    = openssl_digest( "Key",    "SHA256" );

// Method
$method = "AES-256-CBC";

// Prepare substances
$salt   = base64_encode( hex2bin( $salt ));
$iv     = substr( base64_encode( hex2bin( $iv )),  0, 16 );
$key    = substr( base64_encode( hex2bin( $key )), 0, 32 );

// Cipher
$encrypted = openssl_encrypt( $salt .$data, $method, $key, 0, $iv );

// Results
var_dump([  "SALT"      => $salt,
            "IV"        => $iv,
            "KEY"       => $key,
            "ENCRYPTED" => $encrypted ]);

/*
    Results CryptoJS (JS):

    SALT: yDtwME1gxORm3S1FKrWukVtQJ2/EYSTt3j49voeKTf4=
    IV:   pX4G9FSRBn8DEoT7
    KEY:  S4VjDgGFIBNzA2jl8Ta6/iiIWJgtTgWF
    ENCRYPTED
    5y8MvyMiCUjTQJUxtRNZzuYSWwSoY9edMO0o6aQoSX0t4NZWnnViPotU8vkMtgfBuZ6F1FfE/ZJZvafdtGVHJQ==

    Results openssl_encrypt (PHP):

    SALT: yDtwME1gxORm3S1FKrWukVtQJ2/EYSTt3j49voeKTf4=
    IV:   pX4G9FSRBn8DEoT7
    KEY:  S4VjDgGFIBNzA2jl8Ta6/iiIWJgtTgWF
    ENCRYPTED
    5y8MvyMiCUjTQJUxtRNZzuYSWwSoY9edMO0o6aQoSX0t4NZWnnViPotU8vkMtgfBuZ6F1FfE/ZJZvafdtGVHJQ==
*/

Upvotes: 1

Elvin Bayramov
Elvin Bayramov

Reputation: 107

I figured out what problem is. openssl_encrypt in PHP takes the key as a UTF-8 string. After taking enough length, it ignores next characters, so our key: '297796CCB81D2553B07B379D78D87618' trims to '297796CCB81D2553'. This code is working:

// JS 
const key = '297796CCB81D2553'
let k = CryptoJS.enc.Utf8.parse(key)
let cypher = CryptoJS.AES.encrypt(this.text, k, {mode: CryptoJS.mode.ECB})
this.cypher = CryptoJS.enc.Base64.stringify(cypher.ciphertext) 

Upvotes: 4

Related Questions