Encryption in Angular Crypto-JS and Decryption in PHP & Vice Versa - php

I am trying to implement the encryption and decryption in angular 11 crypto-js(browser level) and PHP(server level).
Randomly Generated Key and Iv.
Used this key and iv in both angular and php for doing the encryption and decryption.
Key - 46d7093c56d9079406754989716a402d
Iv - df9fa46af13e5921
Angular CryptoJS Encryption
let msg = "Testing";
let configuration = {
keySize: 128 / 8,
iv: CryptoJS.enc.Utf8.parse(iv),
mode: CryptoJS.mode.CBC
};
let encrypted = CryptoJS.AES.encrypt(msg, key, configuration).toString(); //U2FsdGVkX1+A5bM0Y4epRBtB/A2KYdupCgZXmSSu3hQ=
Angular CryptoJS Decryption
let encrypted = "U2FsdGVkX1+A5bM0Y4epRBtB/A2KYdupCgZXmSSu3hQ=";
let configuration = {
keySize: 128 / 8,
iv: CryptoJS.enc.Utf8.parse(iv),
mode: CryptoJS.mode.CBC
};
let decrypted = CryptoJS.AES.decrypt(encrypted, key, configuration).toString(CryptoJS.enc.Utf8);
PHP Encryption for CryptoJS
$Message = "Testing";
$encrypted = openssl_encrypt($Message, 'AES-128-CBC', $Key, 0, $Iv); #CC06me/4GIHVnoxdYgGTAQ==
$encrypted = openssl_encrypt($Message, 'AES-256-CBC', $Key, 0, $Iv); #cgWrkf8HfdDJg0VybavncQ==
PHP Decryption for CryptoJS
$Key = "46d7093c56d9079406754989716a402d";
$Iv = "df9fa46af13e5921";
$Encrypted = "CC06me/4GIHVnoxdYgGTAQ==";
$encrypted = openssl_decrypt($Encrypted, 'AES-128-CBC', $Key, 0, $Iv);
$Encrypted = "cgWrkf8HfdDJg0VybavncQ==";
$encrypted = openssl_decrypt($Message, 'AES-256-CBC', $Key, 0, $Iv);
The encryption which is made by angular cryptojs is able to decrypt by angular cryptojs, but not in php. I tried multiple module to make the decryption in PHP, but I am unable to decrypt the same.
Can anyone please suggest what I am missing in this method of decryption.
Thanks in advance.

Related

Using openssl_decrypt() not displaying anything when trying to decrypted an encrypted data

