Reputation: 469
I have the following code in NodeJS
import * as CryptoJS from 'crypto-js';
const cfg = {
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
};
encryptAES = (text, key) => {
var encrypted = CryptoJS.AES.encrypt(text, key).toString();
return encrypted;
};
Once i encrypt any text with a 32 digit key, its encrypted and returned. I can decrypt it using the following function
decryptAES = (encryptedBase64, key) => {
const decrypted = CryptoJS.AES.decrypt(encryptedBase64, key);
if (decrypted) {
try {
console.log(decrypted);
const str = decrypted.toString(CryptoJS.enc.Utf8);
if (str.length > 0) {
return str;
} else {
return 'error 1';
}
} catch (e) {
return 'error 2';
}
}
return 'error 3';
};
Both encryption & decryption are working fine in react.
Example:
Text: this is a sample text Key: 12345678123456781234567812345678 Result (encrypted): U2FsdGVkX1/ARpsMWWEdLiOanB67kh2akfCIN5s+RLDsJetSMagGsk444I+F/dbp
Now if i try to decrypt the above given encrypted text using PHP. I am getting false
but nothing as decrypted.
PHP Code is as below:
$key = '12345678123456781234567812345678';
$ciphertext = "U2FsdGVkX1/ARpsMWWEdLiOanB67kh2akfCIN5s+RLDsJetSMagGsk444I+F/dbp";
$result = openssl_decrypt($ciphertext, 'AES-256-CBC', $key, 0);
while ($msg = openssl_error_string())
echo $msg . "<br />\n";
var_dump($result);
What could be wrong?
Upvotes: 1
Views: 1244
Reputation: 49251
If in CryptoJS.AES.encrypt()
the key material is passed as string, then it is interpreted as password and a key derivation is performed using the proprietary key derivation function EVP_BytesToKey()
with MD5 as digest and an iteration count of 1.
The key derivation uses the password and a randomly generated 8 bytes salt to derive a 32 bytes key and a 16 bytes IV. The encrypted data is the concatenation of the ASCII encoding of Salted__
, followed by the 8 bytes salt and followed by the actual ciphertext.
Therefore, during decryption, salt and actual ciphertext must first be extracted from the ciphertext. Then with salt and password the key and the IV must be determined using EVP_BytesToKey()
, and finally the decryption can be performed:
$password = '12345678123456781234567812345678';
// Extract IV and ciphertext
$saltCiphertextB64 = "U2FsdGVkX1/ARpsMWWEdLiOanB67kh2akfCIN5s+RLDsJetSMagGsk444I+F/dbp";
$saltCiphertext = base64_decode($saltCiphertextB64);
$salt = substr($saltCiphertext, 8, 8);
$ciphertext = substr($saltCiphertext, 16);
// Derive key and IV
$keyIv = EVP_BytesToKey($salt, $password);
$key = substr($keyIv, 0, 32);
$iv = substr($keyIv, 32);
// Decrypt
$result = openssl_decrypt($ciphertext, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
var_dump($result); // string(21) "this is a sample text"
function EVP_BytesToKey($salt, $password) {
$derived = '';
$tmp = '';
while(strlen($derived) < 48) {
$tmp = md5($tmp . $password . $salt, true);
$derived .= $tmp;
}
return $derived;
}
Upvotes: 2