C# AES 加密:Starting/Ending space 抛出 CryptographicException:'输入数据不是完整块
C# AES encryption: Starting/Ending space throw CryptographicException: 'The input data is not a complete block
我正在用 C# 研究 AES,并编写了一些代码来加密字符串。
起初,它在下面抛出异常。
System.Security.Cryptography.CryptographicException: 'Padding is invalid and cannot be removed.'
我通过将 encryption/decryption 的填充模式设置为 'None' 来解决这个问题。
然后,我在要加密的字符串中加入一些空格before/after。然后,我得到以下异常。
System.Security.Cryptography.CryptographicException: 'The input data is not a complete block.'
所以,我删除了加密的填充设置。然后,一切看起来都很好。
我的问题是
- 为什么要指定填充模式?
- 将starting/ending个空格的字符串转成字节数组后,我看到的只是一个字节数组。一堆数字。 encryption/decryption 关心 before/after 字符串的字节类型吗?
- 为什么 'setting padding mode none only for decryption' 有效?我期望 encryption/decryption 的对称填充设置。对于 AES,encryption/decryption 'PKCS7'.
的默认填充
提前致谢。
public void ByteEncryption()
{
byte[] key = new byte[16];
byte[] iv = new byte[16];
for (int ii = 0; ii < 16; ii++)
{
key[ii] = (byte)ii;
iv[ii] = (byte)ii;
}
string str_data = " This is a string to be encrypted ";
byte[] data = Encoding.Unicode.GetBytes(str_data);
byte[] encrypted = EncryptMemory(data, key, iv);
foreach(byte b in encrypted)
Console.WriteLine(b);
string str_encrypted = Encoding.Unicode.GetString(encrypted);
Console.Write("Encrypted:");
Console.WriteLine(str_encrypted);
byte[] decrypted = DecryptMemory(encrypted, key, iv);
string str_decrypted = Encoding.Unicode.GetString(decrypted);
Console.Write("---");
Console.Write(str_decrypted);
Console.WriteLine("---");
}
byte[] EncryptMemory(byte[] data, byte[] key, byte[] iv)
{
using (SymmetricAlgorithm algorithm = Aes.Create())
{
algorithm.Padding = PaddingMode.None; // Throw exception
using (ICryptoTransform encryptor = algorithm.CreateEncryptor(key, iv))
{
return Crypt(data, encryptor);
}
}
}
byte[] DecryptMemory(byte[] data, byte[] key, byte[] iv)
{
using (SymmetricAlgorithm algorithm = Aes.Create())
{
algorithm.Padding = PaddingMode.None;
using (ICryptoTransform decryptor = algorithm.CreateDecryptor(key, iv))
{
return Crypt(data, decryptor);
}
}
}
byte[] Crypt(byte[] data, ICryptoTransform cryptor)
{
using (MemoryStream memory = new MemoryStream())
using (CryptoStream stream = new CryptoStream(memory, cryptor, CryptoStreamM ode.Write))
{
stream.Write(data, 0, data.Length);
return memory.ToArray();
}
}
据此link,在阅读下面 cadrell0 的评论后,
Good call on Dispose. I was calling ms.ToArray() before disposing CryptoStream. Moving that line outside of the using fixed it for me
我解决了这个问题。这已经折磨了我两天了。
回答我的问题,所有的误解都来自于我加密的字符串的长度。通过插入随机数的字符,输入的没有特殊字符的字符串长度恰好正好是16的倍数; unicode 的大小是 16 位。没有特殊字符的原始字符串不需要填充,因为它已经是 16 的倍数。
我正在用 C# 研究 AES,并编写了一些代码来加密字符串。 起初,它在下面抛出异常。
System.Security.Cryptography.CryptographicException: 'Padding is invalid and cannot be removed.'
我通过将 encryption/decryption 的填充模式设置为 'None' 来解决这个问题。
然后,我在要加密的字符串中加入一些空格before/after。然后,我得到以下异常。
System.Security.Cryptography.CryptographicException: 'The input data is not a complete block.'
所以,我删除了加密的填充设置。然后,一切看起来都很好。
我的问题是
- 为什么要指定填充模式?
- 将starting/ending个空格的字符串转成字节数组后,我看到的只是一个字节数组。一堆数字。 encryption/decryption 关心 before/after 字符串的字节类型吗?
- 为什么 'setting padding mode none only for decryption' 有效?我期望 encryption/decryption 的对称填充设置。对于 AES,encryption/decryption 'PKCS7'. 的默认填充
提前致谢。
public void ByteEncryption()
{
byte[] key = new byte[16];
byte[] iv = new byte[16];
for (int ii = 0; ii < 16; ii++)
{
key[ii] = (byte)ii;
iv[ii] = (byte)ii;
}
string str_data = " This is a string to be encrypted ";
byte[] data = Encoding.Unicode.GetBytes(str_data);
byte[] encrypted = EncryptMemory(data, key, iv);
foreach(byte b in encrypted)
Console.WriteLine(b);
string str_encrypted = Encoding.Unicode.GetString(encrypted);
Console.Write("Encrypted:");
Console.WriteLine(str_encrypted);
byte[] decrypted = DecryptMemory(encrypted, key, iv);
string str_decrypted = Encoding.Unicode.GetString(decrypted);
Console.Write("---");
Console.Write(str_decrypted);
Console.WriteLine("---");
}
byte[] EncryptMemory(byte[] data, byte[] key, byte[] iv)
{
using (SymmetricAlgorithm algorithm = Aes.Create())
{
algorithm.Padding = PaddingMode.None; // Throw exception
using (ICryptoTransform encryptor = algorithm.CreateEncryptor(key, iv))
{
return Crypt(data, encryptor);
}
}
}
byte[] DecryptMemory(byte[] data, byte[] key, byte[] iv)
{
using (SymmetricAlgorithm algorithm = Aes.Create())
{
algorithm.Padding = PaddingMode.None;
using (ICryptoTransform decryptor = algorithm.CreateDecryptor(key, iv))
{
return Crypt(data, decryptor);
}
}
}
byte[] Crypt(byte[] data, ICryptoTransform cryptor)
{
using (MemoryStream memory = new MemoryStream())
using (CryptoStream stream = new CryptoStream(memory, cryptor, CryptoStreamM ode.Write))
{
stream.Write(data, 0, data.Length);
return memory.ToArray();
}
}
据此link,在阅读下面 cadrell0 的评论后,
Good call on Dispose. I was calling ms.ToArray() before disposing CryptoStream. Moving that line outside of the using fixed it for me
我解决了这个问题。这已经折磨了我两天了。 回答我的问题,所有的误解都来自于我加密的字符串的长度。通过插入随机数的字符,输入的没有特殊字符的字符串长度恰好正好是16的倍数; unicode 的大小是 16 位。没有特殊字符的原始字符串不需要填充,因为它已经是 16 的倍数。