Reputation: 449
I have a problem to generate encryption in JS, I've the encryption generator in PHP like this :
$secret_key = 'thisIsK3y';
$secret_iv = 'tHis1s1v';
$output = false;
$encrypt_method = "AES-256-CBC";
$key = hash( 'sha256', $secret_key );
$iv = substr( hash( 'sha256', $secret_iv ), 0, 16 );
if( $action == 'e' )
{
$output = base64_encode( openssl_encrypt( $string, $encrypt_method, $key, 0, $iv ) );
}
else if( $action == 'd')
{
$output = openssl_decrypt( base64_decode( $string ), $encrypt_method, $key, 0, $iv );
}
return $output;
then I tried to translanguage to JS on React using CryptoJS :
import sha256 from "crypto-js/sha256";
import Base64 from "crypto-js/enc-base64";
import AES from "crypto-js/aes";
let secret_key = "thisIsK3y";
let secret_iv = "tHis1s1v";
let output = false;
let encrypt_method = "AES-256-CBC";
let key = sha256(secret_key);
let iv = String(sha256(secret_iv)).substr(0, 16);
if (action == "e") { // encrypt action
output = AES.encrypt("test", Utf8.parse(key), {
iv: Utf8.parse(iv),
}).toString();
alert(Base64.parse(output));
}
then the alert show me this encryption : fd0337c029ad25c240316a1d61db9144, then I try to decrypt in my php.but it's show me plain text seems like non-printable ascii
b"}¦7▀À4█ÍØ█ù6ÒM§Ú¡]ÙW[¸^8"
and there is PHP notice :
PHP Notice: iconv(): Detected an illegal character in input string in /var/www/html/blabla/vendor/symfony/var-dumper/Dumper/AbstractDumper.php on line 203
Anyone can help me out ?
Upvotes: 4
Views: 6878
Reputation: 49251
If the PHP code is executed with the plaintext $string = "test";
then the encryption part provides:
MWNjdVlVL1hBWGN2UFlpMG9yMGZBUT09
Regarding the PHP code the following should be noted:
base64_encode
, once implicitly by default (s. openssl_encrypt
, 4th parameter). This redundancy is not necessary, i.e. one of the two Base64 encodings should be removed. Analogous for decryption.hash
function returns by default the data hex encoded in lower case. Thus $key
is 64 bytes in size. For AES-256 OpenSSL implicitly uses only the first 32 bytes.The CryptoJS code you posted could be modified as follows to implement this functionality (JavaScript):
var Sha256 = CryptoJS.SHA256;
var Hex = CryptoJS.enc.Hex;
var Utf8 = CryptoJS.enc.Utf8;
var Base64 = CryptoJS.enc.Base64;
var AES = CryptoJS.AES;
var secret_key = 'thisIsK3y';
var secret_iv = 'tHis1s1v';
var key = Sha256(secret_key).toString(Hex).substr(0,32); // Use the first 32 bytes (see 2.)
var iv = Sha256(secret_iv).toString(Hex).substr(0,16);
// Encryption
var output = AES.encrypt("test", Utf8.parse(key), {
iv: Utf8.parse(iv),
}).toString(); // First Base64 encoding, by default (see 1.)
var output2ndB64 = Utf8.parse(output).toString(Base64); // Second Base64 encoding (see 1.)
console.log(output2ndB64); // MWNjdVlVL1hBWGN2UFlpMG9yMGZBUT09
// Decryption
var decrypted = AES.decrypt(output, Utf8.parse(key), {
iv: Utf8.parse(iv),
}).toString(Utf8);
console.log(decrypted); // test
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
taking into account the two points mentioned above for the PHP code. Like the hash
function in the PHP code, toString(Hex)
also uses lower case letters (so no conversion is necessary in this respect).
Note that in practice a static IV must not be used for security reasons. Instead, the IV should be newly generated for each encryption and sent to the recipient along with the ciphertext (the IV isn't secret). Also, using SHA256 as a key derivation function is not very secure.
Upvotes: 5