I am trying to decrypt data coming from ionic in PHP but it is not decrypting using openssl_decrypt().
In my ionic app, I was able to encrypt and also test the decryption function which works well. Below are both the encryption and decryption functions:
Encryption
encrypt(key, iv, value){
const encrypted = CryptoJS.AES.encrypt(value, key, { iv: iv });
const encryptedMessage = encrypted.toString();
return encryptedMessage;
}
Decryption
decrypt(value, keys, ivs){
const decryptedMessage = CryptoJS.AES.decrypt(value, keys, { iv: ivs
}).toString(CryptoJS.enc.Utf8);
return decryptedMessage;
}
Encrypted data with key and iv
$iv = "048eb25d7a45ff00";
$key = "feda4f2f67e7aa96";
$encrypted = "U2FsdGVkX1+kBV6Q5BQrjuOdi4WLiu4+QAnDIkzJYv5ATTkiiPVX8VcDUpMqSeIwCfyTNQOosp/9nYDY4Suu4/Lmhh2quKBU7BHGOtKwu9o=";
**To decrypt in PHP**
<?php
// Use openssl_decrypt() function to decrypt the data
$output = openssl_decrypt($encrypted, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
echo $output;
?>
How can I decrypt this?
In the CryptoJS code, the key material is passed as string, which is why it is interpreted as password and a key derivation is applied. The key derivation function used is the OpenSSL proprietary EVP_BytesToKey(). During encryption, CryptoJS.AES.encrypt() does the following:
Generate an 8 bytes salt implicitly.
Derive a 32 bytes key and 16 bytes IV based on the salt and password using EVP_BytesToKey().
Encrypt the plaintext with key and IV, ignoring any explicitly passed IV (here 048eb25d7a45ff00)!
Convert the data to OpenSSL format (by encrypted.toString()): Base64 encoding of the ASCII encoding of Salted__, followed by the 8 bytes salt and the actual ciphertext.
Therefore, decryption must be carried out as follows:
Separate salt and actual ciphertext.
Derive the 32 bytes key and 16 bytes IV from salt and password using EVP_BytesToKey(). Note that the IV 048eb25d7a45ff00 is not needed.
Decrypt the ciphertext with key and IV.
A possible implementation:
// Separate salt and actual ciphertext
$saltCiphertext = base64_decode("U2FsdGVkX1+kBV6Q5BQrjuOdi4WLiu4+QAnDIkzJYv5ATTkiiPVX8VcDUpMqSeIwCfyTNQOosp/9nYDY4Suu4/Lmhh2quKBU7BHGOtKwu9o=");
$salt = substr($saltCiphertext, 8, 8);
$ciphertext = substr($saltCiphertext, 16);
// Separate key and IV
$keyIv = EVP_BytesToKey($salt, "feda4f2f67e7aa96");
$key = substr($keyIv, 0, 32);
$iv = substr($keyIv, 32, 16);
// Decrypt using key and IV
$decrypted = openssl_decrypt($ciphertext, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
print($decrypted . PHP_EOL); // {"username":"07069605705","password":"father2242"}
// KDF EVP_BytesToKey()
function EVP_BytesToKey($salt, $password) {
$bytes = ''; $last = '';
while(strlen($bytes) < 48) {
$last = hash('md5', $last . $password . $salt, true);
$bytes.= $last;
}
return $bytes;
}
Note: EVP_BytesToKey() is deemed insecure nowadays and should not be used. A more secure alternative is PBKDF2 which is supported by both CryptoJS and PHP.

(ssg-wsg) How to do AES Encryption in SSG-WSG API with Initialization Vector in PHP

I am trying to encrypt the payload with the AES encryption like below for SSG-WSG API. But I keep getting
Failed to parse JSON request content
I think something is wrong with my way of encryption. I am doing this in PHP.
<pre>
$cipher = "aes-256-cbc";
$ekey = "encryption key provided to SSG"
//Generate a 256-bit encryption key
$encryption_key = $ekey;
// Generate an initialization vector
$iv_size = openssl_cipher_iv_length($cipher);
$iv = openssl_random_pseudo_bytes($iv_size);
//Data to encrypt
$data = $f; // payload in f
$encrypted_data = openssl_encrypt($data, $cipher, $encryption_key, 0, $iv);
$x = base64_encode($encrypted_data);
</pre>
Where is the SSGAPIInitVector initialization vector to be used, and how?
Thanks
Based on the openssl_encrypt library documentation, the 5th paramenter $iv is for the initialisation vector value. So, I believe you have to replace what you are doing which randomly generates a random Initialisation Vector to the fixed value provided.

PHP AES-128-CBC Decoding Issue?

I've been going crazy trying to decode an AES-128-CBC encrypted.
The docs from the third-party who encrypt the string.
The parameters are encrypted using AES 128 with Cipher Block Chaining, using PKCS-7
Padding. The decryption algorithm should be initialised with a 16 byte, zero-filled
initialization vector, and should use your encryption key (which can be found on the
Security page of PayWay Net Shopping Cart setup).
Example Encrypted Parameters: =QzFtdn0%2B66KJV5L8ihbr6ofdmrkEQwqMXI3ayF7UpVlRheR7r5fA6
IqBszeKFoGSyR7c7J4YsXgaOergu5SWD%2FvL%2FzPSrZER9BS7mZGckriBrhYt%2FKMAbTSS8F
XR72gWJZsul9aGyGbFripp7XxE9NQHVMWCko0NlpWe7oZ0RBIgNpIZ3JojAfX7b1j%2F5ACJ79S
VeOIK80layBwCmIPOpB%2B%2BNI6krE0wekvkkLKF7CXilj5qITvmv%2FpMqwVDchv%2FUNMfCi
4uUA4igHGhaZDQcV8U%2BcYRO8dv%2FnqVbAjkNwBqxqN3UPNFz0Tt76%2BP7H48PDpU23c61eM
7mx%2FZh%2Few5Pd0WkiCwZVkSZoov97BWdnMIw5tOAiqHvAR3%2BnfmGsx
Example Encryption Key: D5cD2CaHd3zfG3C5Apaeyc==
The code I've tried to use:
$encryptedText = '=QzFtdn0%2B66KJV5L8ihbr6ofdmrkEQwqMXI3ayF7UpVlRheR7r5fA6
IqBszeKFoGSyR7c7J4YsXgaOergu5SWD%2FvL%2FzPSrZER9BS7mZGckriBrhYt%2FKMAbTSS8F
XR72gWJZsul9aGyGbFripp7XxE9NQHVMWCko0NlpWe7oZ0RBIgNpIZ3JojAfX7b1j%2F5ACJ79S
VeOIK80layBwCmIPOpB%2B%2BNI6krE0wekvkkLKF7CXilj5qITvmv%2FpMqwVDchv%2FUNMfCi
4uUA4igHGhaZDQcV8U%2BcYRO8dv%2FnqVbAjkNwBqxqN3UPNFz0Tt76%2BP7H48PDpU23c61eM
7mx%2FZh%2Few5Pd0WkiCwZVkSZoov97BWdnMIw5tOAiqHvAR3%2BnfmGsx';
$password = 'D5cD2CaHd3zfG3C5Apaeyc=='
$method = 'AES-128-CBC';
$iv = substr($password, 0, 16);
$result = openssl_decrypt($encrypted, $method, $password, OPENSSL_ZERO_PADDING, $iv);
return $result;
This exact code won't work as the password is made up. But this is basically the result I get:
hóuR█\f\x04}wù8¨Ø½5\x02|¹ä\x16;┐¸F;Ã=·Íû\x1A¿┴ô`\x05\x08■▓¡¢|Ù_i=æëÔJ▀ß+Ñc"1ÝÒSÑî²ÚMã\x18°FÅcÃj>│└\x0E¦ï\eêÅZ\fÜ║õê6GC╬Íþ╚ɤ?\x11-P^╔öT\x10ÖÈ│,╬¤┼¹op5±órj\x7F\x1D\x10NTªh«#\fÖÚú┤▓╗L┤¼╬1Ç¥æ³\x1Ci R\x1DA8u¥MÀ\x019rmÚ§/~X╔¹\x12]]øÓ PÕopÁ]s‗ \x15Ú$\x0Eo\e\x0F┌äËXû>ÃRr}úýáÞz\x13(Õü\x13╦│\eÿB$ËÁO]¹å‗ÔÓm┴´¦╠`3\x17lPób¼\x15þz\x17/B╝+Èؾ´■,8\x1AAÚöÍá}░TFxÛR)[x?k░%z\fWPÉ-┐üð┬kÜÅr┘.ÔkÅ#^QXiH±¡wö!N
Non-UTF-8 string... I can't figure what I'm doing wrong... Is it the $iv that's wrong? Going crazy here.
The solution was to base64 decode the password/secret key before trying to decrypt.
So solution:
$encryptedText = '=QzFtdn0%2B66KJV5L8ihbr6ofdmrkEQwqMXI3ayF7UpVlRheR7r5fA6
IqBszeKFoGSyR7c7J4YsXgaOergu5SWD%2FvL%2FzPSrZER9BS7mZGckriBrhYt%2FKMAbTSS8F
XR72gWJZsul9aGyGbFripp7XxE9NQHVMWCko0NlpWe7oZ0RBIgNpIZ3JojAfX7b1j%2F5ACJ79S
VeOIK80layBwCmIPOpB%2B%2BNI6krE0wekvkkLKF7CXilj5qITvmv%2FpMqwVDchv%2FUNMfCi
4uUA4igHGhaZDQcV8U%2BcYRO8dv%2FnqVbAjkNwBqxqN3UPNFz0Tt76%2BP7H48PDpU23c61eM
7mx%2FZh%2Few5Pd0WkiCwZVkSZoov97BWdnMIw5tOAiqHvAR3%2BnfmGsx';
$password = 'D5cD2CaHd3zfG3C5Apaeyc=='
$method = 'AES-128-CBC';
$iv = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
$result = openssl_decrypt($encrypted, $method, base64_decode($password), OPENSSL_ZERO_PADDING, $iv);
return $result;

Encrypt with Crypto.JS and decrypt with PHP 7.3

I'm upgrading my code from PHP 5.6 to 7.3 which is a Woocommerce Plugin for my Ionic app. In the meantime I noted that mcrypt_decrypt is deprecated in PHP 7. I tried to figured out how to change my code, but it still does not return the same string. Here is my encryption code in the app:
var password = this.password;
if (this.appConfig.App_Secret != '') {
var key = CryptoJS.enc.Utf8.parse(CryptoJS.MD5(this.appConfig.App_Secret).toString());
var iv = CryptoJS.enc.Utf8.parse(CryptoJS.MD5(this.appConfig.App_Secret).toString().substr(0, 16));
password = CryptoJS.AES.encrypt(password, key, { iv: iv }).toString();
}
And this is my old decryption code in PHP:
$iv=substr(md5(get_option('sow_rest_api_secret')),0,16);
$key = md5(get_option('sow_rest_api_secret'));
$data = base64_decode($decrypt_str);
$result = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv);
return rtrim($result,"\0");
I change the line with the $result variable from
$result = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv);
to
$result = openssl_decrypt($data, 'aes-128-gcm', $key, $options=OPENSSL_RAW_DATA, $iv);
Can you give support?
Quoting this php.net comment:
Also, MCRYPT_RIJNDAEL_256 is not AES-256, it's a different variant of the Rijndael block cipher. If you want AES-256 in mcrypt, you have to use MCRYPT_RIJNDAEL_128 with a 32-byte key. OpenSSL makes it more obvious which mode you are using (i.e. 'aes-128-cbc' vs 'aes-256-ctr').
This means that you've been using AES-256 before, and not AES-128.
Furthermore, CryptoJS uses CBC mode by default, as correctly noted by #Topaco.
Putting this together:
$result = openssl_decrypt($data, 'aes-256-cbc', $key, $options=OPENSSL_RAW_DATA, $iv);
should give the same result, as your previous mcrypt_decrypt solution.

