为什么我的AES解密数据的末尾有垃圾字节?

时间:2019-02-01 05:03:08

标签: c# encryption .net-core aes aescryptoserviceprovider

我正在尝试使用AesCryptoProvider加密和解密字节数组。

这是我的加密和解密方法:

public static byte[] EncryptAes(byte[] data, out byte[] key, out byte[] iv)
{
    if (data == null || data.Length <= 0)
        throw new ArgumentNullException("data");

    try
    {
        using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
        {
            aesAlg.KeySize = 256;
            aesAlg.BlockSize = 128;
            aesAlg.Padding = PaddingMode.PKCS7;
            aesAlg.Mode = CipherMode.CBC;
            aesAlg.GenerateKey();
            aesAlg.GenerateIV();

            key = aesAlg.Key;
            iv = aesAlg.IV;

            using (MemoryStream msEncrypt = new MemoryStream())
            {
                using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, aesAlg.CreateEncryptor(), CryptoStreamMode.Write))
                {
                    csEncrypt.Write(data, 0, data.Length);
                }

                return msEncrypt.ToArray();
            }
        }
    }
    catch (CryptographicException e)
    {
        Log.Error(e);
        key = null;
        iv = null;
        return null;
    }
}

public static byte[] DecryptAes(byte[] encryptedData, byte[] key, byte[] iv)
{
    if (encryptedData == null || encryptedData.Length <= 0)
        throw new ArgumentNullException("encryptedData");
    if (key == null || key.Length <= 0)
        throw new ArgumentNullException("key");
    if (iv == null || iv.Length <= 0)
        throw new ArgumentNullException("iv");

    try
    {
        using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
        {
            aesAlg.KeySize = 256;
            aesAlg.BlockSize = 128;
            aesAlg.Padding = PaddingMode.PKCS7;
            aesAlg.Mode = CipherMode.CBC;
            aesAlg.Key = key;
            aesAlg.IV = iv;

            using (MemoryStream msDecrypt = new MemoryStream(encryptedData))
            {
                using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, aesAlg.CreateDecryptor(), CryptoStreamMode.Write))
                {
                    csDecrypt.Write(encryptedData, 0, encryptedData.Length);
                }

                return msDecrypt.ToArray();
            }
        }
    }
    catch (CryptographicException e)
    {
        Log.Error(e);
        return null;
    }
}

然后对其进行测试,我正在使用以下代码:

originalMessage = "This is a test message.";
originalData = System.Text.Encoding.UTF8.GetBytes(originalMessage);

byte[] key, iv;
byte[] encryptedData = Encryption.EncryptAes(originalData, out key, out iv);
byte[] decryptedData = Encryption.DecryptAes(encryptedData, key, iv);
string decryptedMessage = System.Text.Encoding.UTF8.GetString(decryptedData);
Log.Debug(decryptedMessage); // This is a test message.?{?o?}??

日志输出显示解密的消息中有一堆垃圾字符“?{?o?} ??”在末尾。

我见过类似的问题,但是他们的回答似乎无济于事。我试图在解密过程中像这样写另一个数组:

using (MemoryStream msDecrypt = new MemoryStream(encryptedData))
{
    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, aesAlg.CreateDecryptor(), CryptoStreamMode.Write))
    {
        byte[] decryptedData = new byte[encryptedData.Length];
        csDecrypt.Write(decryptedData, 0, decryptedData.Length);
    }

    return msDecrypt.ToArray();
}

但这会导致此异常:

System.Security.Cryptography.CryptographicException: Padding is invalid and cannot be removed.

所以肯定有我想念的东西。有任何想法吗?谢谢!

1 个答案:

答案 0 :(得分:2)

是的,重复使用缓冲区对您很不利。通常,您不希望加密和解密的数据具有相同的大小,因此重复使用缓冲区会使您看到解密数据中剩余的加密数据。

使您的解密类似于加密。不要将缓冲区传递给MemoryStream的构造函数,而要为其分配正确大小的缓冲区:

using (MemoryStream msDecrypt = new MemoryStream())
{
    using (CryptoStream csDecrypt =
          new CryptoStream(msDecrypt,
                           aesAlg.CreateDecryptor(),
                           CryptoStreamMode.Write))
    {
        csDecrypt.Write(encryptedData, 0, encryptedData.Length);
    }
    return msDecrypt.ToArray();
}
  

我试图在解密过程中像这样写另一个数组:

using (MemoryStream msDecrypt = new MemoryStream(encryptedData))
{
    using (CryptoStream csDecrypt =
          new CryptoStream(msDecrypt,
                           aesAlg.CreateDecryptor(),
                           CryptoStreamMode.Write))
    {
        byte[] decryptedData = new byte[encryptedData.Length];
        csDecrypt.Write(decryptedData, 0, decryptedData.Length);
    }

    return msDecrypt.ToArray();
}

不读回自己。您仍在配置加密流为写入而不是读取。您在这里要做的是分配一个新的缓冲区,然后告诉AES将空的缓冲区解密到用加密数据初始化的内存流中。