画星星高手

It nerver rains but it pours.

C#中AES加密的实现

AES算法简介

高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院(NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准。2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一。

该算法为比利时密码学家Joan Daemen和Vincent Rijmen所设计,结合两位作者的名字,以Rijndael为名投稿高级加密标准的甄选流程。(Rijndael的发音近于”Rhine doll”)

AES加密过程

AES加密过程是在一个4×4的字节矩阵上运作,这个矩阵又称为“体(state)”,其初值就是一个明文区块(矩阵中一个元素大小就是明文区块中的一个Byte)。(Rijndael加密法因支持更大的区块,其矩阵行数可视情况增加)加密时,各轮AES加密循环(除最后一轮外)均包含4个步骤:

  1. AddRoundKey—矩阵中的每一个字节都与该次回合密钥(round key)做XOR运算;每个子密钥由密钥生成方案产生。
  2. SubBytes—通过一个非线性的替换函数,用查找表的方式把每个字节替换成对应的字节。
  3. ShiftRows—将矩阵中的每个横列进行循环式移位。
  4. MixColumns—为了充分混合矩阵中各个直行的操作。这个步骤使用线性转换来混合每内联的四个字节。最后一个加密循环中省略MixColumns步骤,而以另一个AddRoundKey取代。

C#代码实现

定义默认密钥向量
“`c#
private static byte[] _aesKetByte = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
private static string _aesKeyStr = Encoding.UTF8.GetString(_aesKetByte);

<pre class="line-numbers prism-highlight" data-start="1"><code class="language-null"><br />随机生成密钥
“`C#
public static byte[] GetIv(int n)
{
char[] arrChar = new char[]{
‘a’,’b’,’d’,’c’,’e’,’f’,’g’,’h’,’i’,’j’,’k’,’l’,’m’,’n’,’p’,’r’,’q’,’s’,’t’,’u’,’v’,’w’,’z’,’y’,’x’,
‘0’,’1′,’2′,’3′,’4′,’5′,’6′,’7′,’8′,’9′,
‘A’,’B’,’C’,’D’,’E’,’F’,’G’,’H’,’I’,’J’,’K’,’L’,’M’,’N’,’Q’,’P’,’R’,’T’,’S’,’V’,’U’,’W’,’X’,’Y’,’Z’
};

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());
}

_aesKetByte = Encoding.UTF8.GetBytes(num.ToString());
return _aesKetByte;
}

AES加密
“`c#
/// <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);

<pre class="prism-highlight line-numbers" data-start="1"><code class="language-null">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);
</code></pre>

}

<pre class="line-numbers prism-highlight" data-start="1"><code class="language-null"><br />**AES解密**
“`c#
/// <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];
Int32 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);
}

使用默认向量加解密
“`c#
/// <summary>
/// AES加密(无向量)
/// </summary>
/// <param name="Data">被加密的明文</param>
/// <param name="Key">密钥</param>
/// <returns>密文</returns>
public static string AESEncrypt(String Data, String Key)
{
return AESEncrypt(Data, Key, _aesKeyStr);

}
/// <summary>
/// AES解密(无向量)
/// </summary>
/// <param name="Data">被加密的明文</param>
/// <param name="Key">密钥</param>
/// <returns>明文</returns>
public static string AESDecrypt(String Data, String Key)
{
return AESDecrypt(Data, Key, _aesKeyStr);
}
“`


了解更多有趣的操作请关注我的微信公众号:DealiAxy

《C#中AES加密的实现》

每一篇文章都在我的博客有收录:blog.deali.cn

点赞

发表评论