转载注明出处 https://www.jianshu.com/p/6db0395c729c
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个步骤
AddRoundKey—矩阵中的每一个字节都与该次回合密钥round key做XOR运算每个子密钥由密钥生成方案产生。
SubBytes—通过一个非线性的替换函数用查找表的方式把每个字节替换成对应的字节。
ShiftRows—将矩阵中的每个横列进行循环式移位。
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加密
/// /// AES加密/// /// 被加密的明文/// 密钥/// 向量/// 密文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解密
/// /// AES解密/// /// 被解密的密文/// 密钥/// 向量/// 明文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);}
使用默认向量加解密
/// /// AES加密(无向量)/// /// 被加密的明文/// 密钥/// 密文public static string AESEncrypt(String Data, String Key){return AESEncrypt(Data, Key, _aesKeyStr);}/// /// AES解密(无向量)/// /// 被加密的明文/// 密钥/// 明文public static string AESDecrypt(String Data, String Key){return AESDecrypt(Data, Key, _aesKeyStr);}