Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.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#_.net_Encryption - Fatal编程技术网

C# &引用;填充无效,无法删除“;使用AES管理

C# &引用;填充无效,无法删除“;使用AES管理,c#,.net,encryption,C#,.net,Encryption,我正在尝试使用AES进行简单的加密/解密,但在尝试关闭解密流时,我不断遇到异常。这里的字符串得到正确的加密和解密,然后在Console.WriteLine打印正确的字符串后,我得到加密异常“Padding was invalid and cannot remove” 有什么想法吗 MemoryStream ms = new MemoryStream(); byte[] rawPlaintext = Encoding.Unicode.GetBytes("This is annoying!");

我正在尝试使用AES进行简单的加密/解密,但在尝试关闭解密流时,我不断遇到异常。这里的字符串得到正确的加密和解密,然后在Console.WriteLine打印正确的字符串后,我得到加密异常“Padding was invalid and cannot remove”

有什么想法吗

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);
  }
}
字节[]rawData=new 字节[rawPlaintext.Length]


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

诀窍是使用
MemoryStream.ToArray()
。 我还更改了您的代码,以便它使用
加密流
进行加密和解密。而且您不需要显式调用
CryptoStream.FlushFinalBlock()
,因为它位于
using()
语句中,并且该刷新将在
Dispose()
上发生。以下内容适合我

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);
}
另外,我想您知道您将要显式地设置AES托管实例的,并使用从密码和salt派生密钥和IV

另请参见:

-

此异常可能由多个加密参数中的任何一个不匹配引起

我使用接口跟踪加密/解密方法中使用的所有参数


最后我发现我的问题是,我在设置了
键之后设置了
KeySize
属性,导致类重新生成一个随机键,而没有使用最初设置的键。

没有人回答,实际上MemoryStream.GetBuffer返回分配的缓冲区,而不是该缓冲区中的真实数据。在本例中,它返回256字节的缓冲区,而它只包含32字节的加密数据。

关于它的价值,我将记录我所面临的问题。在加密流关闭之前,我试图读取加密程序内存流。我知道这很幼稚,我浪费了一天时间调试它

    public static byte[] Encrypt(byte[] buffer, byte[] sessionKey, out byte[] iv)
    {
        byte[] encrypted;
        iv = null;
        using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider { Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7 })
        {
            aesAlg.Key = sessionKey;
            iv = aesAlg.IV;
            ICryptoTransform encryptor = aesAlg.CreateEncryptor(sessionKey, iv);

            // Create the streams used for encryption.
            using (MemoryStream msEncrypt = new MemoryStream())
            {
                using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                {
                    csEncrypt.Write(buffer, 0, buffer.Length);

                    //This was not closing the cryptostream and only worked if I called FlushFinalBlock()
                    //encrypted = msEncrypt.ToArray(); 
                }

                encrypted = msEncrypt.ToArray();

                return encrypted;
            }
        }
    }

在cypto流关闭后移动加密程序内存流读取解决了该问题。如前所述。如果使用
using
块,则无需调用
FlushFinalBlock()

如其他人所述,如果密钥/iv未正确初始化以进行解密,则可能会发生此错误。在我的情况下,我需要从一些较大的缓冲区复制密钥和iv。以下是我做错的事情:

无效:(填充无效,无法删除)

有效:

var key = new byte[keySize];
Buffer.BlockCopy(someBuffer, keyOffset, key, 0, keySize);
aes.Key = key;

var iv = new byte[ivSize];
Buffer.BlockCopy(someBuffer, ivOffset, iv, 0, ivSize);
aes.IV = iv;

OP没有犯这个错误,但这可能有助于其他人看到同样的错误。

我也有同样的问题,但使用RijndaelManaged(也是对称的),不知道发生了什么。原来
MemoryStream.GetBuffer()
得到的是一个未刷新的数据版本,最后的大部分数据块都是空的,这会干扰我的填充
MemoryStream.ToArray()
获取实际数组。非常感谢这个解决方案!这是迄今为止我见过的最好/最小的实现。很好地调用了
Dispose
。在处理加密流之前,我正在给ToArray()女士打电话。把那个条线移到外面,用它为我修好了。哦,我的天,万分感谢@cheeso!在解密和存储stream.ToArray()时写入加密流。。。。再次万分感谢!这就结束了10个小时的头发拉扯!我的问题是在设置密钥后设置密钥大小,谢谢+非常感谢你,如果可以的话,我会投你100票。我花了一天多的时间试图找出我无法正确解密的原因,结果是我在代码中的密钥之后设置了密钥大小。Security.Cryptography.Debug是否仍然是最新的?自2010年以来似乎没有任何变化你救了我一天
var key = new byte[keySize];
Buffer.BlockCopy(someBuffer, keyOffset, key, 0, keySize);
aes.Key = key;

var iv = new byte[ivSize];
Buffer.BlockCopy(someBuffer, ivOffset, iv, 0, ivSize);
aes.IV = iv;