I've PHP code that have 2 functions there are encryption and decryption that using openSSL, actually before I refactored it, I encoded the openSSL result to base64, cause it too long I change to compress using zlib (gzdeflate, gzinflate) then convert the last result to hexadecimal.
here is my PHP Code, it's working fine on PHP:
$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 );
$action = 'e';
$string = "33f6f1d3ebe5b9da5fd0e3a1c7dd71c6e484be914731cf96adac0c00" //decrypted = "test"
if( $action == 'e' )
{
$output = bin2hex(gzdeflate( gzdeflate(openssl_encrypt( $string, $encrypt_method, $key, 0, $iv ), 9), 9) );
}
else if( $action == 'd' )
{
if (!empty($string))
$output = openssl_decrypt( gzinflate(gzinflate(pack("H*", $string ) ) ), $encrypt_method, $key, 0, $iv );
}
echo $output; // output : "test", it's working fine on PHP
then I tried to translanguage to JS on React and made simple utils, here is my JS code so far, :
let secret_key = "thisIsK3y";
let secret_iv = "tHis1s1v";
var output = false;
let encrypt_method = "AES-256-CBC";
let key = String(sha256(secret_key)).toString(Hex).substr(0, 32);
let iv = String(sha256(secret_iv)).toString(Hex).substr(0, 16);
if (action == 'd') { // Decryption
let enc = gzinflate(gzinflate(hex2bin(string)));
enc = enc.toString(Utf8);
let decrypted = AES.decrypt(enc, Utf8.parse(key), {
iv: Utf8.parse(iv),
}).toString(Utf8);
console.log('sss', hex2bin('33f6f1d3ebe5b9da5fd0e3a1c7dd71c6e484be914731cf96adac0c00'));
debugger;
output = decrypted;
}
I splitted gzinfalte, gzdeflate, hex2bin, bin2hex method to another JS file called string.js and import some packages CryptoJS and PakoJS
string.js contains some methods like this :
export function gzdeflate(str) {
return pako.deflateRaw(str);
}
export function gzinflate(str) {
return pako.inflateRaw(str);
}
export function bin2hex(s) {
let i
let l
let o = ''
let n
s += ''
for (i = 0, l = s.length; i < l; i++) {
n = s.charCodeAt(i)
.toString(16)
o += n.length < 2 ? '0' + n : n
}
return o
}
export function hex2bin(hex) {
let bytes = [], str;
for(var i=0; i< hex.length-1; i+=2){
bytes.push(parseInt(hex.substr(i, 2), 16));
}
str = String.fromCharCode.apply(String, bytes);
return str;
}
when try to debug it, there is no error on hex2bin method
console.log(hex2bin('33f6f1d3ebe5b9da5fd0e3a1c7dd71c6e484be914731cf96adac0c00'));
BUT, when I try to convert the binary to gzinflate it's show me error
console.log(gzinflate(gzinflate(hex2bin(33f6f1d3ebe5b9da5fd0e3a1c7dd71c6e484be914731cf96adac0c00))))
Cannot read property 'ciphertext' of undefined
and when I try to change the secret_key and iv there is error to :
let secret_key = 'ffffffffffffffffffffffff{Curi}ty';
let secret_iv = 'ffffffffffffffffffffffff{Curi}ty';
show me error
Error: invalid stored block lengths
Anyone can help me out ?
I'm no PHP expert but I have others suggest that PHP may be truncating some keys for you.
I suggest making sure the key generation functions are behaving the same for you in both languages and make sure they are both just 32 bytes long.
I want to point out another problem that I see in your code. While it will work, you are degrading the security of your encryption.
Any time you take a 32 byte binary value, convert to HEX then take only 32 characters of the hex output, you have significantly reduced the strength of your key. Find a way to keep as byte value.
You are trying to create a 256 bit key (32 bytes with 256 possible values for each byte). You are actually creating a 32 character string and each character has only 16 possible values (0-1a-f). You have changed your key security of your encryption key from the intended 256^32 (1.1E77) to 16^32 (3.4E38).
Find a way to use the byte values produced by SHA256.