Reputation: 149
I would like to implement a PhP encryption function in a ReactJS application. I need to send the token in the specific format which was created with the OpenSSL library function (openssl_encrypt).
The PHP function produces a few character shorter string in comparison to the JAVASCRIPT function. Of course, both get the same attributes and properties.
PHP:
protected static function encrypt($stringData) {
$encrypted = false;
$encrypt_method = 'AES-256-CBC';
$iv = substr(hash('sha256', static::$ivMessage), 0, 16);
$encrypted= openssl_encrypt($stringData, $encrypt_method, static::$apiSecret, 0, $iv);
return $encrypted;
}
JAVASCRIPT:
export const encrypt = (stringData) => {
const iv = CryptoJS.SHA256(IV_MESSAGE).toString(CryptoJS.enc.Hex).substring(0, 16);
const encrypted = CryptoJS.AES.encrypt(stringData, API_SECRET, {
iv,
mode: CryptoJS.mode.CBC,
pad: CryptoJS.pad.ZeroPadding,
});
return encrypted;
};
Sample constants:
const stringData = "{"uid":19,"price":10000000,"duration":240,"credit_purpose":5,"new_tab":false,"cssFile":"kalkulatorok","css":[],"supported":false,"email":"[email protected]","productType":"home_loan","method":"calculator","calculatorType":"calculator","unique":true}";
const IV_MESSAGE = "a";
const API_SECRET = "secret_key";
(same for PHP function --> $stringData, $ivMessage; $apiSecret)
How can I achieve to "replicate" the PHP function in JAVASCRIPT? What did I miss so far?
Upvotes: 3
Views: 569
Reputation: 49251
The following changes in the CryptoJS code are necessary to generate the ciphertext of the PHP code:
WordArray
. If it is passed as a string, it is interpreted as a passphrase from which a 32 bytes key is derived.The following PHP code:
function encrypt($stringData) {
$ivMessage = "a";
$apiSecret = "secret_key";
$encrypted = false;
$encrypt_method = 'AES-256-CBC';
$iv = substr(hash('sha256', $ivMessage), 0, 16);
$encrypted= openssl_encrypt($stringData, $encrypt_method, $apiSecret, 0, $iv);
return $encrypted;
}
$stringData = '{"uid":19,"price":10000000,"duration":240,"credit_purpose":5,"new_tab":false,"cssFile":"kalkulatorok","css":[],"supported":false,"email":"[email protected]","productType":"home_loan","method":"calculator","calculatorType":"calculator","unique":true}';
print(encrypt($stringData) . "\n");
returns the result:
d/H+FfTaT/3tIkaXtIix937p6Df/vlnxagNJGJ7ljj48phT7oA7QssTatL3WNZY0Igt0r5ObGyCt0AR0IccVTFVZdR+nzNe+RmKQEoD4dj0mRkZ7qi/y3bAICRpFkP3Nz42fuILKApRtmZqGLTNO6dwlCbUVvjg59fgh0wCzy15g51G6CYLsEHa89Dt193g4qcXRWFgI9gyY1Gq7FX0G6Ers0fySQjjNcfDJg0Hj5aSxbPU6EPn14eaWqkliNYSMqzKhe0Ev7Y54x2YlUCNQeLZhwWRM2W0N+jGU7W+P/bCtF4Udwv4cweUESXkHLGtlQ0K6O5etVJDtb7ZtdEI/sA==
The CryptoJS code below generates the same ciphertext:
const IV_MESSAGE = "a";
const API_SECRET = "secret_key\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
function encrypt(stringData){
const iv = CryptoJS.SHA256(IV_MESSAGE).toString(CryptoJS.enc.Hex).substring(0, 16);
const encrypted = CryptoJS.AES.encrypt(
stringData,
CryptoJS.enc.Utf8.parse(API_SECRET),
{
iv: CryptoJS.enc.Utf8.parse(iv)
});
return encrypted;
};
const stringData = {"uid":19,"price":10000000,"duration":240,"credit_purpose":5,"new_tab":false,"cssFile":"kalkulatorok","css":[],"supported":false,"email":"[email protected]","productType":"home_loan","method":"calculator","calculatorType":"calculator","unique":true};
const ciphertextB64 = encrypt(JSON.stringify(stringData)).toString();
console.log(ciphertextB64.replace(/(.{64})/g,'$1\n'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
The following should also be taken into account:
EVP_BytesToKey
, should not be applied because it is not a standard and is also deemed relatively insecure.Upvotes: 3