【问题标题】:CryptographicEngine.Decrypt method return an error in a c# UWP appCryptographicEngine.Decrypt 方法在 c# UWP 应用程序中返回错误
【发布时间】:2015-10-25 20:30:26
【问题描述】:

我不明白为什么这段代码会返回错误:

Data error (cyclic redundancy check). (Exception from HRESULT: 0x80070017)

因为 Silverlight 平台的等效代码不会引发异常。这是下面的 UWP c# 代码:

public static async Task<Stream> Decrypt(Stream source,
            IBuffer easKey,IBuffer IV, byte[] masterKey)
        {
            try
            {

                SymmetricKeyAlgorithmProvider aes = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7);
                if ((source.Length % aes.BlockLength) != 0)
                {
                    var temp = new MemoryStream();
                    temp.SetLength(source.Length + (aes.BlockLength - source.Length % aes.BlockLength));
                    source.CopyTo(temp);
                    source = temp;
                }

                CryptographicKey symmKey = aes.CreateSymmetricKey(easKey);
                var sarray = ((MemoryStream)source).ToArray();
                IBuffer resultBuffer = CryptographicEngine.Decrypt(symmKey,sarray.AsBuffer(), IV);
                byte[] result;
                CryptographicBuffer.CopyToByteArray(resultBuffer, out result);

                return new MemoryStream(result);


            }
            catch (Exception e)
            {
                await new MessageDialog(e.StackTrace, e.Message).ShowAsync();
            }
            return null;

        }

【问题讨论】:

  • 如果你在解密数据我不明白为什么你需要检查数据的长度是块长度的倍数 - 相应的加密函数应该应用填充,所以密文将 总是块大小。

标签: c# windows visual-studio-2015 uwp


【解决方案1】:

vcsjones 在您的问题下的评论中提出了重要的一点。如果您检查数据长度是否是块长度的偶数倍,但事实并非如此,那么您应该在数据错误时立即抛出异常。因为使用 AES 加密的任何东西都不会导致任何与块长度的偶数倍不同的东西。即使是空字符串也会产生一个 1 块长的密文。

话虽如此,您已经准备好使用 PKCS7 填充来解密块的加密算法。另一方面,如果你得到一个短块,你就是将它复制到一个正确长度的 MemoryStream 中。我假设最后一个字节为零。所以该块不是有效的密文块。

PKCS7 填充添加 X 个字节以获得块大小的偶数倍,并且每个字节都是相同的数字。因此,如果您的块大小为 16 字节(128 位),而最后一个块仅包含 10 字节的真实信息,则最后 6 个字节将填充为 0x06 0x06 0x06 0x06 0x06 0x06。

不过,这里的关键在于,此填充是在加密之前添加到纯文本中的。您不能简单地将填充添加到部分密文块的末尾并能够对其进行解密。这些强加密算法的本质是块中任何给定位的最终值实际上是块中每个其他位的函数。因此,如果您丢失了该区块的任何部分,您将无法挽回地丢失整个区块。

现在,如果您确实需要尽可能多地解密消息,请丢弃部分块(正如我上面提到的那样,无论如何您永远不会解密它)。将其替换为完整的 0x10 块(重复 16 次)。这告诉算法您恰好有 X 个纯文本块,并且根据 PKCS7,您添加了完全符合 PKCS7 的填充块。这将允许您解密除部分消息块之外的所有内容。

编辑说您应该使用相同的密钥加密填充块并将其附加到密文中,以便能够解密除部分块之外的所有块。但这无论如何都不是最简单的方法。在您的位置,我只需将解密设置更改为 padding = None。再次丢弃部分块,其余的应该解密没有问题,只要它没有损坏。

【讨论】:

  • 我添加了数据长度检查以确保没有因此引发异常,但即使我删除它也会发生相同的错误。但是我不知道这个检查更改密文。
猜你喜欢
  • 2021-04-03
  • 2013-06-12
  • 2021-11-29
  • 1970-01-01
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多