AES加解密 - 快速上手
@[toc]
简介
这个标准用来替代原先的DES(Data Encryption Standard),已经被多方分析且广为全世界所使用。经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院 (NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准。2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一 。
AES作为计算机领域最常见的通用加密算法之一,称之为对称加密算法中的一哥也丝毫不为过,其重要程度不言而喻。
本文将极尽详细的讲解C#实现AES加密和解密的全过程。
演示
先看一下界面操作的演示:
这里我是用固定的ASE秘钥和向量进行加解密:
AES秘钥(32位):12345678901234567890123456789012
AES向量(16位):1234567890123456
用于测试的明文字符串及得到的加密结果如下:
明文(加密前):早上好
密文(加密后):56BA88D88B33EF9239C15CE521261588
源代码
所有引用
using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Windows.Forms;
AES参数
AES加密需要的6个参数如下所示:
/// <summary>
/// 指定要用于加密的块密码模式
/// </summary>
public CipherMode CipherMode {
get; set; } = CipherMode.CBC;
/// <summary>
/// 指定在消息数据块短于加密操作所需的完整字节数时要应用的填充类型
/// </summary>
public PaddingMode PaddingMode {
get; set; } = PaddingMode.PKCS7;
/// <summary>
/// 获取或设置加密操作的块大小(以位为单位)
/// </summary>
public int BlockSize {
get; set; } = 128;
/// <summary>
/// 获取或设置用于对称算法的密钥大小(以位为单位)
/// </summary>
public int KeySize {
get; set; } = 256;
/// <summary>
/// 用于对称算法的密钥(长度为[KeySize/8]字节)
/// </summary>
public byte[] RgbKey {
get; } = "12345678901234567890123456789012".GetBytes();
/// <summary>
/// 用于对称算法的初始化向量(长度为16字节)
/// </summary>
public byte[] RgbIV {
get; } = "1234567890123456".GetBytes();
生成加密器和解密器
创建AesManaged,将AES加密所需的参数填入,生成加密器和解密器:
// 创建AES配置并生成加密器和解密器
using (var managed = new AesManaged()
{
Mode = CipherMode,
KeySize = KeySize,
Padding = PaddingMode,
BlockSize = BlockSize,
Key = RgbKey,
IV = RgbIV,
})
{
encryptor = managed.CreateEncryptor();
decryptor = managed.CreateDecryptor();
}
加密按钮代码
加密按钮(btnEncrypt)单击事件触发时执行以下代码:
private void btnEncrypt_Click(object sender, EventArgs e)
{
// 读取明文并转为字节数组(默认使用UTF-8编码格式)
var bytes = tbClearText.Text.GetBytes();
// 将待加密字节数组转为内存流
var stream = new MemoryStream(bytes);
// 创建加密流(使用加密器)
var cryptoStream = new CryptoStream(stream, encryptor, CryptoStreamMode.Read);
// 将加密流的内容拷贝到空的内存流中
var encryptedStream = new MemoryStream();
cryptoStream.CopyTo(encryptedStream);
// 将新的内存流内容转为字节数组
var encryptedBytes = encryptedStream.ToArray();
// 以十六进制形式显示
tbEncryptedText.Text = encryptedBytes.ToHexString();
}
解密按钮代码
解密按钮(btnDecrypt)单击事件触发时执行以下代码:
private void btnDecrypt_Click(object sender, EventArgs e)
{
// 读取十六进制密文并转为字节数组
var bytes = tbEncryptedText.Text.HexStringToBytes();
// 将加密字节数组转为内存流
var stream = new MemoryStream(bytes);
// 创建加密流(使用解密器)
var cryptoStream = new CryptoStream(stream, decryptor, CryptoStreamMode.Read);
// 将加密流的内容拷贝到空的内存流中
var clearStream = new MemoryStream();
cryptoStream.CopyTo(clearStream);
// 将新的内存流内容转为字节数组
var encryptedBytes = clearStream.ToArray();
// 将明文字节数组编码为字符串(默认使用UTF-8编码格式)
tbClearText.Text = encryptedBytes.EncodeToString();
}
界面设计
界面设计也非常简单,两个文本框(明文、密文)和两个按钮(加密、解密),布局如下:
源码使用问题
直接使用源码时,以下几处可能会遇到“未找到方法”的提示,这是因为这几个简化开发的方法需要安装扩展包“CodePlus”后才能使用,安装方法:C# 字节数组与16进制字符串互相转换。
当然也可以自己实现这转换过程,都不难。
附录:完整代码
虽然上面已经有了,但是为了方便大家抄作业,还是整个贴上吧。
using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Windows.Forms;
namespace Test.Blog.Aes
{
public partial class AesDemoForm : Form
{
private ICryptoTransform encryptor;
private ICryptoTransform decryptor;
/// <summary>
/// 指定要用于加密的块密码模式
/// </summary>
public CipherMode CipherMode {
get; set; } = CipherMode.CBC;
/// <summary>
/// 指定在消息数据块短于加密操作所需的完整字节数时要应用的填充类型
/// </summary>
public PaddingMode PaddingMode {
get; set; } = PaddingMode.PKCS7;
/// <summary>
/// 获取或设置加密操作的块大小(以位为单位)
/// </summary>
public int BlockSize {
get; set; } = 128;
/// <summary>
/// 获取或设置用于对称算法的密钥大小(以位为单位)
/// </summary>
public int KeySize {
get; set; } = 256;
/// <summary>
/// 用于对称算法的密钥(长度为[KeySize/8]字节)
/// </summary>
public byte[] RgbKey {
get; } = "12345678901234567890123456789012".GetBytes();
/// <summary>
/// 用于对称算法的初始化向量(长度为16字节)
/// </summary>
public byte[] RgbIV {
get; } = "1234567890123456".GetBytes();
public AesDemoForm()
{
InitializeComponent();
// 创建AES配置并生成加密器和解密器
using (var managed = new AesManaged()
{
Mode = CipherMode,
KeySize = KeySize,
Padding = PaddingMode,
BlockSize = BlockSize,
Key = RgbKey,
IV = RgbIV,
})
{
encryptor = managed.CreateEncryptor();
decryptor = managed.CreateDecryptor();
}
}
private void btnEncrypt_Click(object sender, EventArgs e)
{
// 读取明文并转为字节数组(默认使用UTF-8编码格式)
var bytes = tbClearText.Text.GetBytes();
// 将待加密字节数组转为内存流
var stream = new MemoryStream(bytes);
// 创建加密流(使用加密器)
var cryptoStream = new CryptoStream(stream, encryptor, CryptoStreamMode.Read);
// 将加密流的内容拷贝到空的内存流中
var encryptedStream = new MemoryStream();
cryptoStream.CopyTo(encryptedStream);
// 将新的内存流内容转为字节数组
var encryptedBytes = encryptedStream.ToArray();
// 以十六进制形式显示
tbEncryptedText.Text = encryptedBytes.ToHexString();
}
private void btnDecrypt_Click(object sender, EventArgs e)
{
// 读取十六进制密文并转为字节数组
var bytes = tbEncryptedText.Text.HexStringToBytes();
// 将加密字节数组转为内存流
var stream = new MemoryStream(bytes);
// 创建加密流(使用解密器)
var cryptoStream = new CryptoStream(stream, decryptor, CryptoStreamMode.Read);
// 将加密流的内容拷贝到空的内存流中
var clearStream = new MemoryStream();
cryptoStream.CopyTo(clearStream);
// 将新的内存流内容转为字节数组
var encryptedBytes = clearStream.ToArray();
// 将明文字节数组编码为字符串(默认使用UTF-8编码格式)
tbClearText.Text = encryptedBytes.EncodeToString();
}
}
}