C#中實(shí)現(xiàn)AES算法加密解讀
更新時(shí)間:2023年02月26日 14:30:03 作者:yangzm996
這篇文章主要介紹了C#中實(shí)現(xiàn)AES算法加密實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
先上效果圖
文件和加密文件之間的轉(zhuǎn)換。

先添加輔助類
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ì)文本類文件
/// </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é)。
開始實(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讀寫
{
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讀寫
{
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ò)誤或加密文件被篡改,無法解密");
}
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文檔里面的彩色圖片或者文字等通過調(diào)用方法轉(zhuǎn)為文檔頁面為灰色調(diào)、無彩色效果的文檔??靵砀S小編一起學(xué)習(xí)吧2021-11-11
C#實(shí)現(xiàn)讀寫ini文件類實(shí)例
這篇文章主要介紹了C#實(shí)現(xiàn)讀寫ini文件類,實(shí)例分析了C#實(shí)現(xiàn)針對(duì)ini文件的讀、寫、刪除等操作的常用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-03-03
優(yōu)雅又實(shí)用的C#代碼優(yōu)化技巧分享
這篇文章主要為大家整理了一些優(yōu)雅又實(shí)用的C#代碼優(yōu)化技巧,文中的示例代碼講解詳細(xì),對(duì)我們深入了解C#有一定的幫助,需要的可以參考一下2023-06-06
C#中Winform窗體Form的關(guān)閉按鈕變灰色的方法
這篇文章主要介紹了C#中Winform窗體Form的關(guān)閉按鈕變灰色的方法,對(duì)于C#程序界面的設(shè)計(jì)有一定的借鑒價(jià)值,需要的朋友可以參考下2014-08-08

