一、课程知识总分类
本次一共实现5种加密算法,按照加密原理分为三大类,考试必考分类:
1. 对称加密算法(可逆加密)
特点:加密、解密使用同一个密钥;加密速度快;适合大批量数据加密
包含:AES加密、DES加密
2. 非对称加密算法(可逆加密)
特点:拆分公钥、私钥成对密钥;公钥加密、私钥解密;安全性高、运算慢
包含:RSA加密
3. 哈希摘要算法(不可逆、单向)
特点:无密钥、只能加密不能解密;输入任意长度文本,输出固定长度摘要;用于校验数据完整性
包含:MD5算法、SHA256算法
二、全局配置文件(公共依赖)
存放AES、DES加密密钥,统一配置管理,无需硬编码写死密钥
App.config 完整代码
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
<appSettings>
<!-- AES秘钥:16位 128位标准秘钥 -->
<add key="AESKEY" value="1234567890abcdef"/>
<!-- DES秘钥:固定8字节,算法强制要求 -->
<add key="DESKEY" value="12345678"/>
</appSettings>
</configuration>
配置读取命名空间
必须引入:using System.Configuration;
原生代码隐性问题:原版AES、DES将IV初始向量直接读取密钥字段,课堂代码原样保留,不修改业务逻辑,仅做笔记标注
三、第一类:对称加密算法(工具类代码)
3.1 AESHelper 高级对称加密
① 算法原理(保留老师原版注释)
AES:加密算法加密或解密的过程采用同一个秘钥,是一个对称的加密算法
加密过程:先把明文分成一段一段的,先把第一段明文和秘钥以及初始向量进行异或运算,得到一个加密之后的密文,然后再拿出第二段明文和上一次密文进行异或运算,最终得到一个加密之后的文件
必备参数:
秘钥:AES采用128位/192位/256位的秘钥
IV 初始向量:为了让每次加密之后得到密文不一样,需要初始向量不一样
② 完整源码
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.ComTypes;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace EncryptTool
{
public class AESHelper
{
//AES:加密算法加密或解密的过程采用同一个秘钥,是一个对称的加密算法
// 加密过程,先把明文分成一段一段的,先把第一段明文和秘钥以及初始向量进行异或运算,得到一个加密之后的密文,
//然后再拿出第二段明文和上一次密文进行异或运算,最终得到一个加密之后的文件
//需要必备的参数
//秘钥:AES采用128位/192位/256位的秘钥
//IV 初始向量:为了让每次加密之后得到密文不一样,需要初始向量不一样
//读取配置文件秘钥字符串
private static readonly string keyString = ConfigurationManager.AppSettings["AESKEY"];// 秘钥
//课堂原版写法:初始向量复用秘钥字段
private static readonly string IV = ConfigurationManager.AppSettings["AESKEY"];// 初始向量
// 把秘钥字符串转成字节数组,加密算法只识别字节
private static readonly byte[] key = Encoding.UTF8.GetBytes(keyString);// 秘钥字节数组
private static readonly byte[] iv = Encoding.UTF8.GetBytes(IV);// 向量字节数组
/// <summary>
/// AES加密
/// </summary>
/// <param name="data">明文</param>
/// <returns>Base64格式密文</returns>
public static string Encrypt(string data)
{
//1、创建对应算法的实例对象,using自动释放资源
using (Aes aes = Aes.Create())
{
//2、给加密算法赋值必备参数
aes.Key = key; //绑定秘钥
aes.IV = iv; //绑定初始向量
//3、创建加密转换器,绑定秘钥和初始向量,生成加密规则
ICryptoTransform cryptoTransform = aes.CreateEncryptor(aes.Key, aes.IV);
//4、创建内存流,临时存放加密二进制数据
using (MemoryStream stream = new MemoryStream())
{
//5、封装加密流:绑定内存流、加密转换器,开启写入模式
using (CryptoStream cptstream = new CryptoStream(stream, cryptoTransform, CryptoStreamMode.Write))
{
//文本写入流,写入明文自动加密
using (StreamWriter sw = new StreamWriter(cptstream))
{
sw.Write(data);//写入明文数据
}
}
//二进制密文转Base64字符串,方便页面展示、传输保存
return Convert.ToBase64String(stream.ToArray());
}
}
}
/// <summary>
/// AES解密
/// </summary>
/// <param name="data">密文</param>
/// <returns>明文</returns>
public static string Decrypt(string data)
{
using (Aes aes = Aes.Create())
{
//绑定解密参数,必须和加密完全一致
aes.Key = key;
aes.IV = iv;
//创建解密转换器
ICryptoTransform cryptoTransform = aes.CreateDecryptor(aes.Key, aes.IV);
//把Base64密文还原加密字节数组
byte[] bytes = Convert.FromBase64String(data);
//加载密文字节数组进入内存流
using (MemoryStream stream = new MemoryStream(bytes))
{
//解密流:开启读取模式
using (CryptoStream cptstream = new CryptoStream(stream, cryptoTransform, CryptoStreamMode.Read))
{
//读取解密后的明文,直接返回
using (StreamReader sw = new StreamReader(cptstream))
{
return sw.ReadToEnd();
}
}
}
}
}
}
}
3.2 DESHelper 传统对称加密
① 算法原理
1、64 位原始密钥 剥离奇偶校验位,得到 56 位有效密钥
2、用户输入 64 位二进制密钥,每 8 位为一组,每组最后 1 位是奇偶校验位;
3、通过PC-1 置换表打乱重排,丢弃8个校验位,输出56位密钥;
4、拆分密钥左右两半,循环移位16轮,生成子密钥;
5、轮函数异或运算,完成加密;DES固定使用56位有效密钥
② 完整源码
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace EncryptTool
{
public class DESHelper
{
//一、第一步:64 位原始密钥 剥离奇偶校验位,得到 56 位密钥
//1.用户输入 64 位二进制密钥,每 8 位为一组,每组最后 1 位是奇偶校验位(保证每组 1 的个数为奇数);
//2.通过PC-1 置换表打乱重排 64 位,直接丢弃 8 个校验位,输出 56 位密钥;
//3.将 56 位密钥平分为左右两半:C0(前28位)、D0(后28位)。
//4 对 C0、D0 循环移位 16 次,每轮移位后合并、压缩得到一轮子密钥:
//5 加密时按 K₁到 K₁₆的顺序 一一对应供给 16 轮 Feistel(费斯泰尔轮函数) 轮函数做密钥异或混淆运算
//读取配置文件DES秘钥,固定8字节
private static readonly string keyString = ConfigurationManager.AppSettings["DESKEY"];
// DES底层使用56位有效密钥,传入8字节64位秘钥自动剥离校验位
private static readonly byte[] Key = Encoding.UTF8.GetBytes(keyString);
//课堂原版:初始向量复用秘钥
private static readonly byte[] IV = Encoding.UTF8.GetBytes(keyString);
/// <summary>
/// DES加密
/// </summary>
/// <param name="data"> 明文</param>
/// <returns>Base64密文</returns>
public static string Encrypt(string data)
{
//创建DES加密服务对象
using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
{
//创建内存流,存放加密数据
MemoryStream ms = new MemoryStream();
//绑定加密转换器,构建加密流
CryptoStream cstream = new CryptoStream(ms, des.CreateEncryptor(Key, IV), CryptoStreamMode.Write);
//明文转字节数组
byte[] bs = Encoding.UTF8.GetBytes(data);
cstream.Write(bs, 0, bs.Length); //写入加密流自动加密
cstream.FlushFinalBlock();//清空缓冲区,补齐加密尾部数据
return Convert.ToBase64String(ms.ToArray());
}
}
/// <summary>
/// DES解密
/// </summary>
/// <param name="data"> 密文</param>
/// <returns>明文</returns>
public static string Decrypt(string data)
{
using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
{
//Base64密文解码
byte[] bs = Convert.FromBase64String(data);
MemoryStream ms = new MemoryStream();
//创建解密流
CryptoStream cstream = new CryptoStream(ms, des.CreateDecryptor(Key, IV), CryptoStreamMode.Write);
cstream.Write(bs, 0, bs.Length);
cstream.FlushFinalBlock();
//解密字节转回字符串返回
return Encoding.UTF8.GetString(ms.ToArray());
}
}
}
}
四、第二类:非对称加密算法
RSAHelper 非对称加密
① 算法原理
RSA:是一种非对称加密算法,它使用公钥对数据进行加密,使用私钥对数据进行解密
1、公私钥成对生成,一一对应
2、公钥:公开分发,所有人可见,负责加密数据
3、私钥:私密保存,不可外泄,负责解密数据
4、安全性最高,加密速度最慢,适合加密账号、密钥等少量敏感数据
② 完整源码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace EncryptTool
{
public class RSAHelper
{
//RSA:是一种非对称加密算法,它使用公钥对数据进行加密,使用私钥对数据进行解密
// 静态全局公私钥
public static string pub = "<RSAKeyValue><Modulus>n0BquCSJJJAB7sRpOLpv2VB0sLf9kHju0gRult26SqWOcpPXmTJA9OkN9eG0zttXCLgxJGFOaaorjwPtGYtOtUasXhP4zZMFSxWK6qnggH0ObFPFUPvpuJqZDMKxsCKFWof2mY7FAmhGjhDBUZRO67KYBrbsIbSPuyU/BWEkkLE=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
public static string pri = "<RSAKeyValue><Modulus>n0BquCSJJJAB7sRpOLpv2VB0sLf9kHju0gRult26SqWOcpPXmTJA9OkN9eG0zttXCLgxJGFOaaorjwPtGYtOtUasXhP4zZMFSxWK6qnggH0ObFPFUPvpuJqZDMKxsCKFWof2mY7FAmhGjhDBUZRO67KYBrbsIbSPuyU/BWEkkLE=</Modulus><Exponent>AQAB</Exponent><P>0VGhp5MfPtaHkXI4C8ARK0qXXIUWU1X2W21sU+iWuvDRQocH/dKCEE7WSAzBl/JdhTjWSbflcnQQGdG9I6n8ww==</P><Q>wsRcmikGdhGJKAqqbQi+LBQSUHMSIpzBEXX896GftTsMKhkrJh8DieaKZbXSJbraysAxmnnejY8JFSgt1xF1ew==</Q><DP>fYEjmzV0c5nv2T6R6kG0Sa/Ex52owDj3qOQYIst/rQD9h5UtLnyMrbiHdNXpMfEJL/rfSX4w3gpHKSP/8yVWPw==</DP><DQ>BsgjmVKYYQAXUIeei5FkXdCNGrQHC6F9r4f2OQEtuHfH4qdhs0AdNW4Ln6MHID0zZR/wGjroHvG+FTiC8BwxhQ==</DQ><InverseQ>K55gtRDUQab/W25PkYZ6YATqT0fLbQ/zS1/TUlWCWtayhvYSwbzqpDzYDr6kzGFLg5QRAqa4e1yKZ0YGU/XW9Q==</InverseQ><D>dvpGgQry1zkr6Hofbr2DgOVmOP1NWNmw+4FKKja/zrM/6IRiCFeORiu0PWaCkiU3MhGCzX5Regoj/vZc9r+obgLX7AEDRhtg1NAfv6kF3Vidppy+HC9yKhQ/Z0BHYtmHmDuLYnsfRFgkZzdVwPkQ2BevWAySJh4VD5ARcrbehF0=</D></RSAKeyValue>";
/// <summary>
/// 生成公私钥方法,程序启动自动调用
/// </summary>
public static void GetPairKey()
{
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.PersistKeyInCsp = false;//禁止秘钥存入系统密码管理器
pub = rsa.ToXmlString(false); // 参数false:生成公钥
pri = rsa.ToXmlString(true); // 参数true:生成私钥
Console.WriteLine(pub);
Console.WriteLine(pri);
}
}
/// <summary>
/// RSA加密:公钥加密
/// </summary>
public static string Encrypt(string data)
{
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.PersistKeyInCsp = false;
rsa.FromXmlString(pub);//加载公钥
byte[] bs = Encoding.UTF8.GetBytes(data);
byte[] bs1 = rsa.Encrypt(bs, false);//执行加密
return Convert.ToBase64String(bs1);
}
}
/// <summary>
/// RSA解密:私钥解密
/// </summary>
public static string Decrypt(string data)
{
byte[] bs = Convert.FromBase64String(data);
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.PersistKeyInCsp = false;
rsa.FromXmlString(pri);//加载私钥
byte[] bs1 = rsa.Decrypt(bs, false);//执行解密
return Encoding.UTF8.GetString(bs1);
}
}
}
}
五、第三类:哈希不可逆摘要算法
5.1 MD5Helper 哈希算法
算法特性
-
不属于加密算法,是哈希摘要算法
-
不可逆:只能明文生成摘要,无法解密还原明文
-
定长输出:任意文本,固定输出128位哈希值
-
适用场景:账号密码加密、文件完整性校验
完整源码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace EncryptTool
{
public class MD5Helper
{
// MD5:不是加密算法,是哈希摘要算法
// 不可逆:只能从明文算出哈希摘要,不能从哈希摘要逆推原始数据
// 定长输出:任意长度的输入,固定输出128位(16个字节)
public static string Encrypt(string data)
{
using (var md5 = MD5.Create())//创建md5算法实例
{
byte[] bs = Encoding.ASCII.GetBytes(data);//明文转ascii字节数组
byte[] hashBS = md5.ComputeHash(bs); //计算哈希摘要
StringBuilder sb = new StringBuilder();
//遍历字节,转为16进制字符串
for (int i = 0; i < hashBS.Length; i++)
{
//X2:转为大写16进制,不足两位自动补0
sb.Append(hashBS[i].ToString("X2"));
}
return sb.ToString();
}
}
}
}
5.2 SHAHelper 哈希算法
算法特性
-
SHA 和 MD5 一致,属于单向哈希摘要算法,不可逆
-
包含SHA1、SHA256、SHA384、SHA512
-
安全性:SHA256 > MD5,企业项目优先使用SHA
-
用途:合同签名、数据校验、高安全密码加密
完整源码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace EncryptTool
{
public static class SHAHelper
{
//SHA 不是加密(不能解密),是密码哈希摘要算法:输入任意长度原文,输出固定长度不可逆哈希值,用于完整性校验、数字签名
/// <summary>
/// SHA256摘要加密
/// </summary>
/// <param name="data">明文</param>
/// <returns>十六进制哈希字符串</returns>
public static string Encrypt(string data)
{
byte[] plainBytes = Encoding.UTF8.GetBytes(data);
// 包括SHA-1、SHA-256、SHA-384和SHA-512。相比于MD5,SHA系列算法更安全。
using (SHA256 cryptoProvider = new SHA256CryptoServiceProvider())
{
byte[] hashBytes = cryptoProvider.ComputeHash(plainBytes);
StringBuilder hashBuilder = new StringBuilder();
foreach (byte b in hashBytes)
{
hashBuilder.Append(b.ToString("x2"));//小写16进制
}
return hashBuilder.ToString();
}
}
}
}
六、WinForm 窗体调用代码
统一调用五大加密工具类,注释切换算法,和课堂代码完全一致
using EncryptTool;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
namespace _2加密
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
RSAHelper.GetPairKey();//程序启动初始化,生成RSA公私钥
}
//解密按钮
private void button2_Click(object sender, EventArgs e)
{
// textBox1.Text = AESHelper.Decrypt(textBox2.Text); //AES解密
// textBox1.Text = DESHelper.Decrypt(textBox2.Text); //DES解密
// textBox1.Text = RSAHelper.Decrypt(textBox2.Text); //RSA解密
}
//加密按钮
private void button1_Click(object sender, EventArgs e)
{
// textBox2.Text = AESHelper.Encrypt(textBox1.Text); //AES加密
// textBox2.Text = DESHelper.Encrypt(textBox1.Text); //DES加密
// textBox2.Text = RSAHelper.Encrypt(textBox1.Text); //RSA加密
// textBox2.Text = MD5Helper.Encrypt(textBox1.Text); //MD5哈希
textBox2.Text = SHAHelper.Encrypt(textBox1.Text); //SHA256哈希
}
}
}
七、算法分类对比(考试背诵)
| 算法分类 | 具体算法 | 是否可逆 | 密钥规则 | 优缺点 |
|---|---|---|---|---|
| 对称加密 | AES | 可逆 | 加密解密同一密钥 | 安全高、速度快、主流加密 |
| 对称加密 | DES | 可逆 | 固定8字节密钥 | 老旧算法、安全性弱 |
| 非对称加密 | RSA | 可逆 | 公钥加密、私钥解密 | 安全性最高、运算最慢 |
| 哈希摘要 | MD5 | 不可逆 | 无密钥 | 算法老旧、存在破解风险 |
| 哈希摘要 | SHA256 | 不可逆 | 无密钥 | 安全可靠、项目首选 |
| 算法 | 加密类型 | 是否可逆 | 秘钥特点 | 使用场景 |
|---|---|---|---|---|
| AES | 对称加密 | 可逆 | 同一秘钥,128/256位 | 文件、大量业务数据加密 |
| DES | 对称加密 | 可逆 | 8字节秘钥,有效56位 | 老旧系统兼容加密 |
| RSA | 非对称加密 | 可逆 | 公钥加密、私钥解密 | 密钥、核心机密加密 |
| MD5 | 哈希摘要 | 不可逆 | 无秘钥 | 密码校验、文件校验 |
| SHA256 | 哈希摘要 | 不可逆 | 无秘钥 | 高安全数据校验、签名 |
八、课堂易错知识点(分类整理)
1. 对称加密易错点
-
AES、DES加解密密钥、IV向量必须一模一样,解密失败大概率密钥不一致
-
DES密钥强制8字节,长度错误直接报错
2. 非对称加密易错点
-
RSA必须公钥加密、私钥解密,密钥顺序不可颠倒
-
公私钥一一对应,更换密钥无法解密
3. 哈希算法易错点
-
MD5、SHA不是加密算法,属于摘要算法,绝对不能解密
-
Base64不属于加密,只是二进制转文本,方便页面展示