C#中實(shí)現(xiàn)AES算法加密解讀
先上效果圖
文件和加密文件之間的轉(zhuǎn)換。
先添加輔助類(lèi)
public class AES_EnorDecrypt { //定義默認(rèn)密鑰 private static byte[] _aesKeyByte = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF }; private static string _aesKeyStr = Encoding.UTF8.GetString(_aesKeyByte); /// <summary> /// 隨機(jī)生成密鑰,默認(rèn)密鑰長(zhǎng)度為32,不足在加密時(shí)自動(dòng)填充空格 /// </summary> /// <param name="n">密鑰長(zhǎng)度</param> /// <returns></returns> public static string GetIv(int n) { string s = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; char[] arrChar = new char[s.Length]; for (int i = 0; i < s.Length; i++) { arrChar[i] = Convert.ToChar(s.Substring(i, 1)); } StringBuilder num = new StringBuilder(); Random rnd = new Random(DateTime.Now.Millisecond); for (int i = 0; i < n; i++) { num.Append(arrChar[rnd.Next(0, arrChar.Length)].ToString()); } _aesKeyByte = Encoding.UTF8.GetBytes(num.ToString()); return _aesKeyStr = Encoding.UTF8.GetString(_aesKeyByte); } /// <summary> /// AES加密,針對(duì)文本類(lèi)文件 /// </summary> /// <param name="Data">被加密的明文</param> /// <param name="Key">密鑰</param> /// <param name="Vector">密鑰向量</param> /// <returns>密文</returns> public static string AESEncrypt(string Data, string Key, string Vector) { byte[] plainBytes = Encoding.UTF8.GetBytes(Data); byte[] bKey = new byte[32]; Array.Copy(Encoding.UTF8.GetBytes(Key.PadRight(bKey.Length)), bKey, bKey.Length); byte[] bVector = new byte[16]; Array.Copy(Encoding.UTF8.GetBytes(Vector.PadRight(bVector.Length)), bVector, bVector.Length); byte[] Cryptograph = null;//加密后的密文 Rijndael Aes = Rijndael.Create(); try { using (MemoryStream Memory = new MemoryStream()) { //把內(nèi)存流對(duì)象包裝成加密流對(duì)象 using (CryptoStream Encryptor = new CryptoStream(Memory, Aes.CreateEncryptor(bKey, bVector), CryptoStreamMode.Write)) { Encryptor.Write(plainBytes, 0, plainBytes.Length); Encryptor.FlushFinalBlock(); Cryptograph = Memory.ToArray(); } } } catch { Cryptograph = null; } return Convert.ToBase64String(Cryptograph); } /// <summary> /// AES加密,任意文件 /// </summary> /// <param name="Data">被加密的明文</param> /// <param name="Key">密鑰</param> /// <param name="Vector">密鑰向量</param> /// <returns>密文</returns> public static byte[] AESEncrypt(byte[] Data, string Key, string Vector) { byte[] bKey = new byte[32]; Array.Copy(Encoding.UTF8.GetBytes(Key.PadRight(bKey.Length)), bKey, bKey.Length); byte[] bVector = new byte[16]; Array.Copy(Encoding.UTF8.GetBytes(Vector.PadRight(bVector.Length)), bVector, bVector.Length); byte[] Cryptograph = null;//加密后的密文 Rijndael Aes = Rijndael.Create(); try { using (MemoryStream Memory = new MemoryStream()) { //把內(nèi)存流對(duì)象包裝成加密流對(duì)象 using (CryptoStream Encryptor = new CryptoStream(Memory, Aes.CreateEncryptor(bKey, bVector), CryptoStreamMode.Write)) { Encryptor.Write(Data, 0, Data.Length); Encryptor.FlushFinalBlock(); Cryptograph = Memory.ToArray(); } } } catch { Cryptograph = null; } return Cryptograph; } /// <summary> /// AES解密,針對(duì)文本文件 /// </summary> /// <param name="Data">被解密的密文</param> /// <param name="Key">密鑰</param> /// <param name="Vector">密鑰向量</param> /// <returns>明文</returns> public static string AESDecrypt(string Data, string Key, string Vector) { byte[] encryptedBytes = Convert.FromBase64String(Data); byte[] bKey = new byte[32]; Array.Copy(Encoding.UTF8.GetBytes(Key.PadRight(bKey.Length)), bKey, bKey.Length); byte[] bVector = new byte[16]; Array.Copy(Encoding.UTF8.GetBytes(Vector.PadRight(bVector.Length)), bVector, bVector.Length); byte[] original = null;//解密后的明文 Rijndael Aes = Rijndael.Create(); try { using (MemoryStream Memory = new MemoryStream(encryptedBytes)) { //把內(nèi)存流對(duì)象包裝成加密對(duì)象 using (CryptoStream Decryptor = new CryptoStream(Memory, Aes.CreateDecryptor(bKey, bVector), CryptoStreamMode.Read)) { //明文存儲(chǔ)區(qū) using (MemoryStream originalMemory = new MemoryStream()) { byte[] Buffer = new byte[1024]; int readBytes = 0; while ((readBytes = Decryptor.Read(Buffer, 0, Buffer.Length)) > 0) { originalMemory.Write(Buffer, 0, readBytes); } original = originalMemory.ToArray(); } } } } catch { original = null; } return Encoding.UTF8.GetString(original); } /// <summary> /// AES解密,任意文件 /// </summary> /// <param name="Data">被解密的密文</param> /// <param name="Key">密鑰</param> /// <param name="Vector">密鑰向量</param> /// <returns>明文</returns> public static byte[] AESDecrypt(byte[] Data, string Key, string Vector) { byte[] bKey = new byte[32]; Array.Copy(Encoding.UTF8.GetBytes(Key.PadRight(bKey.Length)), bKey, bKey.Length); byte[] bVector = new byte[16]; Array.Copy(Encoding.UTF8.GetBytes(Vector.PadRight(bVector.Length)), bVector, bVector.Length); byte[] original = null;//解密后的明文 Rijndael Aes = Rijndael.Create(); try { using (MemoryStream Memory = new MemoryStream(Data)) { //把內(nèi)存流對(duì)象包裝成加密對(duì)象 using (CryptoStream Decryptor = new CryptoStream(Memory, Aes.CreateDecryptor(bKey, bVector), CryptoStreamMode.Read)) { //明文存儲(chǔ)區(qū) using (MemoryStream originalMemory = new MemoryStream()) { byte[] Buffer = new byte[1024]; int readBytes = 0; while ((readBytes = Decryptor.Read(Buffer, 0, Buffer.Length)) > 0) { originalMemory.Write(Buffer, 0, readBytes); } original = originalMemory.ToArray(); } } } } catch { original = null; } return original; } }
AES是塊加密,塊的長(zhǎng)度是16字節(jié),如果原文不到16的字節(jié),就會(huì)進(jìn)行填充至16個(gè)字節(jié)。
開(kāi)始實(shí)現(xiàn)
界面布局
textbox1為文件位置,textbox2為密碼。
設(shè)置好后
public partial class FormAes : Form { #region 屬性 private static string _aesKeyVector = "q2T_=R/*33vc"; #endregion public FormAes() { InitializeComponent(); } /// <summary> /// 選擇文件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void textBox1_Click(object sender, EventArgs e) { OpenFileDialog dialog = new OpenFileDialog(); dialog.Multiselect = true;//該值確定是否可以選擇多個(gè)文件 dialog.Title = "請(qǐng)選擇文件夾"; dialog.Filter = "所有文件(*.*)|*.*"; if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) { textBox1.Text = dialog.FileName; } } /// <summary> /// 加密 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button1_Click(object sender, EventArgs e) { if (string.IsNullOrWhiteSpace(textBox1.Text.Trim()) || string.IsNullOrWhiteSpace(textBox2.Text.Trim())) return; backgroundWorker1.RunWorkerAsync(); } /// <summary> /// 解密 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button2_Click(object sender, EventArgs e) { if (string.IsNullOrWhiteSpace(textBox1.Text.Trim()) || string.IsNullOrWhiteSpace(textBox2.Text.Trim())) return; backgroundWorker2.RunWorkerAsync(); } /// <summary> /// 后臺(tái)線程執(zhí)行的方法 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { string KeyVector = _aesKeyVector;//密鑰向量 string path = Path.GetDirectoryName(textBox1.Text); string name = Path.GetFileName(textBox1.Text); name += ".En"; #region 加密 FileStream sr = new FileStream(textBox1.Text, FileMode.Open, FileAccess.Read); FileStream sw = new FileStream(path + "\\" + name, FileMode.Create, FileAccess.Write); if (sr.Length > 50 * 1024 * 1024)//如果文件大于50M,采取分塊加密,按50MB讀寫(xiě) { byte[] mybyte = new byte[52428800];//每50MB加密一次 int numBytesRead = 52428800;//每次加密的流大小 long leftBytes = sr.Length;//剩余需要加密的流大小 long readBytes = 0;//已經(jīng)讀取的流大小 //每50MB加密后會(huì)變成50MB+16B byte[] encrpy = new byte[52428816]; while (true) { if (leftBytes > numBytesRead) { sr.Read(mybyte, 0, mybyte.Length); encrpy = AES_EnorDecrypt.AESEncrypt(mybyte, textBox2.Text, KeyVector); sw.Write(encrpy, 0, encrpy.Length); leftBytes -= numBytesRead; readBytes += numBytesRead; backgroundWorker1.ReportProgress((int)(readBytes * 100 / sr.Length)); } else//重新設(shè)定讀取流大小,避免最后多余空值 { byte[] newByte = new byte[leftBytes]; sr.Read(newByte, 0, newByte.Length); byte[] newWriteByte; newWriteByte = AES_EnorDecrypt.AESEncrypt(newByte, textBox2.Text, KeyVector); sw.Write(newWriteByte, 0, newWriteByte.Length); readBytes += leftBytes; backgroundWorker1.ReportProgress((int)(readBytes * 100 / sr.Length)); break; } } } else { byte[] mybyte = new byte[sr.Length]; sr.Read(mybyte, 0, (int)sr.Length); mybyte = AES_EnorDecrypt.AESEncrypt(mybyte, textBox2.Text, KeyVector); sw.Write(mybyte, 0, mybyte.Length); backgroundWorker1.ReportProgress(100); } sr.Close(); sw.Close(); #endregion } private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) { progressBar1.Value = e.ProgressPercentage; } /// <summary> /// 執(zhí)行完成時(shí)觸發(fā) /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { MessageBox.Show("加密成功!"); } /// <summary> /// 后臺(tái)線程執(zhí)行的方法 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e) { try { string KeyVector = _aesKeyVector;//密鑰向量 string path = Path.GetDirectoryName(textBox1.Text); string name = Path.GetFileName(textBox1.Text); if (name.EndsWith(".En")) { name = name.Remove(name.Length - 3, 3); } #region 解密 FileStream sr = new FileStream(textBox1.Text, FileMode.Open, FileAccess.Read); FileStream sw = new FileStream(path + "\\" + name, FileMode.Create, FileAccess.Write); if (sr.Length > 50 * 1024 * 1024)//如果文件大于50M,采取分塊解密,按50MB讀寫(xiě) { byte[] mybyte = new byte[52428816];//解密緩沖區(qū)50MB+16B byte[] decrpt = new byte[52428800];//解密后的50MB int numBytesRead = 52428816;//每次解密的流大小 long leftBytes = sr.Length;//剩余需要解密的流大小 long readBytes = 0;//已經(jīng)讀取的流大小 try { while (true) { if (leftBytes > numBytesRead) { sr.Read(mybyte, 0, mybyte.Length); decrpt = AES_EnorDecrypt.AESDecrypt(mybyte, textBox2.Text, KeyVector); sw.Write(decrpt, 0, decrpt.Length); leftBytes -= numBytesRead; readBytes += numBytesRead; backgroundWorker2.ReportProgress((int)(readBytes * 100 / sr.Length)); } else//重新設(shè)定讀取流大小,避免最后多余空值 { byte[] newByte = new byte[leftBytes]; sr.Read(newByte, 0, newByte.Length); byte[] newWriteByte; newWriteByte = AES_EnorDecrypt.AESDecrypt(newByte, textBox2.Text, KeyVector); sw.Write(newWriteByte, 0, newWriteByte.Length); readBytes += leftBytes; backgroundWorker2.ReportProgress((int)(readBytes * 100 / sr.Length)); break; } } } catch { sr.Close(); sw.Close(); File.Delete(path + "\\" + name); e.Cancel = true; } sr.Close(); sw.Close(); } else { byte[] mybyte = new byte[(int)sr.Length]; sr.Read(mybyte, 0, (int)sr.Length); try { mybyte = AES_EnorDecrypt.AESDecrypt(mybyte, textBox2.Text, KeyVector); sw.Write(mybyte, 0, mybyte.Length); backgroundWorker2.ReportProgress(100); } catch { sr.Close(); sw.Close(); File.Delete(path + "\\" + name); e.Cancel = true; } sr.Close(); sw.Close(); } #endregion } catch { e.Cancel = true; } } private void backgroundWorker2_ProgressChanged(object sender, ProgressChangedEventArgs e) { progressBar1.Value = e.ProgressPercentage; } /// <summary> /// 執(zhí)行完成時(shí)觸發(fā) /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void backgroundWorker2_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Cancelled) { MessageBox.Show("解密失敗\n密碼錯(cuò)誤或加密文件被篡改,無(wú)法解密"); } else { MessageBox.Show("解密成功!"); } } }
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
C#/VB.NET?實(shí)現(xiàn)彩色PDF轉(zhuǎn)為灰度PDF
本文以C#代碼為例介紹如何實(shí)現(xiàn)將彩色PDF文件轉(zhuǎn)為灰度(黑白)的PDF文件,即將PDF文檔里面的彩色圖片或者文字等通過(guò)調(diào)用方法轉(zhuǎn)為文檔頁(yè)面為灰色調(diào)、無(wú)彩色效果的文檔??靵?lái)跟隨小編一起學(xué)習(xí)吧2021-11-11C#實(shí)現(xiàn)讀寫(xiě)ini文件類(lèi)實(shí)例
這篇文章主要介紹了C#實(shí)現(xiàn)讀寫(xiě)ini文件類(lèi),實(shí)例分析了C#實(shí)現(xiàn)針對(duì)ini文件的讀、寫(xiě)、刪除等操作的常用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-03-03優(yōu)雅又實(shí)用的C#代碼優(yōu)化技巧分享
這篇文章主要為大家整理了一些優(yōu)雅又實(shí)用的C#代碼優(yōu)化技巧,文中的示例代碼講解詳細(xì),對(duì)我們深入了解C#有一定的幫助,需要的可以參考一下2023-06-06C#實(shí)現(xiàn)CSV文件讀寫(xiě)的示例詳解
這篇文章主要介紹了CsvHelper、TextFieldParser、正則表達(dá)式三種解析CSV文件的方法,順帶也會(huì)介紹一下CSV文件的寫(xiě)方法,需要的可以參考一下2023-05-05C#使用selenium實(shí)現(xiàn)爬蟲(chóng)
這篇文章介紹了C#使用selenium實(shí)現(xiàn)爬蟲(chóng)的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06C#中Winform窗體Form的關(guān)閉按鈕變灰色的方法
這篇文章主要介紹了C#中Winform窗體Form的關(guān)閉按鈕變灰色的方法,對(duì)于C#程序界面的設(shè)計(jì)有一定的借鑒價(jià)值,需要的朋友可以參考下2014-08-08