I have code in C#
which encrypts and decrypts string:
private readonly UTF8Encoding _encoder;
private readonly ICryptoTransform _encryptor;
private readonly RijndaelManaged _rijndael;
public Crypter()
{
_rijndael = new RijndaelManaged { Key = { 1, 2, 3, 4, ..., 16 } };
_rijndael.GenerateIV();
_encryptor = _rijndael.CreateEncryptor();
_encoder = new UTF8Encoding();
}
public string Encrypt(string unencrypted)
=> Convert.ToBase64String(Encrypt(_encoder.GetBytes(unencrypted)));
private byte[] Encrypt(byte[] buffer)
{
byte[] inputBuffer = _encryptor.TransformFinalBlock(buffer, 0, buffer.Length);
return _rijndael.IV.Concat(inputBuffer).ToArray();
}
public string Decrypt(string encrypted)
=> _encoder.GetString(Decrypt(Convert.FromBase64String(encrypted)));
private byte[] Decrypt(byte[] buffer)
{
byte[] iv = buffer.Take(16).ToArray();
using (ICryptoTransform decryptor = _rijndael.CreateDecryptor(_rijndael.Key, iv))
{
return decryptor.TransformFinalBlock(buffer, 16, buffer.Length - 16);
}
}
If you check Decrypt(byte[] buffer)
, I take first 16 bytes which is IV.
Now I similar want to implement in PHP (imagine, that I will encode on C#
side and send it to server which runs on php, where I want to decrypt it back). As the param to my PHP decrypt function will be output of C# public string Encrypt(string unencrypted)
. I somehow need to get those 16 bytes to get IV and the rest part, which I respectively will pass as $data
and $iv
params to $decrypted_data = openssl_decrypt($data, $cipher, $encryption_key, 0, $iv);
function
I have tried to use something like this (using unpack):
$stringValue = base64_decode($encrypted_data, true);
$integers = unpack("s*", $stringValue);
and then tried to take 16 first numbers and somehow convert them back with pack method. But probably I have lack of knowledge.
Could you please help me with this?
P.S. This one I have tried based on Ilya's answer and comments.
$cipher = "aes-256-cbc";
$encryption_key = hex2bin(env("ENCRYPTION_KEY"));
$base64decoded = base64_decode($encrypted_data, true);
$iv = substr($base64decoded, 0, 16);
$data = substr($base64decoded, 16, strlen($base64decoded) - 16);
$decrypted_data = openssl_decrypt($data, $cipher, $encryption_key, OPENSSL_RAW_DATA, $iv);
dd($decrypted_data);
also if I debug code and check which bytes are in $iv
using this code:
$stringValue = base64_decode($iv, true);
$integers = unpack("C*", $encrypted_data);
and comparing with C#
this byte array byte[] iv = buffer.Take(16).ToArray();
, they are equals, then I expect, that I am using wrongly openssl_decrypt
method
Firstly, I was having an issue how to correct retrieve 16 first bytes from string, because I thought I was doing it incorrectly. Thanks from @Ilia Yatsenko for his answer:
$first16Bytes = substr($str, 0, 16);
But then I have realised, that I am wrongly using openssl_decrypt()
method. After having conversation in comments, particularly with @Topaco, we found what was the proble. Here is working code:
$cipher = "aes-256-cbc";
$encryption_key = hex2bin(env("ENCRYPTION_KEY"));
$base64decoded = base64_decode($encrypted_data, true);
$iv = substr($base64decoded, 0, 16);
$data = substr($base64decoded, 16, strlen($base64decoded) - 16);
$decrypted_data = openssl_decrypt($data, $cipher, $encryption_key,
OPENSSL_RAW_DATA, $iv);
dd($decrypted_data);