我正在使用openssl_encrypt加密字符串并在powershell中解密它们
在PHP中
$data = "helloWorld";
$key = 'CefaiNooH4oi6oje';
$iv = 'Choodub8ahd4choo';
$data = openssl_encrypt($data, 'AES-256-CBC', $key, 0, $iv);
echo base64_encode($data);
在Powershell
$data = "dnQvNEhEczBnQ0F5OEQ4Yi9tOUY4Zz09"
$data = [System.Convert]::FromBase64String($data)
$aesManaged = New-Object "System.Security.Cryptography.AesManaged"
$aesManaged.Mode = [System.Security.Cryptography.CipherMode]::CBC
$aesManaged.Padding = [System.Security.Cryptography.PaddingMode]::Zeros
$aesManaged.BlockSize = 128
$aesManaged.KeySize = 256
$aesManaged.Key = [system.Text.Encoding]::UTF8.GetBytes("CefaiNooH4oi6oje")
$aesManaged.IV = [system.Text.Encoding]::UTF8.GetBytes("Choodub8ahd4choo")
$decryptor = $aesManaged.CreateDecryptor();
$clear = $decryptor.TransformFinalBlock($data, 16, $data.Length - 16);
[System.Text.Encoding]::UTF8.GetString($clear).Trim([char]0)
然后我收到一个错误:
Exception calling "TransformFinalBlock" with "3" argument(s): "The input data is not a complete block."
这可能有什么问题?
编辑#2
令我兴奋的是,当你真正得到解密代码时,我已经弄明白为什么垃圾会出现,我忽略了回答你为什么会收到错误的问题:
Exception calling "TransformFinalBlock" with "3" argument(s): "The input data is not a complete block."
问题是你传递了一大块不足以成为block
的数据。使用您要转换为字节的原始字符串,您将得到一个24字节的数组,但块大小为16字节,因此您需要一个长度为16的倍数的数组。使用正确的字符串vt/4HDs0gCAy8D8b/m9F8g==
,你将获得一个16的数组,这将是有效的(虽然你需要进行TransformFinalBlock
调用的一个小修正,你想调用它的偏移量为0和输入数组的长度 - 我已经更新了我的解决方案,以显示这一点)。
结束编辑#2
我想到了!!!!
所以,第一个问题在这里:
echo base64_encode($data);
您从$data
返回的openssl_encrypt值已经是base64编码的,因此无需再次编码。如果你删除那一行,你会得到这个字符串vt/4HDs0gCAy8D8b/m9F8g==
(参见ideone链接)
如果您需要证明发生了这种情况,这里有另一个ideone链接,显示如果您从Base64转换字符串然后将这些字节转换为字符串会发生什么,您将获得从调用中出来的原始Base64编码字符串to openssl_encrypt。
现在对于解密部分(注意,我将在C#中发布代码但是转换为PowerShell应该相当简单,如果有问题评论,我会尽力帮助)。我通常会创建一个解密器并使用流,但我想要适合您的代码,所以我使用的是TransformBlock
方法。
string result = null;
using (var aes = new AesManaged())
{
// openssl_encrypt will zero pad a key that is not the correct length
var key = Encoding.UTF8.GetBytes("CefaiNooH4oi6oje");
if (key.Length < 32)
{
var temp = new byte[key.Length + (32 - key.Length % 32)];
Array.Copy(key, temp, key.Length);
key = temp;
}
var iv = Encoding.UTF8.GetBytes("Choodub8ahd4choo");
aes.Mode = CipherMode.CBC;
aes.KeySize = 256;
aes.Key = key;
aes.IV = iv;
aes.Padding = PaddingMode.Zeros;
var cipher = Convert.FromBase64String("vt/4HDs0gCAy8D8b/m9F8g==");
using (var decryptor = aes.CreateDecryptor())
{
var buffer = decryptor.TransformFinalBlock(cipher, 0, cipher.Length);
result = Encoding.UTF8.GetString(buffer);
}
}
编辑使用流添加解密代码(我通常在C#中执行此操作)
using (var aes = new AesManaged())
{
// See sample above for setup code, omitted for brevity
using (var dest = new MemoryStream())
using (var input = new MemoryStream(cipher))
using (var cs = new CryptoStream(input, aes.CreateDecryptor(), CryptoStreamMode.Read))
{
var buffer = new byte[1024];
var read = cs.Read(buffer, 0, buffer.Length);
while(read > 0)
{
dest.Write(buffer, 0, read);
read = cs.Read(buffer, 0, buffer.Length);
}
dest.Flush();
result = Encoding.UTF8.GetString(dest.ToArray());
}
}