0

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

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;

        }
4

1 回答 1

0

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

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

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

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

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

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

于 2015-08-03T21:23:37.963 回答