高級加密標準(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密鑰來通信。
最常見的用法是接口請求時,數據傳輸過程中考慮到數據的安全性,需要對數據進行加密傳輸,當服務器接收到請求時對數據進行解密。
C# 加密、解密的代碼如下:
private static byte[] _key1 = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
// 密鑰
public static string _key = "key";
/// <summary>
/// AES加密算法
/// </summary>
/// <param name="plainText">明文字符串</param>
/// <returns>將加密後的密文轉換爲Base64編碼,以便顯示</returns>
public static string AESEncrypt(string plainText)
{
//分組加密算法
SymmetricAlgorithm des = Rijndael.Create();
byte[] inputByteArray = Encoding.UTF8.GetBytes(plainText);//得到需要加密的字節數組
//設置密鑰及密鑰向量
des.Key = Encoding.UTF8.GetBytes(_key);
des.IV = _key1;
byte[] cipherBytes = null;
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(inputByteArray, 0, inputByteArray.Length);
cs.FlushFinalBlock();
cipherBytes = ms.ToArray();//得到加密後的字節數組
cs.Close();
ms.Close();
}
}
return Convert.ToBase64String(cipherBytes);
}
AES解密:
解密其實就是加密的逆過程
/// <summary>
/// AES解密
/// </summary>
/// <param name="cipherText">密文字符串</param>
/// <returns>返回解密後的明文字符串</returns>
public static string AESDecrypt(string showText)
{
byte[] cipherText = Convert.FromBase64String(showText);
SymmetricAlgorithm des = Rijndael.Create();
des.Key = Encoding.UTF8.GetBytes(_key);
des.IV = _key1;
byte[] decryptBytes = new byte[cipherText.Length];
using (MemoryStream ms = new MemoryStream(cipherText))
{
using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Read))
{
cs.Read(decryptBytes, 0, decryptBytes.Length);
cs.Close();
ms.Close();
}
}
return Encoding.UTF8.GetString(decryptBytes).Replace("\0", ""); ///將字符串後尾的'\0'去掉
}