这两天一直在为文件加密解密时,由于关闭数据转换链接流CryptoStream或者使用FlushFinalBlock时出现的
“不正确的数据”和“要解密的数据长度无效”异常而烦恼,到现在也没弄懂具体是什么问题,如果有哪位高人能指点一下,在下不胜感激。
    不过问题最终还是解决了,改变了加密和解密时的读取和写入的方式来解决了,最初都是直接对文件流操作,昨晚把它们修改为直接操作内存流。下面是操作文件流和操作内存流代码的对比:

直接操作文件流---加密:

程序代码:

/// <summary>
/// 文件加密
/// </summary>
/// <param name="inFileName">需要加密的文件(文件的完整路径)</param>
/// <param name="outFileName">加密后的文件(文件的完整路径)</param>
/// <param name="sAlgorithm">对称算法实例</param>
/// <returns>bool</returns>
private bool EncryptFile(string InFileName, string OutFileName, SymmetricAlgorithm sAlgorithm)
{
    try
    {
 //创建加密文件流
 FileStream inFileStream = new FileStream(InFileName, FileMode.Open, FileAccess.Read);
 FileStream outFileStream = new FileStream(OutFileName, FileMode.OpenOrCreate, FileAccess.Write);

 //锁定被加密文件
 inFileStream.Lock(0, inFileStream.Length);
 //设定加密后文件的初始长度
 outFileStream.SetLength(0);

 long fileLength = inFileStream.Length;  //文件的总字节数组长度
 byte[] bytein = new byte[100];        //每次以100个字节读取需要加密的文件
 long readedlen = 0;                    //记录已被读取的字节位置
 int len = 0;                    //每次写入的字节长度
 CryptoStream encStream = new CryptoStream(outFileStream, sAlgorithm.CreateEncryptor(this.KeyValue, this.IVValue), CryptoStreamMode.Write);
 try
 {
     while (readedlen < fileLength)
     {
  len = inFileStream.Read(bytein, 0, 100);//从输入流中读取100字节数组数据到bytein缓冲区
  encStream.Write(bytein, 0, 100);
  readedlen = readedlen + len;
     }
     outFileStream.Flush();
     inFileStream.Flush();
     encStream.Flush();
     return true;
 }
 catch (Exception error)
 {
     throw (error);
 }
 finally
 {
     inFileStream.Unlock(0, inFileStream.Length);
     encStream.Close();
     inFileStream.Close();
     outFileStream.Close();
 }
    }
    catch (Exception error)
    {
 throw (error);
    }
}

上面的文件加密方法在加密的时候没有任何问题,但是同样的,稍微修改下,下面是对应的解密的方法:
程序代码:

/// <summary>
/// 文件解密
/// </summary>
/// <param name="inFileName">需要解密的文件(文件的完整路径)</param>
/// <param name="outFileName">解密后的文件(文件的完整路径)</param>
/// <param name="sAlgorithm">对称算法实例</param>
/// <returns>bool</returns>
public bool DecryptFile(string InFileName, string OutFileName, SymmetricAlgorithm sAlgorithm)
{
    try
    {
 //创建解密文件流
 FileStream inFileStream = new FileStream(InFileName, FileMode.Open, FileAccess.Read);
 FileStream outFileStream = new FileStream(OutFileName, FileMode.OpenOrCreate, FileAccess.Write);
 //设定加密后文件的初始长度
 outFileStream.SetLength(0);
 long fileLength = inFileStream.Length;  //文件的总字节数组长度
 byte[] bytein = new byte[100];        //每次以100个字节读取需要加密的文件
 long readedlen = 0;                    //记录已被读取的字节位置
 int len = 0;                    //每次写入的字节长度
 CryptoStream encStream = new CryptoStream(outFileStream, sAlgorithm.CreateDecryptor(this.KeyValue, this.IVValue), CryptoStreamMode.Write);
 try
 {
     while (readedlen < fileLength)
     {
  len = inFileStream.Read(bytein, 0, 100);//从输入流中读取100字节数组数据到bytein缓冲区
  encStream.Write(bytein, 0, 100);
  readedlen = readedlen + len;
     }
     outFileStream.Flush();
     inFileStream.Flush();
     encStream.FlushFinalBlock(); //加了这一句,有的时候就会出现异常,不知道为什么  
     return true; 
 }
 catch (Exception error)
 {
     throw (error);
 }
 finally
 {
     encStream.Close(); //加了这一句,有的时候就会出现异常,不知道为什么  
     inFileStream.Close();
     outFileStream.Close();
 }
    }
    catch (Exception error)
    {
 throw (error);
    }
}


