C#五大加密算法(AES、DES、MD5、RSA、SHA)

一、课程知识总分类

本次一共实现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不属于加密,只是二进制转文本,方便页面展示

相关推荐
namexingyun1 小时前
Scaling Law bug实战启示:从“虚胖“到“精瘦“的算力效率革命
开发语言·网络·人工智能·bug·ai编程
hnxaoli1 小时前
统信小程序(十六)xls转xlsx
开发语言·python·小程序
孝顺的书包1 小时前
将《C# 调用非托管程序》一文中最后一种方法修改如下(篇幅原因简化了注释):
开发语言·c#
辰三1 小时前
统信 UOS + GBase 8s 国产化环境部署实战:从虚拟机到数据库连接完整指南
linux·c#
标致的钢铁侠1 小时前
c# 温故而知新: 线程篇(一)
java·jvm·c#
不知名的老吴1 小时前
浅谈:编程语言中的那些「锁」事(二)
java·开发语言
蜗牛~turbo2 小时前
金蝶云星空的网络控制设置
开发语言·c#·金蝶·erp·云星空·k3 cloud
Reload.2 小时前
GJ航司,验证码网易易盾 JS逆向 纯算轨迹
开发语言·前端·javascript
人道领域3 小时前
【LeetCode刷题日记】贪心算法理论与实战:455.分发饼干最优解
java·开发语言·数据结构·算法·leetcode·贪心算法