C#中实现AES算法加密解读

作者:yangzm996 时间:2022-09-17 16:49:36 

先上效果图

文件和加密文件之间的转换。

C#中实现AES算法加密解读

先添加辅助类

public class AES_EnorDecrypt
   {
       //定义默认密钥
       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>
       /// 随机生成密钥,默认密钥长度为32,不足在加密时自动填充空格
       /// </summary>
       /// <param name="n">密钥长度</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加密,针对文本类文件
       /// </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())
               {
                   //把内存流对象包装成加密流对象
                   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())
               {
                   //把内存流对象包装成加密流对象
                   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解密,针对文本文件
       /// </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))
               {
                   //把内存流对象包装成加密对象
                   using (CryptoStream Decryptor = new CryptoStream(Memory, Aes.CreateDecryptor(bKey, bVector), CryptoStreamMode.Read))
                   {
                       //明文存储区
                       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))
               {
                   //把内存流对象包装成加密对象
                   using (CryptoStream Decryptor = new CryptoStream(Memory, Aes.CreateDecryptor(bKey, bVector), CryptoStreamMode.Read))
                   {
                       //明文存储区
                       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是块加密,块的长度是16字节,如果原文不到16的字节,就会进行填充至16个字节。

开始实现

界面布局

C#中实现AES算法加密解读

textbox1为文件位置,textbox2为密码。

C#中实现AES算法加密解读

C#中实现AES算法加密解读

C#中实现AES算法加密解读

设置好后

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;//该值确定是否可以选择多个文件
           dialog.Title = "请选择文件夹";
           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>
       /// 后台线程执行的方法
       /// </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;//已经读取的流大小
               //每50MB加密后会变成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//重新设定读取流大小,避免最后多余空值
                   {
                       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>
       /// 执行完成时触发
       /// </summary>
       /// <param name="sender"></param>
       /// <param name="e"></param>
       private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
       {
           MessageBox.Show("加密成功!");
       }

/// <summary>
       /// 后台线程执行的方法
       /// </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];//解密缓冲区50MB+16B
                   byte[] decrpt = new byte[52428800];//解密后的50MB
                   int numBytesRead = 52428816;//每次解密的流大小
                   long leftBytes = sr.Length;//剩余需要解密的流大小
                   long readBytes = 0;//已经读取的流大小
                   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//重新设定读取流大小,避免最后多余空值
                           {
                               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>
       /// 执行完成时触发
       /// </summary>
       /// <param name="sender"></param>
       /// <param name="e"></param>
       private void backgroundWorker2_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
       {
           if (e.Cancelled)
           {
              MessageBox.Show("解密失败\n密码错误或加密文件被篡改,无法解密");                
           }
           else
           {
               MessageBox.Show("解密成功!");
           }
       }  
   }

来源:https://blog.csdn.net/weixin_39448579/article/details/119953604

标签:C#,AES,算法加密
0
投稿

猜你喜欢

  • java 引用传递的三种类型小结

    2023-09-03 03:59:47
  • java语言基础之标识符和命名规则详解

    2023-04-21 16:50:18
  • Java操作Redis2种方法代码详解

    2022-09-10 22:58:56
  • Flutter 状态管理的实现

    2023-08-21 02:38:33
  • Java多线程 Guarded Suspension设计模式

    2023-03-12 01:52:00
  • java显示当前运行时的参数(java运行参数)

    2023-09-07 10:03:22
  • java字符串遍历的几种常用方法总结

    2022-08-19 06:36:41
  • Java基础之多线程

    2022-11-30 11:01:43
  • 浅谈Java封装、继承、多态特性

    2023-10-09 13:59:35
  • SpringMVC请求流程源码解析

    2021-08-07 03:35:11
  • Java的关键字与标识符小结

    2023-08-17 08:36:50
  • 详解Java接口签名(Signature)实现方案

    2022-02-05 09:28:57
  • Springboot - Fat Jar示例详解

    2023-11-19 21:28:35
  • java json 省市级联实例代码

    2021-11-13 18:50:35
  • Java中io流解析及代码实例

    2023-08-22 16:46:48
  • 如何将写好的.py/.java程序变成.exe文件详解

    2022-04-06 09:22:14
  • 自定义log4j日志文件命名规则说明

    2021-11-21 16:55:51
  • 浅谈java中守护线程与用户线程

    2023-11-26 20:46:41
  • Java的split方法使用详解

    2021-10-03 06:09:57
  • java实现简单快递系统

    2021-11-28 07:01:57
  • asp之家 软件编程 m.aspxhome.com