1. 程式人生 > >C#之AES加密解密

C#之AES加密解密

高階加密標準(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
    }
}