C#之AES加密解密
阿新 • • 發佈:2019-01-10
高階加密標準(AES,Advanced Encryption Standard)為最常見的對稱加密演算法(微信小程式加密傳輸就是用這個加密演算法的)。對稱加密演算法也就是加密和解密用相同的金鑰,具體的加密流程如下圖:(原理:轉自https://blog.csdn.net/qq_28205153/article/details/55798628)
程式碼例項如下:
using System; using System.Text; using System.Security.Cryptography; using System.IO; namespace Common.Helper.Crypto { /// <summary> /// AES加密解密 /// </summary> public static class AesCrypto { //對稱加密和分組加密中的四種模式(ECB、CBC、CFB、OFB),這三種的區別,主要來自於金鑰的長度,16位金鑰=128位,24位金鑰=192位,32位金鑰=256位。 //更多參考:http://www.cnblogs.com/happyhippy/archive/2006/12/23/601353.html /// <summary> /// 檢驗金鑰是否有效長度【16|24|32】 /// </summary> /// <param name="key">金鑰</param> /// <returns>bool</returns> private static bool CheckKey(string key) { if (string.IsNullOrWhiteSpace(key)) return false; if (16.Equals(key.Length) || 24.Equals(key.Length) || 32.Equals(key.Length)) return true; else return false; } /// <summary> /// 檢驗向量是否有效長度【16】 /// </summary> /// <param name="iv">向量</param> /// <returns>bool</returns> private static bool CheckIv(string iv) { if (string.IsNullOrWhiteSpace(iv)) return false; if (16.Equals(iv.Length)) return true; else return false; } #region 引數是string型別的 /// <summary> /// 加密 引數:string /// </summary> /// <param name="palinData">明文</param> /// <param name="key">金鑰</param> /// <param name="iv">向量</param> /// <param name="encodingType">編碼方式</param> /// <returns>string:密文</returns> public static string Encrypt(string palinData, string key, string iv, EncodingStrOrByte.EncodingType encodingType = EncodingStrOrByte.EncodingType.UTF8) { if (string.IsNullOrWhiteSpace(palinData)) return null; if (!(CheckKey(key) && CheckIv(iv))) return palinData; byte[] toEncryptArray = EncodingStrOrByte.GetBytes(palinData, encodingType); var rm = new RijndaelManaged { IV = EncodingStrOrByte.GetBytes(iv, encodingType), Key = EncodingStrOrByte.GetBytes(key, encodingType), Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7 }; ICryptoTransform cTransform = rm.CreateEncryptor(); byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); return Convert.ToBase64String(resultArray, 0, resultArray.Length); } /// <summary> /// 解密 引數:string /// </summary> /// <param name="encryptedData">密文</param> /// <param name="key">金鑰</param> /// <param name="iv">向量</param> /// <param name="encodingType">編碼方式</param> /// <returns>string:明文</returns> public static string Decrypt(string encryptedData, string key, string iv, EncodingStrOrByte.EncodingType encodingType = EncodingStrOrByte.EncodingType.UTF8) { if (string.IsNullOrWhiteSpace(encryptedData)) return null; if (!(CheckKey(key) && CheckIv(iv))) return encryptedData; byte[] toEncryptArray = Convert.FromBase64String(encryptedData); var rm = new RijndaelManaged { IV = EncodingStrOrByte.GetBytes(iv, encodingType), Key = EncodingStrOrByte.GetBytes(key, encodingType), Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7 }; ICryptoTransform cTransform = rm.CreateDecryptor(); byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); return Encoding.UTF8.GetString(resultArray); } #endregion #region 引數是byte[]型別的 /// <summary> /// 加密 引數:byte[] /// </summary> /// <param name="palinData">明文</param> /// <param name="key">金鑰</param> /// <param name="iv">向量</param> /// <returns>密文</returns> public static byte[] Encrypt(byte[] palinData, string key, string iv, EncodingStrOrByte.EncodingType encodingType = EncodingStrOrByte.EncodingType.UTF8) { if (palinData == null) return null; if (!(CheckKey(key) && CheckIv(iv))) return palinData; byte[] bKey = new byte[32]; Array.Copy(EncodingStrOrByte.GetBytes(key.PadRight(bKey.Length), encodingType), bKey, bKey.Length); byte[] bVector = new byte[16]; Array.Copy(EncodingStrOrByte.GetBytes(iv.PadRight(bVector.Length), encodingType), bVector, bVector.Length); byte[] cryptograph = null; // 加密後的密文 Rijndael Aes = Rijndael.Create(); // 開闢一塊記憶體流 using (MemoryStream Memory = new MemoryStream()) { // 把記憶體流物件包裝成加密流物件 using (CryptoStream Encryptor = new CryptoStream(Memory, Aes.CreateEncryptor(bKey, bVector), CryptoStreamMode.Write)) { // 明文資料寫入加密流 Encryptor.Write(palinData, 0, palinData.Length); Encryptor.FlushFinalBlock(); cryptograph = Memory.ToArray(); } } return cryptograph; } /// <summary> /// 解密 引數:byte[] /// </summary> /// <param name="encryptedData">被解密的密文</param> /// <param name="key">金鑰</param> /// <param name="iv">向量</param> /// <returns>明文</returns> public static byte[] Decrypt(byte[] encryptedData, string key, string iv, EncodingStrOrByte.EncodingType encodingType = EncodingStrOrByte.EncodingType.UTF8) { if (encryptedData == null) return null; if (!(CheckKey(key) && CheckIv(iv))) return encryptedData; byte[] bKey = new byte[32]; Array.Copy(EncodingStrOrByte.GetBytes(key.PadRight(bKey.Length), encodingType), bKey, bKey.Length); byte[] bVector = new byte[16]; Array.Copy(EncodingStrOrByte.GetBytes(iv.PadRight(bVector.Length), encodingType), bVector, bVector.Length); byte[] original = null; // 解密後的明文 Rijndael Aes = Rijndael.Create(); // 開闢一塊記憶體流,儲存密文 using (MemoryStream Memory = new MemoryStream(encryptedData)) { // 把記憶體流物件包裝成加密流物件 using (CryptoStream Decryptor = new CryptoStream(Memory,Aes.CreateDecryptor(bKey, bVector),CryptoStreamMode.Read)) { // 明文儲存區 using (MemoryStream originalMemory = new MemoryStream()) { byte[] Buffer = new byte[1024]; int readBytes = 0; while ((readBytes = Decryptor.Read(Buffer, 0, Buffer.Length)) > 0) { originalMemory.Write(Buffer, 0, readBytes); } original = originalMemory.ToArray(); } } } return original; } #endregion } }