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#代码实现

定义默认密钥向量

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

随机生成密钥

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加密

/// <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);

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

AES解密

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

使用默认向量加解密

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