关于c#:“填充无效,无法删除”使用AesManaged

“Padding is invalid and cannot be removed” using AesManaged

我正在尝试使用aesmanaged进行简单的加密/解密,但在尝试关闭解密流时,我总是遇到一个异常。这里的字符串得到了正确的加密和解密,然后在console.writeline打印正确的字符串后,我得到了cryptographicException"padding was invalid and cannot be removed"。

有什么想法吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
MemoryStream ms = new MemoryStream();
byte[] rawPlaintext = Encoding.Unicode.GetBytes("This is annoying!");

using (Aes aes = new AesManaged())
{
  aes.Padding = PaddingMode.PKCS7;
  aes.Key = new byte[128/8];
  aes.IV = new byte[128/8];

  using (CryptoStream cs = new CryptoStream(ms, aes.CreateEncryptor(),
                                            CryptoStreamMode.Write))
  {
    cs.Write(rawPlaintext, 0, rawPlaintext.Length);
    cs.FlushFinalBlock();
  }

  ms = new MemoryStream(ms.GetBuffer());
  using (CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(),
                                            CryptoStreamMode.Read))
  {
    byte[] rawData = new byte[rawPlaintext.Length];
    int len = cs.Read(rawData, 0, rawPlaintext.Length);
    string s = Encoding.Unicode.GetString(rawData);
    Console.WriteLine(s);
  }
}

诀窍是使用MemoryStream.ToArray()。我还修改了您的代码,以便它使用CryptoStream在加密和解密中进行写入。你不需要明确地调用CryptoStream.FlushFinalBlock(),因为你在using()语句中有它,而这个刷新将发生在Dispose()上。以下是我的作品。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
byte[] rawPlaintext = System.Text.Encoding.Unicode.GetBytes("This is all clear now!");

using (Aes aes = new AesManaged())
{
    aes.Padding = PaddingMode.PKCS7;
    aes.KeySize = 128;          // in bits
    aes.Key = new byte[128/8];  // 16 bytes for 128 bit encryption
    aes.IV = new byte[128/8];   // AES needs a 16-byte IV
    // Should set Key and IV here.  Good approach: derive them from
    // a password via Cryptography.Rfc2898DeriveBytes
    byte[] cipherText= null;
    byte[] plainText= null;

    using (MemoryStream ms = new MemoryStream())
    {
        using (CryptoStream cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
        {
            cs.Write(rawPlaintext, 0, rawPlaintext.Length);
        }

        cipherText= ms.ToArray();
    }


    using (MemoryStream ms = new MemoryStream())
    {
        using (CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write))
        {
            cs.Write(cipherText, 0, cipherText.Length);
        }

        plainText = ms.ToArray();
    }
    string s = System.Text.Encoding.Unicode.GetString(plainText);
    Console.WriteLine(s);
}

另外,我想您知道您需要显式设置aesmanaged实例的模式,并使用system.security.cryptography.rfc2898派生字节从密码和salt派生密钥和iv。

参见:-审美管理


此异常可能是由于许多加密参数中的任何一个不匹配造成的。

我使用security.cryptography.debug接口跟踪加密/解密方法中使用的所有参数。

最后我发现我的问题是,我在设置Key之后设置了KeySize属性,导致类重新生成随机密钥,而不使用最初设置的密钥。


没有人回答,实际上memoryStream.getBuffer返回分配的缓冲区,而不是该缓冲区中的实际数据。在这种情况下,它返回256字节的缓冲区,而它只包含32字节的加密数据。


byte[] rawData = new
byte[rawPlaintext.Length];

您需要读取缓冲区的长度,这可能包括必要的填充(IIRC,已经有几年了)。