Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/tfs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#:AES错误:填充无效,无法删除。相同的钥匙和所有东西,救命_C#_Aes_Padding - Fatal编程技术网

C#:AES错误:填充无效,无法删除。相同的钥匙和所有东西,救命

C#:AES错误:填充无效,无法删除。相同的钥匙和所有东西,救命,c#,aes,padding,C#,Aes,Padding,我对C#很陌生,所以请对我耐心点。我知道这个问题被问了很多次,但我找不到问题的答案 我正在保存一些数据,在将其写入文件之前,我将其转换为二进制并存储在数组中,然后对数组进行加密并写入文件。我加密数据块(32字节)。以同样的方式,我读取32字节的数据块,然后解密这些数据,然后重复这个过程直到文件结束。但在解密时会抛出以下错误: 填充无效,无法删除。 我使用相同的钥匙和iv(在我开始工作之前,硬编码) 这是我的加密代码,可以正常工作: //result byte[]

我对C#很陌生,所以请对我耐心点。我知道这个问题被问了很多次,但我找不到问题的答案

我正在保存一些数据,在将其写入文件之前,我将其转换为二进制并存储在数组中,然后对数组进行加密并写入文件。我加密数据块(32字节)。以同样的方式,我读取32字节的数据块,然后解密这些数据,然后重复这个过程直到文件结束。但在解密时会抛出以下错误:

填充无效,无法删除。

我使用相同的钥匙和iv(在我开始工作之前,硬编码)

这是我的加密代码,可以正常工作:

        //result
        byte[] data = new byte[32];

        //setup encryption (AES)
        SymmetricAlgorithm aes = Aes.Create();
        byte[] key = { 145, 12, 32, 245, 98, 132, 98, 214, 6, 77, 131, 44, 221, 3, 9,50};
        byte[] iv = { 15, 122, 132, 5, 93, 198, 44, 31, 9, 39, 241, 49, 250, 188, 80, 7 };
        ICryptoTransform encryptor = aes.CreateEncryptor(key, iv);

        FileStream fStream = new FileStream(file, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read, 1024, false);

        //prepare data to write (byte array 'data') ...

        //encrypt
               MemoryStream m = new MemoryStream();
               using (Stream c = new CryptoStream(m, encryptor, CryptoStreamMode.Write))
                   c.Write(data, 0, data.Length);
               data = m.ToArray();
               fStream.Write(data, 0, data.Length);
这是我的解密代码:

FileStream fStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, false);

            //setup encryption (AES)
            SymmetricAlgorithm aes = Aes.Create();
            byte[] key = { 145, 12, 32, 245, 98, 132, 98, 214, 6, 77, 131, 44, 221, 3, 9, 50 };
            byte[] iv = { 15, 122, 132, 5, 93, 198, 44, 31, 9, 39, 241, 49, 250, 188, 80, 7 };
            ICryptoTransform decryptor = aes.CreateDecryptor(key, iv);

            //result
            byte[] data = new byte[32];

            //loop for reading the whole file ...
            int len = fStream.Read(data, 0, 32);

            //decrypt
                MemoryStream m = new MemoryStream();
                using (Stream c = new CryptoStream(m, decryptor, CryptoStreamMode.Write))
                    c.Write(data, 0, data.Length); //The exception is thrown in this line                  
                data = m.ToArray();

                //using the decrypted data and then looping back to reading and decrypting...
我尝试了我能想到的一切(这并不多,因为我对密码学非常陌生),我到处搜索,但我找不到解决问题的方法。简而言之,我还自学了C#一书

如果有人知道为什么会发生这种情况,我会非常感激,因为我不知道

谢谢你的时间和回答

编辑: 加密数据的大小似乎是48字节(比原始数据多12字节)。为什么会这样?我认为只有当字节不是块大小的倍数(16字节,我的数据是32字节)时,它才会添加字节。数据总是更大,并且不断增加(为了正确读取和解密,我需要知道这一点)


注意:我不能直接使用其他流,因为我需要控制输出格式,而且我认为在内存中加密更安全、更快。

您似乎将明文的长度视为密文的长度。这不是一个安全的假设

为什么要在
文件流
内存流
之间进行复制,您可以将
文件流
直接传递给加密机/解密机


在PKCS7中,至少有一个填充字节(用于存储填充字节的数量)。因此,输出大小将是
Ceil16(input.Length+1)
,或
(input.Length&~15)+1

,简称AES以16字节的块对消息进行加密。如果消息不是16字节的偶数倍,则最后一个块的算法需要稍微不同;具体来说,最后一个块必须使用算法已知的填充值(通常为零,有时为空格字符值)进行“填充”

通过将数据放入一个固定长度的字节数组,您可以自己完成这项工作。您自己填充了数据,但解密程序现在正在尝试对最后一个块进行反填充,并获取它无法识别的字节值,作为加密程序对应方可能添加的填充

这个键不是用来填充信息的。您可以使用BitConverter类在IConvertible类型(值类型和字符串)之间转换字节数组,然后使用它而不是滚动您自己的字节数组。然后,当您解密时,您可以从解密流中读取密文长度,但不要期望解密结果中有那么多实际字节。

根据您的编辑:

编辑:加密数据的大小似乎是48字节(比原始数据多12字节)。为什么会这样?我认为只有当字节不是块大小的倍数(16字节,我的数据是32字节)时,它才会添加字节。数据总是更大,并且不断增加(为了正确读取和解密,我需要知道这一点)

如果加密数据为48字节,则比原始数组大16字节。这是有意义的,因为使用pad的算法会填充数据,因为默认值为(即使大小与块大小匹配,因为它会填充到块大小的下一个倍数)。如果希望保留32字节,只需将


我想Ben就在这里,你能检查一下文件以查看加密数据的输出吗(即,二进制文件是否大于32字节?)。您需要读取整个文件并解密。other@Ben:48字节比您的输入多16字节,而不是12字节。是什么阻止您仅使用加密流的长度?应该只需要几个额外的字节就可以将长度保存到加密数据嵌入的任何结构/包装信封/pdu中。@SwDevMan81我在加密后和写入文件之前检查了数组,它有48个字节大,是的,还有16个而不是12=)。我不能,因为有时候文件会变得非常大,我只需要从一个位置计算一个特殊的数据块,因此我必须能够以块的方式解密文件@Ben Voigt如果它总是(对于相同的块大小)在大小上产生相同的“增量”,那么我可以适应,但我发现这些东西加起来很快,这是浪费空间。这是有道理的。在这种情况下,我想我会关闭填充,否则你将永远不知道从哪里读取。在他的算法中,他将自己的字节数组精确地滚动到32字节,这是块大小的偶数倍,因此密文实际上将与输入字节数组完全匹配。问题是这样做,他自己做了“填充”,这会混淆解密步骤。@Keith:你绝对确定加密机不会生成额外的头块或类似的东西吗?所以如果我创建一个31字节数组,我可以在解密后传递32字节?其他@Ben:我预测是的,你可以。非常感谢,这解决了我的问题。所以它总是垫到块大小的下一个倍数?因为“KeithS”发布:如果你的消息不是16字节的偶数倍。。。一定要公平吗?顺便说一句,它只是aes.Padding=…@Ben-它将填充到下一个块大小,因此如果设置了它,它总是要填充。我更新了代码,谢谢。很高兴这有帮助。看来我忘了运行这个方法,它似乎认为它是有效的,但是
aes.Padding = PaddingMode.None;