当我使用错误的密钥时,我收到一个“解密”垃圾文件和mscorlib.dll的异常,“指定的块大小对此算法无效。”我想要的是解密完全失败而不抛出异常。
这是我目前的代码(改编自我在互联网上找到的vb.net示例,因此如果有更好的解决方案,将会受到赞赏)
public static bool EncryptOrDecryptFile(string strInputFile,
string strOutputFile, string pKey, string pIv, CryptoAction Direction)
{
Byte[] bytKey = CreateKey(pKey);
Byte[] bytIV = CreateIV(pIv);
bool pRet = false;
if (!File.Exists(strInputFile))
return false;
try
{
using (FileStream fsInput = new FileStream(strInputFile, FileMode.Open, FileAccess.Read))
{
using (FileStream fsOutput = new FileStream(strOutputFile, FileMode.OpenOrCreate, FileAccess.Write))
{
fsOutput.SetLength(0);
byte[] bytBuffer = new byte[4097];
long lngBytesProcessed = 0;
long lngFileLength = fsInput.Length;
int intBytesInCurrentBlock = 0;
CryptoStream csCryptoStream = null;
RijndaelManaged cspRijndael = new RijndaelManaged();
cspRijndael.BlockSize = 4096;
switch (Direction)
{
case CryptoAction.ActionEncrypt:
csCryptoStream = new CryptoStream(fsOutput, cspRijndael.CreateEncryptor(bytKey, bytIV),
CryptoStreamMode.Write);
break;
case CryptoAction.ActionDecrypt:
csCryptoStream = new CryptoStream(fsOutput, cspRijndael.CreateDecryptor(bytKey, bytIV),
CryptoStreamMode.Write);
break;
}
while (lngBytesProcessed < lngFileLength)
{
intBytesInCurrentBlock = fsInput.Read(bytBuffer, 0, 4096);
csCryptoStream.Write(bytBuffer, 0, intBytesInCurrentBlock);
lngBytesProcessed = lngBytesProcessed + Convert.ToInt64(intBytesInCurrentBlock);
}
csCryptoStream.Close();
}
}
pRet = true;
}
catch (Exception ex)
{
pRet = false;
}
return pRet;
}
#endregion
}
答案 0 :(得分:1)
鉴于正确长度的任何比特组合都可以是有效密钥,并且对于IV也是如此,加密流无法确定任何一个是不正确的,直到它尝试解密最后一个块为止。密码文本 - 此时它检测到填充错误并抛出异常。此外,您不能使用任何您想要的块大小 - 某些块大小对特定加密提供程序有效 - 对于Rijndael,我认为有效块大小为128,192和256.
避免“垃圾”文件的唯一方法是在内存中执行所有解密,或者写入临时文件而不是最终输出文件。没有办法避免异常,但无论如何它应该是一个不寻常的事件。
我还要删除代码中的所有缓冲区管理,长度检查等,并在输入流和加密流之间使用Stream.CopyTo。 E.g:
using (FileStream fsInput = new FileStream(strInputFile, FileMode.Open, FileAccess.Read))
{
using (FileStream fsOutput = new FileStream(strOutputFile, FileMode.OpenOrCreate, FileAccess.Write))
{
CryptoStream csCryptoStream = null;
RijndaelManaged cspRijndael = new RijndaelManaged();
cspRijndael.BlockSize = 256;
switch (Direction)
{
case CryptoAction.ActionEncrypt:
csCryptoStream = new CryptoStream(fsOutput, cspRijndael.CreateEncryptor(bytKey, bytIV),
CryptoStreamMode.Write);
break;
case CryptoAction.ActionDecrypt:
csCryptoStream = new CryptoStream(fsOutput, cspRijndael.CreateDecryptor(bytKey, bytIV),
CryptoStreamMode.Write);
break;
}
fsInput.CopyTo(csCryptoStream);
csCryptoStream.Close();
}
}
pRet = true;
答案 1 :(得分:1)
RijndaelManaged
可用的modes of operation都不提供完整性保护或身份验证。依赖于检查填充的有效性不是替代,因为您可以轻松地获得有效填充的错误消息。
相反,您应该对加密邮件应用HMAC。