using System;using System.IO;using System.Security.Cryptography;namespace ConsoleApp_SymmetricalEncryption{ class PRogram { static void Main(string[] args) { SymmetricalEncryption ss = new SymmetricalEncryption(); ss.EncryptFile(@"C:/error.txt", @"C:/error_EncryptFile.txt", ss.Key); Console.WriteLine("加密成功!"); Console.ReadKey(); ss.DecryptFile(@"C:/error_EncryptFile.txt", @"C:/error_DecryptFile.txt", ss.Key); Console.WriteLine("解密成功!"); Console.ReadKey(); } } /// <summary> /// 對文件使用對稱加密算法 /// </summary> public class SymmetricalEncryption { /* 對稱加密: * 需要發送者和接收者協定一個密鑰K,K可以是一個密鑰對,但必須是加密密鑰和解密密鑰之間能夠互相推算出來的。 * 常用的對稱加密算法中,加密解密共享一個密鑰。 * 本例中使用的是同一個密鑰; * * 非對稱加密: * 有一個密鑰對,分別為 公鑰、私鑰(公鑰用來加密,私鑰用來解密) * 私鑰永遠不需要傳遞給對方; * * 優缺點比較: * 非對稱加密算法復雜,導致加解密速度慢,只適合與數據量小的場合。 * 對稱加密解密效率高,系統開銷小,適合金星大數據量的加解密。(大文件一般適合使用對稱加密) */ /// <summary> /// 隨機產生的密鑰(也可以自己指定) /// 【注意:對稱加密算法 加密解密用的Key值是相同的(非對稱加密才分:公鑰和私鑰)】 /// </summary> public string Key = Guid.NewGuid().ToString().Replace("-", "").ToUpper() + Guid.NewGuid().ToString().Replace("-", "").ToUpper(); /// <summary> /// 緩沖區大小 /// </summary> private int bufferSize = 128 * 1024; /// <summary> /// 密鑰salt /// </summary> private byte[] salt = { 134, 216, 7, 36, 88, 164, 91, 227, 174, 76, 191, 197, 192, 154, 200, 248 }; //salt用來防止窮舉暴力破解(salt是在密鑰導出之前在密碼末尾引入的隨機字節,它使得這類攻擊變得非常困難) /// <summary> /// 初始化向量 /// </summary> private byte[] iv = { 134, 216, 7, 36, 88, 164, 91, 227, 174, 76, 191, 197, 192, 154, 200, 248 }; //初始化向量iv起到的也是增強破解難度的作用 /// <summary> /// 初始化 并返回對稱加密算法 /// </summary> /// <param name="argKey"></param> /// <param name="argSalt"></param> /// <returns></returns> private SymmetricAlgorithm CreateRijindael(string argKey, byte[] argSalt) { PassWordDeriveBytes pdb = new PasswordDeriveBytes(argKey, argSalt, "SHA256", 1000); SymmetricAlgorithm sma = Rijndael.Create(); sma.KeySize = 256; sma.Key = pdb.GetBytes(32); sma.Padding = PaddingMode.PKCS7; return sma; } /// <summary> /// 加密文件 /// </summary> /// <param name="argInFile">輸入文件</param> /// <param name="argOutFile">輸出加密后的文件</param> /// <param name="argKey">加密用的Key</param> public void EncryptFile(string argInFile, string argOutFile, string argKey) { using (FileStream inFileStream = File.OpenRead(argInFile), outFileStream = File.Open(argOutFile, FileMode.OpenOrCreate)) using (SymmetricAlgorithm algorithm = CreateRijindael(argKey, salt)) { algorithm.IV = iv; using (CryptoStream cryptoStream = new CryptoStream(outFileStream, algorithm.CreateEncryptor(), CryptoStreamMode.Write)) { byte[] bytes = new byte[bufferSize]; int readSize = -1; while ((readSize = inFileStream.Read(bytes, 0, bytes.Length)) != 0) { cryptoStream.Write(bytes, 0, readSize); } cryptoStream.Flush(); } } } /// <summary> /// 解密文件 /// </summary> /// <param name="argInFile">輸入待解密的文件</param> /// <param name="argOutFile">輸出解密后的文件</param> /// <param name="argKey">加密用的Key</param> public void DecryptFile(string argInFile, string argOutFile, string argKey) { try { using (FileStream inFileStream = File.OpenRead(argInFile), outFileStream = File.OpenWrite(argOutFile)) using (SymmetricAlgorithm algorithm = CreateRijindael(argKey, salt)) { algorithm.IV = iv; using (CryptoStream cryptoStream = new CryptoStream(inFileStream, algorithm.CreateDecryptor(), CryptoStreamMode.Read)) { byte[] bytes = new byte[bufferSize]; int readSize = -1; int numReads = (int)(inFileStream.Length / bufferSize); int slack = (int)(inFileStream.Length % bufferSize); for (int i = 0; i < numReads; ++i) { readSize = cryptoStream.Read(bytes, 0, bytes.Length); outFileStream.Write(bytes, 0, readSize); } if (slack > 0) { readSize = cryptoStream.Read(bytes, 0, (int)slack); outFileStream.Write(bytes, 0, readSize); } outFileStream.Flush(); } } } catch (Exception ex) { throw new Exception("解密失敗:" + ex.Message);//可能是密鑰輸入的不正確,或者文件被修改過 } } }}
新聞熱點
疑難解答