Is there any difference between Ruby 'AES-128-CBC' and PHP 'rijndael-128' encryption?

Ruby code is
require 'base64'
require 'openssl'
def ruby_dec iv, key, encrypted
decipher = OpenSSL::Cipher::AES.new(128, :CBC)
#decipher.padding = 0
decipher.decrypt
decipher.key = key
decipher.iv = iv
ciphertext = Base64.decode64 encrypted
decipher.update(ciphertext) + decipher.final
end
def ruby_enc iv, key, plaintext
enc = OpenSSL::Cipher.new 'aes-128-cbc'
enc.encrypt
enc.key = key
enc.iv = iv
Base64.encode64(enc.update(plaintext) + enc.final)
end
iv = Base64.decode64("TOB+9YNdXSbkSYIU7D/IpQ==")
key = Base64.decode64("7DxoShENB0D+8xrwOwSbi1TPQBiIaFq2yveoUkutCpM=")
plaintext = "testtesttest"
encrypted = ruby_enc iv, key, plaintext
puts "encrypted is #{encrypted}"
ruby_dec iv, key, encrypted
puts "plaintext is #{plaintext}"
then
$ ruby enc_dec.rb #the above code
encrypted is LXJmnM7t+HGKi2iI51ethA==
plaintext is testtesttest
Now PHP code is
function php_dec($iv, $key, $encrypted) {
$cipher_algorithm = 'rijndael-128';
$cipher_mode = 'cbc';
$key = base64_decode($key);
$iv = base64_decode($iv);
$ciphertext = base64_decode($enctypted);
return $ciphertext;
}
function php_enc($iv, $key, $plaintext){
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
$mcrypt_key = base64_decode($key);
$iv = base64_decode($iv);
mcrypt_generic_init($td, $mcrypt_key, $iv);
$ciphertext = mcrypt_generic($td, $plaintext);
retun base64_encode($ciphertext);
}
$iv = base64_decode("TOB+9YNdXSbkSYIU7D/IpQ==");
$key = base64_decode("7DxoShENB0D+8xrwOwSbi1TPQBiIaFq2yveoUkutCpM=");
$plaintext = "testtesttest";
$encrypted = php_enc($iv, $key, $plaintext);
echo "encrypted is ".$encrypted."\n";
php_dec($iv, $key, $encrypted);
echo "plaintext is ".$plaintext."\n";
$ruby_encrypted = base64_encode("LXJmnM7t+HGKi2iI51ethA==");
php_dec($iv, $key, $ruby_encrypted);
echo "plaintext is ".$plaintext."\n";
then I get
$ php enc_dec.php
encrypted is SUR33tXu32JjR9JAKIGL7w==
plaintext is testtesttest
plaintext is testtesttest
the ciphertext is different from the ruby one.
Now I try to decrypt ruby with cipher text made by PHP.
$ pry
[1] pry(main)> load 'enc_dec.rb'
[2] pry(main)> iv = Base64.decode64("TOB+9YNdXSbkSYIU7D/IpQ==")
=> "L\xE0~\xF5\x83]]&\xE4I\x82\x14\xEC?\xC8\xA5"
[3] pry(main)> key = Base64.decode64("7DxoShENB0D+8xrwOwSbi1TPQBiIaFq2yveoUkutCpM=")
=> "\xEC<hJ\x11\r\a#\xFE\xF3\x1A\xF0;\x04\x9B\x8BT\xCF#\x18\x88hZ\xB6\xCA\xF7\xA8RK\xAD\n\x93"
[4] pry(main)> ruby_dec iv, key, Base64.decode64("SUR33tXu32JjR9JAKIGL7w==")
OpenSSL::Cipher::CipherError: data not multiple of block length
from enc_dec.rb:12:in `final'
[5] pry(main)>
Is there any difference between Ruby 'AES-128-CBC' and PHP 'rijndael-128' encryption?
and how can i decrypt with ruby?
There is a difference between AES and Rijndael in the meaning of 128, in AES the 128 is the keysize, in Rijndael it is the blocksize.
The key you used is larger than 128 bits I believe.
See this article:
http://www.leaseweblabs.com/2014/02/aes-php-mcrypt-key-padding/

Categories