上面的解密方法中,红颜色标识的两行代码,在有些情况下就会提示我上面所说的两种异常,到现在我唯一能稍微明白的是可能因为我加密后立即解密就会出现上面的异常情况,因为我查了好多资料都没有提示有这两种异常的出现。下面是我加密解密方法我改成操作内存流的代码,下面的代码能正常执行。
加密:
程序代码:

/// <summary>
/// 文件加密
/// </summary>
/// <param name="inFileName">需要加密的文件(文件的完整路径)</param>
/// <param name="outFileName">加密后的文件(文件的完整路径)</param>
/// <param name="sAlgorithm">对称算法实例</param>
/// <returns>bool</returns>
private bool EncryptFile(string InFileName, string OutFileName, SymmetricAlgorithm sAlgorithm)
{
    //将文件内容读取到字节数组
    FileStream inFileStream = new FileStream(InFileName, FileMode.Open, FileAccess.Read);
    byte[] sourceByte       = new byte[inFileStream.Length];
    inFileStream.Read(sourceByte, 0, sourceByte.Length);
    inFileStream.Flush();
    inFileStream.Close();

    MemoryStream encryptStream  = new MemoryStream();
    CryptoStream encStream      = new CryptoStream(encryptStream, sAlgorithm.CreateEncryptor(), CryptoStreamMode.Write);
    try
    {
 //利用链接流加密源字节数组
 encStream.Write(sourceByte, 0, sourceByte.Length);
 encStream.FlushFinalBlock();

 //将字节数组信息写入指定文件
 FileStream outFileStream= new FileStream(OutFileName, FileMode.OpenOrCreate, FileAccess.Write);
 BinaryWriter bWriter    = new BinaryWriter(outFileStream);
 bWriter.Write(encryptStream.ToArray());
 encryptStream.Flush();

 bWriter.Close();
 encryptStream.Close();
    }
    catch (Exception error)
    {
 throw (error);
    }
    finally
    {
 encryptStream.Close();
 encStream.Close();
    }
    return true;
}


对应的解密方法:
程序代码:

/// <summary>
/// 文件解密
/// </summary>
/// <param name="inFileName">需要解密的文件(文件的完整路径)</param>
/// <param name="outFileName">解密后的文件(文件的完整路径)</param>
/// <param name="sAlgorithm">对称算法实例</param>
/// <returns>bool</returns>
public bool DecryptFile(string InFileName, string OutFileName, SymmetricAlgorithm sAlgorithm)
{

    //读取被加密文件到字节数组
    FileStream encryptFileStream= new FileStream(InFileName, FileMode.Open, FileAccess.Read);
    byte[] encryptByte          = new byte[encryptFileStream.Length];
    encryptFileStream.Read(encryptByte, 0, encryptByte.Length);
    encryptFileStream.Flush();
    encryptFileStream.Close();
    
    MemoryStream decryptStream  = new MemoryStream();
    CryptoStream encStream      = new CryptoStream(decryptStream, sAlgorithm.CreateDecryptor(), CryptoStreamMode.Write);
    try
    {
 encStream.Write(encryptByte, 0, encryptByte.Length);
 encStream.FlushFinalBlock();

 byte[] decryptByte          = decryptStream.ToArray();
 FileStream decryptFileStream= new FileStream(OutFileName, FileMode.OpenOrCreate, FileAccess.Write);
 BinaryWriter bWriter        = new BinaryWriter(decryptFileStream, Encoding.GetEncoding("GB18030"));
 bWriter.Write(decryptByte);
 decryptFileStream.Flush();

 bWriter.Close();
 decryptFileStream.Close();
    }
    catch (Exception error)
    {
 throw (error);
    }
    finally
    {
 decryptStream.Close();
 encStream.Close();
    }

    return true;
}
posted on 2009-03-03 14:56  王波  阅读(2736)  评论(0编辑  收藏  举报