为什么我的 AES 解密数据末尾有垃圾字节?
Why does my AES-decrypted data have garbage bytes at the end?
我正在尝试使用 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.
所以一定是我遗漏了什么。有任何想法吗?谢谢!
是的,重复使用缓冲区让您很苦恼。您通常不希望加密数据和解密数据的大小相同,因此重复使用缓冲区会导致您在解密数据中看到剩余的加密数据。
使您的解密类似于加密。不要将缓冲区传递给 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();
}
I've tried writing to another array during decryption like this:
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 解密那个空缓冲区到用加密数据初始化的内存流中。
我正在尝试使用 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.
所以一定是我遗漏了什么。有任何想法吗?谢谢!
是的,重复使用缓冲区让您很苦恼。您通常不希望加密数据和解密数据的大小相同,因此重复使用缓冲区会导致您在解密数据中看到剩余的加密数据。
使您的解密类似于加密。不要将缓冲区传递给 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();
}
I've tried writing to another array during decryption like this:
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 解密那个空缓冲区到用加密数据初始化的内存流中。