无法解密AES加密字符串

问题描述 投票:1回答:1

我正在使用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."

这可能有什么问题?

php powershell encryption aes
1个回答
1
投票

编辑#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());
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.