FileEncryptTool.cs 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. //************************************************************************
  2. // https://github.com/yuzhengyang
  3. // author: yuzhengyang
  4. // date: 2017.6.8 - 2017.6.10
  5. // desc: 文件加密工具
  6. // Copyright (c) yuzhengyang. All rights reserved.
  7. //************************************************************************
  8. using System;
  9. using System.Collections.Generic;
  10. using System.IO;
  11. using System.Linq;
  12. using System.Text;
  13. using Y.Utils.DataUtils.EncryptUtils;
  14. namespace Y.Utils.IOUtils.FileUtils
  15. {
  16. /// <summary>
  17. /// 文件加密工具
  18. /// </summary>
  19. public class FileEncryptTool
  20. {
  21. private static string FileTypeDesc = "FileEncrypt [文件加密]";
  22. private static int FileBuffer = 1024 * 1024;
  23. /// <summary>
  24. /// 文件加密
  25. /// </summary>
  26. /// <param name="srcFile">源文件</param>
  27. /// <param name="dstFile">目标文件</param>
  28. /// <param name="password">加密密码</param>
  29. /// <param name="overwrite">是否覆盖已有目标文件</param>
  30. /// <returns>
  31. /// 1:操作成功
  32. /// -11:要加密的文件不存在
  33. /// -12:加密后的目标文件已存在
  34. /// -404:未知错误,操作失败
  35. /// </returns>
  36. public static int Encrypt(string srcFile, string dstFile, string password, bool overwrite = true)
  37. {
  38. DateTime beginTime = DateTime.Now;
  39. if (!File.Exists(srcFile)) return -11; //要加密的文件不存在
  40. if (File.Exists(dstFile) && !overwrite) return -12;//加密后的目标文件已存在
  41. string fmtPwd = AesTool.FmtPassword(password);
  42. string pwdMd5 = MD5Tool.Encrypt(MD5Tool.Encrypt(fmtPwd));
  43. string md5 = FileTool.GetMD5(srcFile);
  44. using (FileStream fsRead = new FileStream(srcFile, FileMode.Open))
  45. {
  46. using (FileStream fsWrite = new FileStream(dstFile, FileMode.Create))
  47. {
  48. try
  49. {
  50. //文件头部数据定义
  51. List<byte[]> headdata = new List<byte[]>()
  52. {
  53. Encoding.Default.GetBytes(FileTypeDesc),
  54. Encoding.Default.GetBytes(md5),
  55. Encoding.Default.GetBytes(AesTool.Encrypt(fmtPwd,AesTool.DefaultPassword)),
  56. Encoding.Default.GetBytes(pwdMd5),
  57. Encoding.Default.GetBytes(DateTime.Now.ToString())
  58. };
  59. //写入头部信息个数
  60. byte[] count = BitConverter.GetBytes(headdata.Count);
  61. fsWrite.Write(count, 0, count.Length);
  62. //写入各部分长度
  63. for (int i = 0; i < headdata.Count; i++)
  64. {
  65. byte[] length = BitConverter.GetBytes(headdata[i].Length);
  66. fsWrite.Write(length, 0, length.Length);
  67. }
  68. //写入各部分数据
  69. for (int i = 0; i < headdata.Count; i++)
  70. {
  71. fsWrite.Write(headdata[i], 0, headdata[i].Length);
  72. }
  73. //写入文件源数据
  74. int readCount = 0;
  75. byte[] buffer = new byte[FileBuffer];
  76. while ((readCount = fsRead.Read(buffer, 0, buffer.Length)) > 0)
  77. {
  78. if (readCount != buffer.Length)
  79. {
  80. byte[] temp = new byte[readCount];
  81. Buffer.BlockCopy(buffer, 0, temp, 0, readCount);
  82. byte[] enbyte = AesTool.Encrypt(temp, fmtPwd);
  83. fsWrite.Write(enbyte, 0, enbyte.Length);
  84. }
  85. else
  86. {
  87. byte[] enbyte = AesTool.Encrypt(buffer, fmtPwd);
  88. fsWrite.Write(enbyte, 0, enbyte.Length);
  89. }
  90. }
  91. return (int)Math.Ceiling((DateTime.Now - beginTime).TotalSeconds);//操作成功
  92. }
  93. catch (Exception e) { }
  94. fsWrite.Close();
  95. }
  96. fsRead.Close();
  97. //加密失败后,删除加密的文件
  98. try { File.Delete(dstFile); } catch (Exception e) { }
  99. }
  100. return -404;//未知错误,操作失败
  101. }
  102. /// <summary>
  103. /// 文件解密
  104. /// </summary>
  105. /// <param name="srcFile">源文件</param>
  106. /// <param name="dstFile">目标文件</param>
  107. /// <param name="password">解密密码</param>
  108. /// <param name="overwrite">是否覆盖已有目标文件</param>
  109. /// <returns>
  110. /// 1:操作成功
  111. /// -11:要解密的文件不存在
  112. /// -12:解密后的目标文件已存在
  113. /// -30:文件头不长度不吻合
  114. /// -90:解锁密码错误
  115. /// -404:未知错误,操作失败
  116. /// </returns>
  117. public static int Decrypt(string srcFile, string dstFile, string password, bool overwrite = true)
  118. {
  119. DateTime beginTime = DateTime.Now;
  120. if (!File.Exists(srcFile)) return -11;//要解密的文件不存在
  121. if (File.Exists(dstFile) && !overwrite) return -12;//解密后的目标文件已存在
  122. string fmtPwd = AesTool.FmtPassword(password);
  123. string pwdMd5 = MD5Tool.Encrypt(MD5Tool.Encrypt(fmtPwd));
  124. List<string> headdata = new List<string>();
  125. using (FileStream fsRead = new FileStream(srcFile, FileMode.Open))
  126. {
  127. using (FileStream fsWrite = new FileStream(dstFile, FileMode.Create))
  128. {
  129. try
  130. {
  131. //读取头部信息个数
  132. byte[] count = new byte[4];
  133. fsRead.Read(count, 0, count.Length);
  134. int countint = BitConverter.ToInt32(count, 0);
  135. //读取各部分长度和数据
  136. byte[] headlength = new byte[4 * countint];
  137. if (fsRead.Read(headlength, 0, headlength.Length) == headlength.Length)
  138. {
  139. for (int i = 0; i < countint; i++)
  140. {
  141. int datalong = BitConverter.ToInt32(headlength, i * 4);
  142. byte[] tempdata = new byte[datalong];
  143. fsRead.Read(tempdata, 0, datalong);
  144. headdata.Add(Encoding.Default.GetString(tempdata));
  145. }
  146. }
  147. if (headdata.Count < 5) return -30;//文件头不长度不吻合
  148. if (pwdMd5 != headdata[3]) return -90;//解锁密码错误
  149. int readCount = 0;
  150. byte[] buffer = new byte[FileBuffer + 16];
  151. while ((readCount = fsRead.Read(buffer, 0, buffer.Length)) > 0)
  152. {
  153. if (readCount != buffer.Length)
  154. {
  155. byte[] temp = new byte[readCount];
  156. Buffer.BlockCopy(buffer, 0, temp, 0, readCount);
  157. byte[] debyte = AesTool.Decrypt(temp, fmtPwd);
  158. fsWrite.Write(debyte, 0, debyte.Length);
  159. }
  160. else
  161. {
  162. byte[] debyte = AesTool.Decrypt(buffer, fmtPwd);
  163. fsWrite.Write(debyte, 0, debyte.Length);
  164. }
  165. }
  166. }
  167. catch (Exception e) { }
  168. fsWrite.Close();
  169. }
  170. fsRead.Close();
  171. }
  172. string md5 = FileTool.GetMD5(dstFile);
  173. if (headdata.Count > 1 && md5 == headdata[1])
  174. {
  175. return (int)Math.Ceiling((DateTime.Now - beginTime).TotalSeconds);//操作成功
  176. }
  177. else
  178. {
  179. //解密失败后,删除解密的文件
  180. try { File.Delete(dstFile); } catch (Exception e) { }
  181. }
  182. return -404;//未知错误,操作失败
  183. }
  184. }
  185. }