简体   繁体   English

CryptographicEngine.Decrypt方法在ac#UWP应用中返回错误

[英]CryptographicEngine.Decrypt method return an error in a c# UWP app

I don't undrestand why this code return an error: 我不明白为什么这段代码会返回错误:

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

because the equivalent code from Silverlight Platform does not raise an exception.This is the UWP c# code below: 因为Silverlight Platform中的等效代码不会引发异常。这是下面的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;

        }

vcsjones hit an important point in the comment under your question. vcsjones在您的问题下的评论中占据了重要位置。 If you check for the data length to be an even multiple of the block length and it's not, you should throw an exception right then that the data is bad. 如果您检查数据长度是否为块长度的偶数倍,而不是块长度的倍数,则应立即抛出异常,表明数据不正确。 Because nothing encrypted with AES will result in anything different from an even multiple of the block length ever. 因为用AES加密的任何东西都不会导致与块长度的偶数倍不同的东西。 Even the empty string produces a 1-block-long cipher text. 即使是空字符串也会产生一个1块长的密文。

Having said that, you have your encryption algorithm prepared to decrypt blocks with PKCS7 padding. 话虽如此,您已经准备好使用PKCS7填充解密块的加密算法。 And on the other hand, if you get a short block, you are copying it into a MemoryStream that is the correct length. 另一方面,如果得到一个较短的块,则将其复制到正确长度的MemoryStream中。 I assume the last bytes are zeros. 我假设最后一个字节为零。 So that block is not a valid cipher text block. 因此,该块不是有效的密文块。

PKCS7 padding adds X number of bytes to get the even multiple of the block size, and each of those bytes is that same number. PKCS7填充将X字节数相加以获得块大小的偶数倍,并且这些字节中的每个字节都是相同的数。 So if you have a block size of 16 bytes (128 bits) and your last block only contains 10 bytes of real information, you would have the last 6 bytes padded as 0x06 0x06 0x06 0x06 0x06 0x06. 因此,如果块大小为16个字节(128位),而最后一个块仅包含10个字节的实际信息,则将最后6个字节填充为0x06 0x06 0x06 0x06 0x06 0x06。

Critical here, though, is that this padding is added to the plain text before encryption. 不过,关键是在加密之前,将此填充添加到纯文本中。 You cannot simply add the padding to the end of a partial block of cipher text and be able to decrypt it. 您不能简单地将填充添加到部分密文的末尾并能够对其进行解密。 It is the nature of these strong encryption algorithms that the final value of any given bit in the block is a function of literally every other bit in the block. 这些强加密算法的本质是,块中任何给定位的最终值实际上是该块中其他所有位的函数。 So if you lost any portion of that block, you lost the whole block irretrievably. 因此,如果丢失了该块的任何部分,则将无法挽回地丢失整个块。

Now if you really need to decrypt as much of the message as you can, throw away the partial block (you'll never decrypt it anyway as I mentioned above). 现在,如果您确实确实需要尽可能多地解密消息,则丢弃部分块(无论如何我都不会像上面提到的那样解密它)。 Replace it with a full block of 0x10 (repeated 16 times). 用0x10的完整块替换它(重复16次)。 This tells the algorithm that you had exactly X number of blocks of plain text and, per PKCS7, you added exactly an entire block of PKCS7-compliant padding. 这告诉算法,您有正好为X数量的纯文本块,并且对于每个PKCS7,您正好添加了整个与PKCS7兼容的填充块。 This will allow you to decrypt all but the partial block of the message. 这将允许您解密除消息的部分块以外的所有块。

Editing to say you should encrypt the padding block using the same key and tack it to the cipher text to be able to decrypt all but the partial block. 编辑说您应该使用相同的密钥对填充块进行加密,并将其附加到密文上,以便能够解密除部分块以外的所有块。 But that is not the easiest way anyway. 但这毕竟不是最简单的方法。 In your place I would just change my decrypt settings to padding = None. 在您的位置,我只需将解密设置更改为padding = None。 Again throw away the partial block, and the rest should decrypt without a problem as long as it is not corrupted. 再次丢弃该部分块,其余部分只要没有损坏就应该解密而没有问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM