如果我有包含来自 IV 和加密数据的 base64 字符串,如何正确调用 openssl_decrypt 方法?
How to properly call openssl_decrypt method if I have base64 string which contains from IV and encrypted data?
我在 C#
中有加密和解密字符串的代码:
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);
}
}
如果你勾选 Decrypt(byte[] buffer)
,我取前 16 个字节,即 IV。
现在我想在 PHP 中实现(想象一下,我将在 C#
端编码并将其发送到在 php 上运行的服务器,我想在那里解密回来了)。作为我的 PHP 解密函数的参数将是 C# public string Encrypt(string unencrypted)
的输出。我不知何故需要获取这 16 个字节来获取 IV 和其余部分,我分别将它们作为 $data
和 $iv
参数传递给 $decrypted_data = openssl_decrypt($data, $cipher, $encryption_key, 0, $iv);
函数
我试过使用这样的东西(使用解包):
$stringValue = base64_decode($encrypted_data, true);
$integers = unpack("s*", $stringValue);
然后尝试取前 16 个数字并以某种方式用 pack 方法将它们转换回来。不过可能是我知识不够
你能帮我解决这个问题吗?
P.S。这是我根据 Ilya 的回答和评论尝试过的。
$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);
如果我调试代码并使用此代码检查 $iv
中有哪些字节:
$stringValue = base64_decode($iv, true);
$integers = unpack("C*", $encrypted_data);
与 C#
这个字节数组 byte[] iv = buffer.Take(16).ToArray();
比较,它们是相等的,那么我预计,我使用错误的 openssl_decrypt
方法
在 php 中,任何字符串都只是一个字节序列,因此您可以直接使用它,例如通过其索引访问单个字节,或使用 substr
到 trim 一些字节。示例:
$str = 'some text or binary data received by http';
$first16Bytes = substr($str, 0, 16);
首先,我遇到了如何更正从字符串中检索前 16 个字节的问题,因为我认为我做错了。感谢@Ilia Yatsenko 的回答:
$first16Bytes = substr($str, 0, 16);
但后来我意识到,我错误地使用了 openssl_decrypt()
方法。在评论中进行对话后,尤其是与@Topaco 进行对话后,我们发现了问题所在。这是工作代码:
$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);
我在 C#
中有加密和解密字符串的代码:
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);
}
}
如果你勾选 Decrypt(byte[] buffer)
,我取前 16 个字节,即 IV。
现在我想在 PHP 中实现(想象一下,我将在 C#
端编码并将其发送到在 php 上运行的服务器,我想在那里解密回来了)。作为我的 PHP 解密函数的参数将是 C# public string Encrypt(string unencrypted)
的输出。我不知何故需要获取这 16 个字节来获取 IV 和其余部分,我分别将它们作为 $data
和 $iv
参数传递给 $decrypted_data = openssl_decrypt($data, $cipher, $encryption_key, 0, $iv);
函数
我试过使用这样的东西(使用解包):
$stringValue = base64_decode($encrypted_data, true);
$integers = unpack("s*", $stringValue);
然后尝试取前 16 个数字并以某种方式用 pack 方法将它们转换回来。不过可能是我知识不够
你能帮我解决这个问题吗?
P.S。这是我根据 Ilya 的回答和评论尝试过的。
$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);
如果我调试代码并使用此代码检查 $iv
中有哪些字节:
$stringValue = base64_decode($iv, true);
$integers = unpack("C*", $encrypted_data);
与 C#
这个字节数组 byte[] iv = buffer.Take(16).ToArray();
比较,它们是相等的,那么我预计,我使用错误的 openssl_decrypt
方法
在 php 中,任何字符串都只是一个字节序列,因此您可以直接使用它,例如通过其索引访问单个字节,或使用 substr
到 trim 一些字节。示例:
$str = 'some text or binary data received by http';
$first16Bytes = substr($str, 0, 16);
首先,我遇到了如何更正从字符串中检索前 16 个字节的问题,因为我认为我做错了。感谢@Ilia Yatsenko 的回答:
$first16Bytes = substr($str, 0, 16);
但后来我意识到,我错误地使用了 openssl_decrypt()
方法。在评论中进行对话后,尤其是与@Topaco 进行对话后,我们发现了问题所在。这是工作代码:
$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);