DESFileClass.cs 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Security.Cryptography;
  5. using System.IO;
  6. namespace Ant.Frame
  7. {
  8. /// <summary>
  9. /// 异常处理类
  10. /// </summary>
  11. public class CryptoHelpException : ApplicationException
  12. {
  13. public CryptoHelpException(string msg) : base(msg) { }
  14. }
  15. /// <summary>
  16. /// CryptHelp
  17. /// </summary>
  18. public class DESFileClass
  19. {
  20. private const ulong FC_TAG = 0xFC010203040506CF;
  21. private const int BUFFER_SIZE = 128 * 1024;
  22. /// <summary>
  23. /// 检验两个Byte数组是否相同
  24. /// </summary>
  25. /// <param name="b1">Byte数组</param>
  26. /// <param name="b2">Byte数组</param>
  27. /// <returns>true-相等</returns>
  28. private static bool CheckByteArrays(byte[] b1, byte[] b2)
  29. {
  30. if (b1.Length == b2.Length)
  31. {
  32. for (int i = 0; i < b1.Length; ++i)
  33. {
  34. if (b1[i] != b2[i])
  35. return false;
  36. }
  37. return true;
  38. }
  39. return false;
  40. }
  41. /// <summary>
  42. /// 创建DebugLZQ ,http://www.cnblogs.com/DebugLZQ
  43. /// </summary>
  44. /// <param name="password">密码</param>
  45. /// <param name="salt"></param>
  46. /// <returns>加密对象</returns>
  47. private static SymmetricAlgorithm CreateRijndael(string password, byte[] salt)
  48. {
  49. PasswordDeriveBytes pdb = new PasswordDeriveBytes(password, salt, "SHA256", 1000);
  50. SymmetricAlgorithm sma = Rijndael.Create();
  51. sma.KeySize = 256;
  52. sma.Key = pdb.GetBytes(32);
  53. sma.Padding = PaddingMode.PKCS7;
  54. return sma;
  55. }
  56. /// <summary>
  57. /// 加密文件随机数生成
  58. /// </summary>
  59. private static RandomNumberGenerator rand = new RNGCryptoServiceProvider();
  60. /// <summary>
  61. /// 生成指定长度的随机Byte数组
  62. /// </summary>
  63. /// <param name="count">Byte数组长度</param>
  64. /// <returns>随机Byte数组</returns>
  65. private static byte[] GenerateRandomBytes(int count)
  66. {
  67. byte[] bytes = new byte[count];
  68. rand.GetBytes(bytes);
  69. return bytes;
  70. }
  71. /// <summary>
  72. /// 加密文件
  73. /// </summary>
  74. /// <param name="inFile">待加密文件</param>
  75. /// <param name="outFile">加密后输入文件</param>
  76. /// <param name="password">加密密码</param>
  77. public static void EncryptFile(string inFile, string outFile, string password)
  78. {
  79. using (FileStream fin = File.OpenRead(inFile),
  80. fout = File.OpenWrite(outFile))
  81. {
  82. long lSize = fin.Length; // 输入文件长度
  83. int size = (int)lSize;
  84. byte[] bytes = new byte[BUFFER_SIZE]; // 缓存
  85. int read = -1; // 输入文件读取数量
  86. int value = 0;
  87. // 获取IV和salt
  88. byte[] IV = GenerateRandomBytes(16);
  89. byte[] salt = GenerateRandomBytes(16);
  90. // 创建加密对象
  91. SymmetricAlgorithm sma = DESFileClass.CreateRijndael(password, salt);
  92. sma.IV = IV;
  93. // 在输出文件开始部分写入IV和salt
  94. fout.Write(IV, 0, IV.Length);
  95. fout.Write(salt, 0, salt.Length);
  96. // 创建散列加密
  97. HashAlgorithm hasher = SHA256.Create();
  98. using (CryptoStream cout = new CryptoStream(fout, sma.CreateEncryptor(), CryptoStreamMode.Write),
  99. chash = new CryptoStream(Stream.Null, hasher, CryptoStreamMode.Write))
  100. {
  101. BinaryWriter bw = new BinaryWriter(cout);
  102. bw.Write(lSize);
  103. bw.Write(FC_TAG);
  104. // 读写字节块到加密流缓冲区
  105. while ((read = fin.Read(bytes, 0, bytes.Length)) != 0)
  106. {
  107. cout.Write(bytes, 0, read);
  108. chash.Write(bytes, 0, read);
  109. value += read;
  110. }
  111. // 关闭加密流
  112. chash.Flush();
  113. chash.Close();
  114. // 读取散列
  115. byte[] hash = hasher.Hash;
  116. // 输入文件写入散列
  117. cout.Write(hash, 0, hash.Length);
  118. // 关闭文件流
  119. cout.Flush();
  120. cout.Close();
  121. }
  122. }
  123. }
  124. /// <summary>
  125. /// 解密文件
  126. /// </summary>
  127. /// <param name="inFile">待解密文件</param>
  128. /// <param name="outFile">解密后输出文件</param>
  129. /// <param name="password">解密密码</param>
  130. public static void DecryptFile(string inFile, string outFile, string password)
  131. {
  132. // 创建打开文件流
  133. using (FileStream fin = File.OpenRead(inFile),
  134. fout = File.OpenWrite(outFile))
  135. {
  136. int size = (int)fin.Length;
  137. byte[] bytes = new byte[BUFFER_SIZE];
  138. int read = -1;
  139. int value = 0;
  140. int outValue = 0;
  141. byte[] IV = new byte[16];
  142. fin.Read(IV, 0, 16);
  143. byte[] salt = new byte[16];
  144. fin.Read(salt, 0, 16);
  145. SymmetricAlgorithm sma = DESFileClass.CreateRijndael(password, salt);
  146. sma.IV = IV;
  147. value = 32;
  148. long lSize = -1;
  149. // 创建散列对象, 校验文件
  150. HashAlgorithm hasher = SHA256.Create();
  151. using (CryptoStream cin = new CryptoStream(fin, sma.CreateDecryptor(), CryptoStreamMode.Read),
  152. chash = new CryptoStream(Stream.Null, hasher, CryptoStreamMode.Write))
  153. {
  154. // 读取文件长度
  155. BinaryReader br = new BinaryReader(cin);
  156. lSize = br.ReadInt64();
  157. ulong tag = br.ReadUInt64();
  158. if (FC_TAG != tag)
  159. throw new CryptoHelpException("文件被破坏");
  160. long numReads = lSize / BUFFER_SIZE;
  161. long slack = (long)lSize % BUFFER_SIZE;
  162. for (int i = 0; i < numReads; ++i)
  163. {
  164. read = cin.Read(bytes, 0, bytes.Length);
  165. fout.Write(bytes, 0, read);
  166. chash.Write(bytes, 0, read);
  167. value += read;
  168. outValue += read;
  169. }
  170. if (slack > 0)
  171. {
  172. read = cin.Read(bytes, 0, (int)slack);
  173. fout.Write(bytes, 0, read);
  174. chash.Write(bytes, 0, read);
  175. value += read;
  176. outValue += read;
  177. }
  178. chash.Flush();
  179. chash.Close();
  180. fout.Flush();
  181. fout.Close();
  182. byte[] curHash = hasher.Hash;
  183. // 获取比较和旧的散列对象
  184. byte[] oldHash = new byte[hasher.HashSize / 8];
  185. read = cin.Read(oldHash, 0, oldHash.Length);
  186. if ((oldHash.Length != read) || (!CheckByteArrays(oldHash, curHash)))
  187. throw new CryptoHelpException("文件被破坏");
  188. }
  189. if (outValue != lSize)
  190. throw new CryptoHelpException("文件大小不匹配");
  191. }
  192. }
  193. }
  194. //http://www.jb51.net/article/30277.htm 例子
  195. //调用方法
  196. //private void btnSelectFile_Click(object sender, EventArgs e)
  197. //{
  198. //if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
  199. //{
  200. //txtFileName.Text = openFileDialog1.FileName ;
  201. //}
  202. //}
  203. //private void btnEncryptFile_Click(object sender, EventArgs e)
  204. //{
  205. //string inFile=txtFileName.Text;
  206. //string outFile = inFile + ".dat";
  207. //string password=txtPassword.Text ;
  208. //DESFile.DESFileClass.EncryptFile(inFile, outFile, password);//加密文件
  209. ////删除加密前的文件
  210. //File.Delete(inFile);
  211. //txtFileName.Text = string.Empty;
  212. //MessageBox.Show("加密成功");
  213. //}
  214. //private void btnDecryptFile_Click(object sender, EventArgs e)
  215. //{
  216. //string inFile = txtFileName.Text;
  217. //string outFile = inFile.Substring(0,inFile.Length - 4);
  218. //string password = txtPassword.Text;
  219. //DESFile.DESFileClass.DecryptFile (inFile, outFile, password);//解密文件
  220. ////删除解密前的文件
  221. //File.Delete(inFile);
  222. //txtFileName.Text = string.Empty;
  223. //MessageBox.Show("解密成功");
  224. //}
  225. }