【问题标题】:Padding invalid when decrypting stream解密流时填充无效
【发布时间】:2011-02-28 23:34:47
【问题描述】:

我正在尝试使用 AesManaged 加密流(来自文件)。我可以毫无错误地加密文件,但在解密时我得到以下 CryptographicException:

填充无效,不能 删除。

处理 CryptoStream 时引发异常。我使用以下加密输入数据:

public byte[] Encrypt(Stream plain)
{
    // Create a decrytor to perform the stream transform.
    using( var msEncrypt = new MemoryStream() )
    {
        using (ICryptoTransform encryptor = _myAes.CreateEncryptor(_myAes.Key, _myAes.IV))
        using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
        using (BinaryWriter swEncrypt = new BinaryWriter(csEncrypt))
        {
            int buf_size = 32768;
            byte[] buffer = new byte[buf_size];
            int read = 0;
            while ((read = plain.Read(buffer, 0, buf_size)) > 0)
            {
                swEncrypt.Write(buffer, 0, read);
            }
        }

        return msEncrypt.ToArray();
    }
}

还有这个解密数据:

public byte[] Decrypt(Stream cipherText)
{

    using (MemoryStream ms = new MemoryStream())
    {
        // Create a decrytor to perform the stream transform.
        using (ICryptoTransform decryptor = _myAes.CreateDecryptor(_myAes.Key, _myAes.IV))
        using (CryptoStream csDecrypt = new CryptoStream(ms, decryptor, CryptoStreamMode.Write))
        using (BinaryWriter swDecrypt = new BinaryWriter(csDecrypt))
        {
            int buf_size = 32768;
            byte[] buffer = new byte[buf_size];
            int read = 0;
            while ((read = cipherText.Read(buffer, 0, buf_size)) > 0)
            {
                swDecrypt.Write(buffer, 0, read);
            }
        }

        return ms.ToArray();
    }
}

任何关于为什么会出现这个异常的想法都会很棒。谢谢

更新

这里是创建 Aes 对象的地方,注意 Key 和 IV 只是暂时设置为它们的当前值,它不是真正要使用的键:

private Crypto()
{
    _myAes = new AesManaged();
    _myAes.Padding = PaddingMode.PKCS7;
    _myAes.KeySize = 128;
    _myAes.Key = Enumerable.Repeat((byte)'B', 128 / 8).ToArray();
    _myAes.IV = Enumerable.Repeat((byte)'C', 128 / 8).ToArray();
}

【问题讨论】:

  • 您能展示一下您是如何创建 _myAes 的吗?
  • @SimonJ - 我在实例化该对象的地方添加了 sn-p。
  • 这个错误可能是由很多原因引起的。很可能是您使用了错误的密钥或 IV。它也可能是由数据损坏引起的。
  • @GregS - 我将其更改为使用上面显示的固定键和 IV,所以它们应该是相同的。我正在获取文件并将其上传到 AmazonS3,并且我已经尝试了几次,所以我不知道数据会如何损坏,除非我做错了什么。

标签: c# encryption aes


【解决方案1】:

过去,当我尝试解密长度不是 16 字节的倍数的缓冲区时,我遇到了这个异常。

您是否尝试在处理之前在CryptoStream 上调用Flush?可能,如果它没有被刷新,那么它最终会尝试解密一个长度不对齐的缓冲区。

另一个注意事项 - 我不知道这是否能解决您的问题,但是当您创建 CryptoStream 以解密缓冲区时,您不应该使用 CryptoStreamMode.Read 而不是 CryptoStreamMode.Write?

【讨论】:

  • 我最初尝试使用读取模式的方式,但我得到了同样的异常。我尝试在加密和解密时在CryptoStream 上调用Flush 和FlushFinalBlock,但仍然抛出相同的异常。
  • 另外我应该指出,当我将其更改为 CryptoSteamMode.Read 时,它会在我从流中读取而不是在处理它时抛出异常。
【解决方案2】:

确保在写入端干净地完成CryptoStream。您可能需要调用 FlushFinalBlock() 以确保写入流结束填充 - 否则,您可能最终会丢失流的最后一个块,这将导致无效填充异常。

【讨论】:

  • 我很确定在处理 CryptoStream 时会调用 FlushFinalBlock,但为清楚起见,恕我直言,它应该明确完成。
  • 我尝试在Encrypt 方法中显式调用FlushFinalBlock(),但仍然遇到同样的异常。
【解决方案3】:

我不知道 4 年后发布内容是否仍然相关,但您应该尝试将填充设置为无。我在 3DES 上遇到了同样的问题,并且问题得到了解决(但要确保要解密的数据长度是正确的......)

private Crypto()
{
    _myAes = new AesManaged();
    _myAes.Padding = PaddingMode.none; //rather than _myAes.Padding = PaddingMode.PKCS7;
    _myAes.KeySize = 128;
    _myAes.Key = Enumerable.Repeat((byte)'B', 128 / 8).ToArray();
    _myAes.IV = Enumerable.Repeat((byte)'C', 128 / 8).ToArray();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-15
    • 2019-12-23
    • 1970-01-01
    • 2021-03-15
    • 2012-12-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多