資料加密是資訊安全的基石。本文系統整理雜湊演算法(MD5、SHA1)、對稱加密(DES、AES)、非對稱加密(RSA)的原理、優缺點與 C# 實作,並針對已知弱點給出建議。
摘要演算法(雜湊/散列)將任意長度資料映射為固定長度指紋,具單向不可逆、雪崩效應特性。常用於密碼儲存、完整性校驗、數位簽名。注意:MD5 已被破解,建議改用 SHA256 或更強演算法。
輸出 128 位(16 位元組),常以 32 字元十六進位字串呈現。
public static string EncryptByMD5(string input) {
using (MD5 md5 = MD5.Create()) {
byte[] data = md5.ComputeHash(Encoding.UTF8.GetBytes(input));
StringBuilder sb = new StringBuilder();
foreach (byte b in data) sb.Append(b.ToString("x2"));
return sb.ToString();
}
}
輸出 160 位(20 位元組),比 MD5 強但亦已不建議用於高安全性場合。
public static string EncryptBySHA1(string input) {
using (SHA1 sha = SHA1.Create()) {
byte[] bytes = Encoding.Unicode.GetBytes(input);
byte[] result = sha.ComputeHash(bytes);
return BitConverter.ToString(result).Replace("-", "");
}
}
加密解密使用同一把金鑰。優點:速度快、效率高,適合大量資料。缺點:金鑰管理困難、缺乏簽名功能。DES 已被破解,建議使用 3DES 或 AES。
56 位金鑰,64 位分組,16 輪迭代。現今極易暴力破解,僅供非機密場合參考。
public static string EncryptString(string input, string sKey) {
byte[] data = Encoding.UTF8.GetBytes(input);
using (DESCryptoServiceProvider des = new DESCryptoServiceProvider()) {
des.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
des.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
ICryptoTransform encryptor = des.CreateEncryptor();
byte[] result = encryptor.TransformFinalBlock(data, 0, data.Length);
return BitConverter.ToString(result);
}
}
public static string DecryptString(string input, string sKey) {
string[] sInput = input.Split('-');
byte[] data = new byte[sInput.Length];
for (int i = 0; i < sInput.Length; i++) data[i] = byte.Parse(sInput[i], NumberStyles.HexNumber);
using (DESCryptoServiceProvider des = new DESCryptoServiceProvider()) {
des.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
des.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
ICryptoTransform decryptor = des.CreateDecryptor();
byte[] result = decryptor.TransformFinalBlock(data, 0, data.Length);
return Encoding.UTF8.GetString(result);
}
}
美國聯邦政府採用標準,支援 128/192/256 位金鑰,取代 DES 成為主流對稱加密。
// 需定義 static readonly byte[] AES_IV = ... (16 位元組)
public static string EncryptByAES(string input, string key) {
byte[] keyBytes = Encoding.UTF8.GetBytes(key.Substring(0, 32)); // 256 位
using (AesCryptoServiceProvider aes = new AesCryptoServiceProvider()) {
aes.Key = keyBytes; aes.IV = AES_IV;
using (MemoryStream ms = new MemoryStream())
using (CryptoStream cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
using (StreamWriter sw = new StreamWriter(cs)) {
sw.Write(input);
}
return BitConverter.ToString(ms.ToArray());
}
}
public static string DecryptByAES(string input, string key) {
string[] sInput = input.Split('-');
byte[] inputBytes = new byte[sInput.Length];
for (int i = 0; i < sInput.Length; i++) inputBytes[i] = byte.Parse(sInput[i], NumberStyles.HexNumber);
byte[] keyBytes = Encoding.UTF8.GetBytes(key.Substring(0, 32));
using (AesCryptoServiceProvider aes = new AesCryptoServiceProvider()) {
aes.Key = keyBytes; aes.IV = AES_IV;
using (MemoryStream ms = new MemoryStream(inputBytes))
using (CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Read))
using (StreamReader sr = new StreamReader(cs)) {
return sr.ReadToEnd();
}
}
}

使用公鑰/私鑰對。公鑰加密、私鑰解密(機密性);私鑰加密、公鑰解密(簽名/身分驗證)。優點:無需預先交換金鑰、金鑰管理容易、支援防抵賴。缺點:運算速度慢,不適合大量資料。
RSA、ElGamal、ECC(橢圓曲線)等。RSA 最常見,基於大數質因數分解困難性。
public static string EncryptByRSA(string plaintext, string publicKey) {
UnicodeEncoding converter = new UnicodeEncoding();
byte[] data = converter.GetBytes(plaintext);
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider()) {
rsa.FromXmlString(publicKey);
byte[] encrypted = rsa.Encrypt(data, false);
return Convert.ToBase64String(encrypted);
}
}
public static string DecryptByRSA(string ciphertext, string privateKey) {
UnicodeEncoding converter = new UnicodeEncoding();
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider()) {
rsa.FromXmlString(privateKey);
byte[] data = Convert.FromBase64String(ciphertext);
byte[] decrypted = rsa.Decrypt(data, false);
return converter.GetString(decrypted);
}
}

完整原始碼下載:EncriptSample.zip