生活随笔
收集整理的這篇文章主要介紹了
C#文件加密和解密
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
下載
csdn下載分會越來越高,所以我轉存到百度盤了,有需要的朋友可以從這里下載
百度盤鏈接
鏈接:https://pan.baidu.com/s/1bK4sug-eK85fmPgi9DzhcA 提取碼:0vp3
源碼可以參考github
GitHub
CSDN下載(csdn自動把分調高了…)
//
最近看了一下加密算法,對加密文件突然很感興趣,就研究了一下:
加密算法和加密后的長度問題(這里用的AES);加密大文件使用流的方式一點一點加密(防止一次性吃掉很多內存);加密過程的回調;文件結構;
截圖
加密:
解密:
選擇文件:
內存及CPU的使用:
一、算法
首先,文件要加密就一定要解密,所以一定要找個能解密的算法,這個不用多說……其實加密解密算法也算是C#里自帶了,代碼如下:
/// <summary>
/// 加密
/// </summary>
/// <param name="array">要加密的 byte[] 數組</param>
/// <param name="key"></param>
/// <returns></returns>
public static byte[] Encrypt(byte[] array, string key)
{key = FmtPassword(key);byte[] keyArray = Encoding.UTF8.GetBytes(key);RijndaelManaged rDel = new RijndaelManaged();rDel.Key = keyArray;rDel.Mode = CipherMode.ECB;rDel.Padding = PaddingMode.PKCS7;ICryptoTransform cTransform = rDel.CreateEncryptor();byte[] resultArray = cTransform.TransformFinalBlock(array, 0, array.Length);return resultArray;
} /// <summary>
/// 解密
/// </summary>
/// <param name="array">要解密的 byte[] 數組</param>
/// <param name="key"></param>
/// <returns></returns>
public static byte[] Decrypt(byte[] array, string key)
{key = FmtPassword(key);byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);RijndaelManaged rDel = new RijndaelManaged();rDel.Key = keyArray;rDel.Mode = CipherMode.ECB;rDel.Padding = PaddingMode.PKCS7;ICryptoTransform cTransform = rDel.CreateDecryptor();byte[] resultArray = cTransform.TransformFinalBlock(array, 0, array.Length);return resultArray;
}
這里要注意一點,AES加密的話,密碼是需要32位的,不然會提示錯誤:DES和AES加密:指定鍵的大小對于此算法無效
所以需要自己把不夠長度的密碼填充一下(超出長度的也需要處理一下),避免出現這種錯誤
二、流
文件加密的功能網上有很多,我發現有很多直接把文件全部讀取出來,然后加密整個文件。這種方法在處理大文件會消耗非常大的內存,所以需要注意不能一次性把文件全加密。
注1: 關于加密的部分,可以只加密文件的一部分數據,這樣可以保證加密速度。
注2: 使用流讀取部分,循環加密的時候,AES加密后的內容長度會增加,比如要加密一個 byte[1024] 大小的內容,加密后會變成 byte[1024+16] ,這一點可以自己試一試。
三、進度
進度方面是很有必要的,在加密大文件的時候,如果光等著沒有進度也顯得很尷尬,所以做一個委托,來把進度回調出來。
// 定義
public delegate void ProgressHandler(object sender, ProgressEventArgs e);// 使用
progress?.Invoke(sender, new ProgressEventArgs(fsRead.Position, fsRead.Length));
四、文件結構
加密文件后的文件結構是要自己重新做定義的,使自己的程序能讀懂,并且能成功解密即可。這里貼一個文件加密的方法:
里面有很多我自己寫的方法,下面會給鏈接地址
/// <summary>
/// 文件加密
/// </summary>
/// <param name="srcFile">源文件</param>
/// <param name="dstFile">目標文件</param>
/// <param name="password">加密密碼</param>
/// <param name="progress">回調進度</param>
/// <param name="overwrite">是否覆蓋已有目標文件</param>
/// <returns>
/// >0:操作成功(操作共計秒數)
/// -11:要加密的文件不存在
/// -12:加密后的目標文件已存在
/// -404:未知錯誤,操作失敗
/// </returns>
public static int Encrypt(string srcFile, string dstFile, string password, ProgressDelegate.ProgressHandler progress = null, object sender = null, bool overwrite = true)
{DateTime beginTime = DateTime.Now;if (!File.Exists(srcFile)) return -11; //要加密的文件不存在if (File.Exists(dstFile) && !overwrite) return -12;//加密后的目標文件已存在string fmtPwd = AesTool.FmtPassword(password);string pwdMd5 = MD5Tool.Encrypt(MD5Tool.Encrypt(fmtPwd));string md5 = FileTool.GetMD5(srcFile);using (FileStream fsRead = new FileStream(srcFile, FileMode.Open)){using (FileStream fsWrite = new FileStream(dstFile, FileMode.Create)){try{//寫入文件類型標識和版本號byte[] filetypeandversion = Encoding.Default.GetBytes(FileType + FileVersion);fsWrite.Write(filetypeandversion, 0, filetypeandversion.Length);//文件頭部數據定義List<byte[]> headdata = new List<byte[]>(){Encoding.Default.GetBytes(FileType),Encoding.Default.GetBytes(md5),Encoding.Default.GetBytes(AesTool.Encrypt(fmtPwd,AesTool.DefaultPassword)),Encoding.Default.GetBytes(pwdMd5),Encoding.Default.GetBytes(DateTime.Now.ToString())};//寫入頭部信息個數byte[] count = BitConverter.GetBytes(headdata.Count);fsWrite.Write(count, 0, count.Length);//寫入各部分長度for (int i = 0; i < headdata.Count; i++){byte[] length = BitConverter.GetBytes(headdata[i].Length);fsWrite.Write(length, 0, length.Length);}//寫入各部分數據for (int i = 0; i < headdata.Count; i++){fsWrite.Write(headdata[i], 0, headdata[i].Length);}//寫入文件源數據int readCount = 0;byte[] buffer = new byte[FileBuffer];while ((readCount = fsRead.Read(buffer, 0, buffer.Length)) > 0){if (readCount != buffer.Length){byte[] temp = new byte[readCount];Buffer.BlockCopy(buffer, 0, temp, 0, readCount);byte[] enbyte = AesTool.Encrypt(temp, fmtPwd);fsWrite.Write(enbyte, 0, enbyte.Length);}else{byte[] enbyte = AesTool.Encrypt(buffer, fmtPwd);fsWrite.Write(enbyte, 0, enbyte.Length);}progress?.Invoke(sender, new ProgressEventArgs(fsRead.Position, fsRead.Length));}return (int)Math.Ceiling((DateTime.Now - beginTime).TotalSeconds);//操作成功}catch (Exception e) { }}//加密失敗后,刪除加密的文件try { File.Delete(dstFile); } catch (Exception e) { }}return -404;//未知錯誤,操作失敗
}
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎
總結
以上是生活随笔為你收集整理的C#文件加密和解密的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。