C#:AES 错误:填充无效且无法删除。相同的钥匙和一切,帮助

问题描述 投票:0回答:4

我对 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# in a Nutshell》这本书。 如果有人知道为什么会发生这种情况,我将非常感激,因为我没有任何想法。

感谢您的时间和回答。

编辑: 看来加密数据的大小是48字节(比原来多了12字节)。为什么会这样?我认为它只会添加字节,如果它们不是块大小的倍数(16 字节,我的数据是 32 字节)。数据是否总是较大,并且不断增加(我需要知道这一点才能正确读取和解密)。

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

c# aes padding
4个回答
8
投票

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

如果加密数据为 48 字节,则比原始数组大 16 字节。这是有道理的,因为算法会填充数据,因为默认值为
PKCS7

(即使大小与块大小匹配,因为它会填充到块大小的next倍数)。如果您希望保留 32 个字节,只需将 Padding 更改为 None aes.Padding = PaddingMode.None;



4
投票

为什么要在

FileStream

MemoryStream
之间复制,你可以直接将一个
FileStream
传递给加密器/解密器。


在PKCS7中,至少有1个填充字节(用于存储填充字节数)。因此输出大小将为

Ceil16(input.Length + 1)

(input.Length & ~15) + 1
    


3
投票

您自己将数据放入固定长度的字节数组中。您自己填充了数据,但解密器现在正在尝试去填充最后一个块并获取它无法识别为加密器对应部分将添加的填充的字节值。

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


0
投票

© www.soinside.com 2019 - 2024. All rights reserved.