目录
一、介绍
1.1 什么是AES
AES,全称为Advanced Encryption Standard,也称为高级加密标准,或者Rijndael加密法(该算法为比利时密码学家Joan Daemen和Vincent Rijmen所设计,结合两位作者的名字)。
AES是一种对称加密算法,是美国联邦政府采用的一种区块加密标准,由美国国家标准与技术研究院(NIST)于2001年发布。
AES作为之前的DES加密算法的替代方案,是目前最流行的对称加密方案,目前仍被广泛地应用在各种开发活动中。
对称加密
加密和解密使用相同的密钥,对称性加密解密性能好效率高,适合经常发送数据的场景。缺点是密钥的传输和管理比较麻烦。
非对称加密
加密和解密用的密钥是不同的,这种加密方式是用数学上的难解问题构造的,通常加密解密的速度比较慢,适合偶尔发送数据的场合。优点是密钥传输方便。常见的非对称加密算法为RSA、ECC和EIGamal。
1.2AES的的原理
本段内容引用自AES加密算法原理的详细介绍与实现,可以去那边看更详细的介绍
AES的加密流程如图所示
介绍下各个部分的作用与意义:
明文P
没有经过加密的数据。
密钥K
用来加密明文的密码,在对称加密算法中,加密与解密的密钥是相同的。密钥为接收方与发送方协商产生,但不可以直接在网络上传输,否则会导致密钥泄漏,通常是通过非对称加密算法加密密钥,然后再通过网络传输给对方,或者直接面对面商量密钥。密钥是绝对不可以泄漏的,否则会被攻击者还原密文,窃取机密数据。
AES加密函数
设AES加密函数为E,则 C = E(K, P),其中P为明文,K为密钥,C为密文。也就是说,把明文P和密钥K作为加密函数的参数输入,则加密函数E会输出密文C。
密文C
经加密函数处理后的数据
AES解密函数
设AES解密函数为D,则 P = D(K, C),其中C为密文,K为密钥,P为明文。也就是说,把密文C和密钥K作为解密函数的参数输入,则解密函数会输出明文P。
实际中,一般是通过RSA加密AES的密钥,传输到接收方,接收方解密得到AES密钥,然后发送方和接收方用AES密钥来通信。
1.3 AES的优缺点
1.3.1 优点
安全性高:
AES算法采用了复杂的数学运算和混淆技术,使得攻击者很难从密文中推断出明文内容,即使获取了加密密钥也难以破解。经过多方分析和测试,AES算法被认为是目前最安全的对称加密算法之一。
效率高
AES算法采用了并行处理和优化的加密方式,使得加密和解密的速度都非常快,适用于大规模的数据加密需求。
兼容性良好
AES算法在硬件和软件上都有广泛的支持,易于集成和使用。
灵活性高
AES算法支持不同的密钥长度,分别为128位、192位和256位,可以根据实际需求选择合适的密钥长度,以满足不同级别的安全需求。
1.3.2 缺点
密钥长度较短
AES的密钥长度为56位,这在现代加密标准中可能被视为较短,因此其安全性相对较低,可能受到穷举攻击。
密钥管理复杂
由于AES算法支持多种密钥长度,过多的密钥在管理和保密上可能成为一个问题。
1.4 AES的应用场景
AES仍然被广泛应用在各种开发场景中,以下列出一些常见的应用场景
1.4.1 金融行业
AES加密算法常用于保护银行卡交易、ATM机交易、电子支付等金融交易领域中的数据传输,以确保交易过程的安全性。也用于保护用户账户的信息安全。
1.4.2 电子商务
AES加密算法可用于保护在线交易的数据传输,包括信用卡信息、客户信息等敏感数据的加密和解密。
1.4.3 政府通信
AES加密算法可用于保护政府机构之间的通信,包括机密文件传输、电子邮件通信等。
1.4.4 医疗信息加密
医疗档案关乎病人的生命安全,可以使用AES技术保护医院医疗档案的安全性。
1.4.5 数据库加密
AES加密算法可用于数据库中敏感数据的加密和解密,以保护数据隐私和机密性。
1.4.6 VPN加密
AES加密算法可用于虚拟专用网络(VPN)连接的加密和解密,以确保数据的安全传输。
1.4.7 网络安全
AES加密算法可用于保护数据传输和通信过程中的安全,包括防止黑客攻击、网络入侵等网络安全问题。
1.4.8 移动设备安全
AES加密算法可用于保护移动设备的数据存储和传输,包括智能手机、平板电脑等设备。
1.4.9 资源文件加密
对应用或游戏的资源素材文件进行加密,防止使用逆向技术解析出应用或游戏中的素材文件。
二、AES算法实现
2.1 AES的参数
Key Length(密钥长度/位数)
不论密钥长度为多少,AES的明文分组始终为16字节(4字,128位),密钥长度可以为128位(16字节)、192位(24字节)、256位(32字节),根据密钥长度的不同,AES分为AES-128、AES-192、AES-256三种。
Key(密钥)
Key指的是密钥,如果密钥位数不够,某些库可能会自动填充。如AES-128位数不够就会自动填充到128位。
Mode(加密模式)
AES的模式包含ECB, CBC, CFB, OFB, CTR。AES常用的GCM模式,其实是带GMAC(伽罗瓦消息验证码)的CTR模式。
IV(向量)
IV称为初始向量,不同的IV加密后的字符串是不同的,加密和解密需要相同的IV。AES加密算法的各种模式中,只有ECB模式不需要IV,同时其安全性也是最低的。在使用同一种加密同一个密钥时不应该使用相同的IV,否则会失去一定甚至全部的安全性。
针对不同的模式,IV代表的意义也不一样:
ECB模式没有IV;
CBC模式中IV是用于与第一个明文分组抑或,然后对抑或结果加密,相当于第一个预设的密文块,长度同分组块长度;
CFB模式中IV是第一个用于加密的内容,然后与明文块抑或,相当于第一个预设的密文块,长度同分组块长度;
OFB模式中IV是第一个用于加密的内容,长度同分组块长度;
CTR模式中IV可以理解为计数器的初始值。
Padding(填充方式)
CFB,OFB和CTR模式不需要任何特殊措施来处理长度不是块大小倍数的消息,因为这些模式通过将明文与块密码的输出进行异或工作。ECB和CBC要求在加密之前填补最终的块。常用的PADDING模式为PKCS5, PKCS7, NOPADDING,ZerosPadding,ISO 10126,ANSI X9.23,ISO / IEC 7816-4。
2.2 AES的实现
以下提供C#中的一个AES加密的实现,可以通过自定义的key和iv对string和byte[]数据进行加密,大家也可以自己尝试一下
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
/// <summary>
/// Aes加密
/// </summary>
public class AesEncryptUtils
{
//字符串转字节数组
private static byte[] StringToBytes(string str, int length)
{
byte[] bytes = Encoding.UTF8.GetBytes(str);
Array.Resize(ref bytes, length);
return bytes;
}
//字节数组转字符串
private static string BytesToString(byte[] bytes)
{
string str = Encoding.UTF8.GetString(bytes);
return str;
}
//加密-String转String
public static string Encrypt(string str,string key,string iv)
{
return Convert.ToBase64String(Encrypt(StringToBytes(str, str.Length+4), key, iv));//注意长度+4
}
//加密-Bytes转Bytes
public static byte[] Encrypt(byte[] bytes,string key,string iv)
{
using (Aes aes = Aes.Create())
{
aes.Key = StringToBytes(key,32);
aes.IV = StringToBytes(iv,16);
ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
byte[] encryptedBytes;
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
csEncrypt.Write(bytes, 0, bytes.Length);
}
encryptedBytes = msEncrypt.ToArray();
}
return encryptedBytes;
}
}
//解密-String转String
public static string Decrypt(string str,string key,string iv)
{
return BytesToString(Decrypt(Convert.FromBase64String(str), key, iv));
}
//解密-Bytes转Bytes
public static byte[] Decrypt(byte[] bytes,string key,string iv)
{
using (Aes aes = Aes.Create())
{
aes.Key = StringToBytes(key,32);
aes.IV = StringToBytes(iv,16);
ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
using (MemoryStream msDecrypt = new MemoryStream(bytes))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (MemoryStream msOutput = new MemoryStream())
{
csDecrypt.CopyTo(msOutput);
return msOutput.ToArray();
}
}
}
}
}
}