/// <summary> /// AES對稱加密和分組加密中的四種模式(ECB、CBC、CFB、OFB),這三種的區別,主要來自於密鑰的長度,16位密鑰=128位,24位密鑰=192位,32位密鑰=256位 /// 檢驗密鑰是否有效長度【16|24|32】 /// </summary> /// <param name="key">密鑰</param> /// <returns>bool</returns> private static bool AesCheckKey(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; } #region 參數是string類型的 /// <summary> /// AES加密 參數:string /// </summary> /// <param name="source">源字符串</param> /// <param name="key">密鑰</param> /// <param name="base64">是否轉64進制</param> /// <param name="model">運算模式</param> /// <param name="padding">填充模式</param> /// <param name="encoding">編碼類型</param> /// <returns>加密後的字符串</returns> public static string AesEncrypt(string source, string key, bool base64 = false, CipherMode model = CipherMode.ECB, PaddingMode padding = PaddingMode.PKCS7, Encoding encoding = null) { if (string.IsNullOrWhiteSpace(source)) return null; if (!AesCheckKey(key)) return source; if (encoding == null) encoding = Encoding.UTF8; using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider()) { aesProvider.Key = encoding.GetBytes(key); aesProvider.Mode = model; aesProvider.Padding = padding; //aesProvider.KeySize = 128; //aesProvider.BlockSize = 128; using (ICryptoTransform cryptoTransform = aesProvider.CreateEncryptor()) { byte[] toEncryptArray = encoding.GetBytes(source); byte[] resultArray = cryptoTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); aesProvider.Clear(); //return Convert.ToBase64String(resultArray, 0, resultArray.Length); return base64 ? Convert.ToBase64String(resultArray) : byteToHexString(resultArray); } } //RijndaelManaged rijndaelCipher = new RijndaelManaged(); //rijndaelCipher.Mode = CipherMode.ECB; //rijndaelCipher.Padding = PaddingMode.PKCS7; //rijndaelCipher.KeySize = 128; //rijndaelCipher.BlockSize = 128; //byte[] pwdBytes = System.Text.Encoding.UTF8.GetBytes(key); //byte[] keyBytes = new byte[16]; //int len = pwdBytes.Length; //if (len > keyBytes.Length) len = keyBytes.Length; //System.Array.Copy(pwdBytes, keyBytes, len); //rijndaelCipher.Key = keyBytes; ////加密初始化向量 //string iv = " "; //byte[] ivBytes = System.Text.Encoding.UTF8.GetBytes(iv); //rijndaelCipher.IV = new byte[16]; //ICryptoTransform transform = rijndaelCipher.CreateEncryptor(); //byte[] plainText = System.Text.Encoding.UTF8.GetBytes(source); //byte[] cipherBytes = transform.TransformFinalBlock(plainText, 0, plainText.Length); //return byteToHexString(cipherBytes);// Convert.ToBase64String(cipherBytes); } /// <summary> /// AES解密 參數:string /// </summary> /// <param name="source">源字符串</param> /// <param name="key">密鑰</param> /// <param name="base64">是否轉64進制</param> /// <param name="model">運算模式</param> /// <param name="padding">填充模式</param> /// <param name="encoding">編碼類型</param> /// <returns>解密後的字符串</returns> public static string AesDecrypt(string source, string key, bool base64 = false, CipherMode model = CipherMode.ECB, PaddingMode padding = PaddingMode.PKCS7, Encoding encoding = null) { if (string.IsNullOrWhiteSpace(source)) return null; if (!AesCheckKey(key)) return source; if (encoding == null) encoding = Encoding.UTF8; using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider()) { aesProvider.Key = encoding.GetBytes(key); aesProvider.Mode = model; aesProvider.Padding = padding; //aesProvider.KeySize = 128; //aesProvider.BlockSize = 128; using (ICryptoTransform cryptoTransform = aesProvider.CreateDecryptor()) { byte[] toEncryptArray = base64 == true ? Convert.FromBase64String(source) : stringToHexByte(source); byte[] resultArray = cryptoTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); aesProvider.Clear(); return encoding.GetString(resultArray); } } } #endregion /// <summary> /// 字節數組轉16進制字符串 /// </summary> /// <param name="bytes"></param> /// <returns></returns> public static string byteToHexString(byte[] bytes) { string returnStr = ""; if (bytes != null) { for (int i = 0; i < bytes.Length; i++) { returnStr += bytes[i].ToString("X2"); } } return returnStr; } /// <summary> /// 將16進制字符串轉換爲字節數組 /// </summary> /// <param name="hexString"></param> /// <returns></returns> private static byte[] stringToHexByte(string hexString) { hexString = hexString.Replace(" ", ""); if ((hexString.Length % 2) != 0) hexString += " "; byte[] returnBytes = new byte[hexString.Length / 2]; for (int i = 0; i < returnBytes.Length; i++) returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16); return returnBytes; } #region 參數是byte[]類型的 /// <summary> /// AES加密 參數:byte[] /// </summary> /// <param name="source">源字符字節組</param> /// <param name="key">密鑰</param> /// <param name="model">運算模式</param> /// <param name="padding">填充模式</param> /// <param name="encoding">編碼類型</param> /// <returns>加密後的字符字節組</returns> public static byte[] AesEncrypt(byte[] source, string key, CipherMode model = CipherMode.ECB, PaddingMode padding = PaddingMode.PKCS7, Encoding encoding = null) { if (source == null) return null; if (!AesCheckKey(key)) return source; if (encoding == null) encoding = Encoding.UTF8; byte[] bKey = encoding.GetBytes(key); byte[] cryptograph = null; //加密後的密文 Rijndael Aes = Rijndael.Create(); Aes.Key = bKey; //開闢一塊內存流 using (MemoryStream Memory = new MemoryStream()) { //把內存流對象包裝成加密流對象 using (CryptoStream Encryptor = new CryptoStream(Memory, Aes.CreateEncryptor(), CryptoStreamMode.Write)) { //明文數據寫入加密流 Encryptor.Write(source, 0, source.Length); Encryptor.FlushFinalBlock(); cryptograph = Memory.ToArray(); } } return cryptograph; } /// <summary> /// AES解密 參數:byte[] /// </summary> /// <param name="source">源字符字節組</param> /// <param name="key">密鑰</param> /// <param name="model">運算模式</param> /// <param name="padding">填充模式</param> /// <param name="encoding">編碼類型</param> /// <returns>解密後的字符字節組</returns> public static byte[] AesDecrypt(byte[] source, string key, CipherMode model = CipherMode.ECB, PaddingMode padding = PaddingMode.PKCS7, Encoding encoding = null) { if (source == null) return null; if (!AesCheckKey(key)) return source; if (encoding == null) encoding = Encoding.UTF8; byte[] bKey = encoding.GetBytes(key); byte[] original = null; //解密後的明文 Rijndael Aes = Rijndael.Create(); //開闢一塊內存流,存儲密文 using (MemoryStream Memory = new MemoryStream(source)) { //把內存流對象包裝成加密流對象 using (CryptoStream Decryptor = new CryptoStream(Memory, Aes.CreateDecryptor(bKey, null), 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 /// <summary> /// 對字符串SHA1加密 /// </summary> /// <param name="source">源字符串</param> /// <param name="encoding">編碼類型</param> /// <returns>加密後的十六進制字符串</returns> public static string Sha1Encrypt(string source, Encoding encoding = null) { if (encoding == null) encoding = Encoding.UTF8; // 第一種方式 byte[] byteArray = encoding.GetBytes(source); using (HashAlgorithm hashAlgorithm = new SHA1CryptoServiceProvider()) { byteArray = hashAlgorithm.ComputeHash(byteArray); StringBuilder stringBuilder = new StringBuilder(256); foreach (byte item in byteArray) { stringBuilder.AppendFormat("{0:x2}", item); } hashAlgorithm.Clear(); return stringBuilder.ToString(); } //// 第二種方式 //using (SHA1 sha1 = SHA1.Create()) //{ // byte[] hash = sha1.ComputeHash(encoding.GetBytes(source)); // StringBuilder stringBuilder = new StringBuilder(); // for (int index = 0; index < hash.Length; ++index) // stringBuilder.Append(hash[index].ToString("x2")); // sha1.Clear(); // return stringBuilder.ToString(); //} } /// <summary> /// 對字符串MD5加密 /// </summary> /// <param name="source">源字符串</param> /// <param name="encoding">編碼類型</param> /// <returns>加密後的十六進制字符串</returns> public static string Md5Encrypt(string source, Encoding encoding = null) { if (encoding == null) encoding = Encoding.UTF8; byte[] byteArray = encoding.GetBytes(source); using (HashAlgorithm hashAlgorithm = new MD5CryptoServiceProvider()) { byteArray = hashAlgorithm.ComputeHash(byteArray); StringBuilder stringBuilder = new StringBuilder(); foreach (byte item in byteArray) { stringBuilder.AppendFormat("{0:x2}", item); } hashAlgorithm.Clear(); return stringBuilder.ToString(); } }
AES加密方式中關於PKCS5Padding與PKCS7Padding的區別html
在PKCS5Padding中,明肯定義Block的大小是8位,而在PKCS7Padding定義中,對於塊的大小是不肯定的,能夠在1-255之間(塊長度超出255的尚待研究),填充值的算法都是同樣的:java
value=k - (l mod k) ,K=塊大小,l=數據長度,若是l=8, 則須要填充額外的8個byte的8算法
在.net中,例如TripleDESCryptoServiceProvider ,默認BlockSize=64bits=8bytes,因此在這種狀況下在PKCS5Padding=PKCS7Padding。數組
若是在C#中本身定義了一個不是64bits的加密塊大小,同時使用PKCS7Padding,那麼在java中使用JDK標準的PKCS5Padding就不能解密了。ide