用AES加密/解密字串
阿新 • • 發佈:2018-12-09
高階加密標準(AES,Advanced Encryption Standard)為最常見的對稱加密演算法(微信小程式加密傳輸就是用這個加密演算法的)。對稱加密演算法也就是加密和解密用相同的金鑰,具體的加密流程如下圖:
下面簡單介紹下各個部分的作用與意義:
-
明文P
沒有經過加密的資料。
-
金鑰K
用來加密明文的密碼,在對稱加密演算法中,加密與解密的金鑰是相同的。金鑰為接收方與傳送方協商產生,但不可以直接在網路上傳輸,否則會導致金鑰洩漏,通常是通過非對稱加密演算法加密金鑰,然後再通過網路傳輸給對方,或者直接面對面商量金鑰。金鑰是絕對不可以洩漏的,否則會被攻擊者還原密文,竊取機密資料。
-
AES加密函式
設AES加密函式為E,則 C = E(K, P),其中P為明文,K為金鑰,C為密文。也就是說,把明文P和金鑰K作為加密函式的引數輸入,則加密函式E會輸出密文C。
-
密文C
經加密函式處理後的資料
-
AES解密函式
設AES解密函式為D,則 P = D(K, C),其中C為密文,K為金鑰,P為明文。也就是說,把密文C和金鑰K作為解密函式的引數輸入,則解密函式會輸出明文P。
在這裡簡單介紹下對稱加密演算法與非對稱加密演算法的區別。
-
對稱加密演算法
加密和解密用到的金鑰是相同的,這種加密方式加密速度非常快,適合經常傳送資料的場合。缺點是金鑰的傳輸比較麻煩。
-
非對稱加密演算法
加密和解密用的金鑰是不同的,這種加密方式是用數學上的難解問題構造的,通常加密解密的速度比較慢,適合偶爾傳送資料的場合。優點是金鑰傳輸方便。常見的非對稱加密演算法為RSA、ECC和EIGamal。
實際中,一般是通過RSA加密AES的金鑰,傳輸到接收方,接收方解密得到AES金鑰,然後傳送方和接收方用AES金鑰來通訊。
加密
/// <summary> /// 使用AES加密字串 /// </summary> /// <param name="encryptString">待加密字串</param> /// <param name="encryptKey">加密密匙</param> /// <param name="salt">鹽</param> /// <returns>加密結果,加密失敗則返回源串</returns> public static string EncryptAES(string encryptString, string encryptKey, string salt) { AesManaged aes = null; MemoryStream ms = null; CryptoStream cs = null; try { Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(encryptKey, Encoding.UTF8.GetBytes(salt)); aes = new AesManaged(); aes.Key = rfc2898.GetBytes(aes.KeySize / 8); aes.IV = rfc2898.GetBytes(aes.BlockSize / 8); ms = new MemoryStream(); cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write); byte[] data = Encoding.UTF8.GetBytes(encryptString); cs.Write(data, 0, data.Length); cs.FlushFinalBlock(); return Convert.ToBase64String(ms.ToArray()); } catch { return encryptString; } finally { if (cs != null) cs.Close(); if (ms != null) ms.Close(); if (aes != null) aes.Clear(); } }
解密
/// <summary>
/// 使用AES解密字串
/// </summary>
/// <param name="decryptString">待解密字串</param>
/// <param name="decryptKey">解密密匙</param>
/// <param name="salt">鹽</param>
/// <returns>解密結果,解謎失敗則返回源串</returns>
public static string DecryptAES(string decryptString, string decryptKey, string salt)
{
AesManaged aes = null;
MemoryStream ms = null;
CryptoStream cs = null;
try
{
Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(decryptKey, Encoding.UTF8.GetBytes(salt));
aes = new AesManaged();
aes.Key = rfc2898.GetBytes(aes.KeySize / 8);
aes.IV = rfc2898.GetBytes(aes.BlockSize / 8);
ms = new MemoryStream();
cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write);
byte[] data = Convert.FromBase64String(decryptString);
cs.Write(data, 0, data.Length);
cs.FlushFinalBlock();
return Encoding.UTF8.GetString(ms.ToArray(), 0, ms.ToArray().Length);
}
catch
{
return decryptString;
}
finally
{
if (cs != null)
cs.Close();
if (ms != null)
ms.Close();
if (aes != null)
aes.Clear();
}
}