AES 解密时的空输出流。原因?
Empty output stream at AES decrypt. Reason?
我试图解密一些东西,但不明白为什么我得到的结果是空的。我没有收到任何错误。我觉得这很奇怪。即使密钥无效,解密后的垃圾也应该是无意义的字节,但不是空的。我做了最小的例子。
Aes aes = Aes.Create();
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
aes.KeySize = 128;
aes.Key = new byte[] { 0x5f, 0x4d, 0xcc, 0x3b, 0x5a, 0xa7, 0x65, 0xd6, 0x1d, 0x83, 0x27, 0xde, 0xb8, 0x82, 0xcf, 0x99 };
aes.IV = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
// Create a decryptor to perform the stream transform.
ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
// Create the streams used for decryption.
string encrypted_str_b64 = "E1UinhOTTy8Sj/IxCPEM+UNhIpTXIXnOAUtPgA35erJmvRc22gsdvIgcMZORZ2SY";
byte[] ecrypted_junk = Convert.FromBase64String(encrypted_str_b64);
string plaintext = string.Empty;
using (MemoryStream memoryStream = new MemoryStream(ecrypted_junk))
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(cryptoStream))
{
cryptoStream.FlushFinalBlock();
byte[] temp_buf = new byte[1024];
int read_bytes = cryptoStream.Read(temp_buf, 0, temp_buf.Length); //read_bytes = 0...
plaintext = srDecrypt.ReadToEnd(); //string is empty...
}
}
}
没有解密数据,因为解密数据时CryptoStream
为空。这是因为在实际读取之前用FlushFinalBlock()
清零了。根据评论,FlushFinalBlock()
是因为否则会发生填充异常而实现的,但这不是解决问题的方法。
如果删除了 FlushFinalBlock()
调用,则会生成 CryptographicException: Padding is invalid and cannot be removed,指示解密过程中的错误(例如,通常在使用与用于生成密文的密钥不同的密钥)。
padding异常的直接原因是解密产生了错误的明文(由无意义的字节组成,因此产生了无效的PKCS7 padding at the end. If the decryption would be done without padding (PaddingMode.None
),不会产生这个异常,结果是确实是无意义的字节。
所以真正问题的解决方案是使用正确的密钥,即创建密文的密钥。否则解密几乎是不可能的。
只是为了完整性:发布的代码使用了一个缓冲区(temp_buf
),该缓冲区是根据评论为测试目的而实现的。使用 CryptoStream#Read()
. The rest is read with StreamReader#ReadToEnd()
将数据写入此 1024 字节缓冲区。如果数据完全适合缓冲区,则第二部分不再 return 数据,因此 return 是一个空字符串,即使在成功解密的情况下,这也不会失败(与关于注释 //string is empty... 在发布的代码中)。
我试图解密一些东西,但不明白为什么我得到的结果是空的。我没有收到任何错误。我觉得这很奇怪。即使密钥无效,解密后的垃圾也应该是无意义的字节,但不是空的。我做了最小的例子。
Aes aes = Aes.Create();
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
aes.KeySize = 128;
aes.Key = new byte[] { 0x5f, 0x4d, 0xcc, 0x3b, 0x5a, 0xa7, 0x65, 0xd6, 0x1d, 0x83, 0x27, 0xde, 0xb8, 0x82, 0xcf, 0x99 };
aes.IV = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
// Create a decryptor to perform the stream transform.
ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
// Create the streams used for decryption.
string encrypted_str_b64 = "E1UinhOTTy8Sj/IxCPEM+UNhIpTXIXnOAUtPgA35erJmvRc22gsdvIgcMZORZ2SY";
byte[] ecrypted_junk = Convert.FromBase64String(encrypted_str_b64);
string plaintext = string.Empty;
using (MemoryStream memoryStream = new MemoryStream(ecrypted_junk))
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(cryptoStream))
{
cryptoStream.FlushFinalBlock();
byte[] temp_buf = new byte[1024];
int read_bytes = cryptoStream.Read(temp_buf, 0, temp_buf.Length); //read_bytes = 0...
plaintext = srDecrypt.ReadToEnd(); //string is empty...
}
}
}
没有解密数据,因为解密数据时CryptoStream
为空。这是因为在实际读取之前用FlushFinalBlock()
清零了。根据评论,FlushFinalBlock()
是因为否则会发生填充异常而实现的,但这不是解决问题的方法。
如果删除了 FlushFinalBlock()
调用,则会生成 CryptographicException: Padding is invalid and cannot be removed,指示解密过程中的错误(例如,通常在使用与用于生成密文的密钥不同的密钥)。
padding异常的直接原因是解密产生了错误的明文(由无意义的字节组成,因此产生了无效的PKCS7 padding at the end. If the decryption would be done without padding (PaddingMode.None
),不会产生这个异常,结果是确实是无意义的字节。
所以真正问题的解决方案是使用正确的密钥,即创建密文的密钥。否则解密几乎是不可能的。
只是为了完整性:发布的代码使用了一个缓冲区(temp_buf
),该缓冲区是根据评论为测试目的而实现的。使用 CryptoStream#Read()
. The rest is read with StreamReader#ReadToEnd()
将数据写入此 1024 字节缓冲区。如果数据完全适合缓冲区,则第二部分不再 return 数据,因此 return 是一个空字符串,即使在成功解密的情况下,这也不会失败(与关于注释 //string is empty... 在发布的代码中)。