如何使用Rijndael解密文件来确定密钥或向量是否不正确?

时间:2011-03-01 13:02:12

标签: c# .net encryption rijndael

当我使用错误的密钥时,我收到一个“解密”垃圾文件和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
}

2 个答案:

答案 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