关于最近给一家企业做的文档保全系统的技术整理(2)
3、将文件加密
为了防止文件被非法用户查看,采用的方法是将文件加密。考虑到大文件的加密效率和内存使用的问题,加密时使用Stream的Read方法连续的读取并加密,而不是ReadToEnd的方式。具体加密的算法采用对称加密Des,可以直接使用。Net提供的DES类。
public enum DESErrorEnum { None, UnEncryptError, EncryptedError, FileUnExistsError, KeyError, FileDeleteError, UnKnowError }
先定义一个加解密异常的枚举类型。
public class DESHelper { /// <summary> /// 加密文件的标识头数据 /// </summary> private static byte[] EncryptFlag = { 99, 98, 97, 96, 95, 95, 96, 97, 98, 99 }; /// <summary> /// 对称加密算法的初始化向量 /// </summary> private static byte[] MyDESIV = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; /// <summary> /// 对称加密算法的密钥 /// </summary> private static byte[] MyDESKey = { 0x49, 0x50, 0x51, 0x52, 0x49, 0x50, 0x51, 0x52 }; private static FileStream MyInFileStream; private static FileStream MyOutFileStream; private static DES MyDES = new DESCryptoServiceProvider(); /// <summary> /// 判断两个数组是否相等 /// </summary> /// <param name="b1"></param> /// <param name="b2"></param> /// <returns></returns> private static bool CheckEqual(byte[] b1, byte[] b2) { if (b1.Length != b2.Length) { return false; } for (int i = 0; i < b1.Length; i++) { if (b1[i] != b2[i]) { return false; } } return true; } /// <summary> /// 检测文件是否已经加密 /// </summary> /// <param name="fileName"></param> /// <returns></returns> public static bool CheckFileEncrypted(string fileName) { bool flag = false; try { MyInFileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read); byte[] ef = new byte[10]; MyInFileStream.Read(ef, 0, 10); if (CheckEqual(ef, EncryptFlag)) { flag = true; } else { flag = false; } MyInFileStream.Close(); MyInFileStream.Dispose(); } catch { try { MyInFileStream.Close(); MyInFileStream.Dispose(); } catch { } flag = false; } return flag; } /// <summary> /// 使用DES加密方法加密文件 /// </summary> /// <param name="inFile">源文件</param> /// <param name="outFile">目标文件</param> /// <param name="deleteInFile">加密完毕是否删除源文件</param> /// <returns>错误</returns> public static DESErrorEnum DESEncrypt(string inFile, string outFile, bool deleteInFile) { if (!File.Exists(inFile)) { return DESErrorEnum.FileUnExistsError; } if (CheckFileEncrypted(inFile))//判断文件是否已经加密 { return DESErrorEnum.EncryptedError; } try { File.SetAttributes(inFile, FileAttributes.Normal); //创建输入和输出文件流 MyInFileStream = new FileStream(inFile, FileMode.Open, FileAccess.Read); MyOutFileStream = new FileStream(outFile, FileMode.OpenOrCreate, FileAccess.Write); MyOutFileStream.SetLength(0); //每次的中间流. byte[] InsertData = new byte[100]; //写入加密标识头数据 MyOutFileStream.Write(EncryptFlag, 0, 10); //代表已经加密流的大小 int CompletedLength = 0; //代表要加密文件总的大小 long InFileSize = MyInFileStream.Length; //创建加密流 CryptoStream EncryptStream = new CryptoStream(MyOutFileStream, MyDES.CreateEncryptor(MyDESKey, MyDESIV), CryptoStreamMode.Write); //从输入文件中读取流,然后加密到输出文件中 while (CompletedLength < InFileSize) { //每次写入加密文件的数据大小 int Length = MyInFileStream.Read(InsertData, 0, 100); EncryptStream.Write(InsertData, 0, Length); CompletedLength = CompletedLength + Length; } //关闭流 EncryptStream.Close(); MyOutFileStream.Close(); MyInFileStream.Close(); EncryptStream.Dispose(); MyInFileStream.Dispose(); MyOutFileStream.Dispose(); if (deleteInFile) { try { File.Delete(inFile); } catch { return DESErrorEnum.FileDeleteError; } } return DESErrorEnum.None; } catch { try { MyOutFileStream.Close(); MyInFileStream.Close(); MyInFileStream.Dispose(); MyOutFileStream.Dispose(); } catch { } return DESErrorEnum.UnKnowError; } } /// <summary> /// DES加密文件覆盖源文件 /// </summary> /// <param name="file">待加密文件</param> /// <returns></returns> public static DESErrorEnum DESEncrypt(string file) { DESErrorEnum err = DESErrorEnum.None; try { if (DESHelper.CheckFileEncrypted(file)) { return err; } string outFile = System.Environment.GetFolderPath(System.Environment.SpecialFolder.InternetCache) + Path.GetFileName(file); err = DESEncrypt(file, outFile, true); File.Move(outFile, file); return err; } catch { return DESErrorEnum.UnKnowError; } } /// <summary> /// DES解密文件覆盖源文件 /// </summary> /// <param name="file">待解密文件</param> /// <returns></returns> public static DESErrorEnum DESDecrypt(string file) { //DESErrorEnum err = DESErrorEnum.None; //try //{ // string outFile = file + ".ec"; // err = DESDecrypt(file, outFile, true); // File.Move(outFile, file); // return err; //} //catch //{ // return DESErrorEnum.UnKnowError; //} return DESErrorEnum.None; } /// <summary> /// 使用DES加密方法解密文件 /// </summary> /// <param name="inFile">源文件</param> /// <param name="outFile">目标文件</param> /// <param name="deleteInFile">解密完毕是否删除源文件</param> /// <returns>错误</returns> public static DESErrorEnum DESDecrypt(string inFile, string outFile, bool deleteInFile) { if (!File.Exists(inFile)) { return DESErrorEnum.FileUnExistsError; } if (!CheckFileEncrypted(inFile)) { return DESErrorEnum.UnEncryptError; } try { File.SetAttributes(inFile, FileAttributes.Normal); MyInFileStream = new FileStream(inFile, FileMode.Open, FileAccess.Read); MyOutFileStream = new FileStream(outFile, FileMode.OpenOrCreate, FileAccess.Write); MyOutFileStream.SetLength(0); //每次的中间流. byte[] InsertData = new byte[100]; //代表已经解密的流的大小 int MyCompletedSize = 0; //代表要解密文件总的大小 long MyFileSize = MyInFileStream.Length; //创建解密流 CryptoStream DecryptStream = new CryptoStream(MyOutFileStream, MyDES.CreateDecryptor(MyDESKey, MyDESIV), CryptoStreamMode.Write); //从输入文件中读取流,然后解密到输出文件中 byte[] tempB = new byte[10]; MyInFileStream.Read(tempB, 0, 10); while (MyCompletedSize < MyFileSize - 10) { //每次写入解密流的大小 int length = MyInFileStream.Read(InsertData, 0, 100); DecryptStream.Write(InsertData, 0, length); MyCompletedSize = MyCompletedSize + length; } DecryptStream.Close(); MyOutFileStream.Close(); MyInFileStream.Close(); DecryptStream.Dispose(); MyInFileStream.Dispose(); MyOutFileStream.Dispose(); if (deleteInFile) { try { File.Delete(inFile); } catch { return DESErrorEnum.FileDeleteError; } } return DESErrorEnum.None; } catch { try { MyOutFileStream.Close(); MyInFileStream.Close(); MyInFileStream.Dispose(); MyOutFileStream.Dispose(); } catch { } return DESErrorEnum.UnKnowError; } } }
在该DES类中提供2个主要的方法DESEncrypt(加密方法需要提供参数:要加密的源文件、加密后保存的目的文件、加密完毕是否删除源文件)和DESDecrypt(解密方法)
因为在该项目中队文件的加密不需要设置密钥所以我直接在该类中设置了一个固定的加密密钥。
/// <summary> /// 对称加密算法的密钥 /// </summary> private static byte[] MyDESKey = { 0x49, 0x50, 0x51, 0x52, 0x49, 0x50, 0x51, 0x52 };
大家实际的使用的时候可以让用户输入要设置的加密密码。
标准的加密密码为8位,当然用户可以使用少于8为的密钥,但是在加密的时候程序必须要按照某种规则补全为8位才可以进行加密。
浙公网安备 33010602011771号