刚接触加密那会儿,我被那些术语绕得头晕——AES、DES、RSA、散列、盐值...听起来就像天书。但真正用起来才发现,日常开发中掌握那么三四个套路就够用了。
先搞懂三个核心概念
1. 对称加密(AES)—— 像保险箱
- 同一把钥匙加密和解密
- 速度快,适合大数据量
- 关键问题:钥匙怎么安全地交给对方?
2. 非对称加密(RSA)—— 像信箱
- 公钥加密,私钥解密
- 速度慢,适合小数据量
- 完美解决钥匙传递问题
3. 哈希(MD5、SHA)—— 像指纹
- 单向的,无法还原
- 主要用于校验数据完整性
- 注意:MD5现在已不安全,别用在密码加密上
实战场景1:用户密码加密
这是我踩过的第一个坑。早期项目我直接MD5加密密码,直到有天发现彩虹表一撞一个准...
现在正确的做法:
// 使用PBKDF2或BCrypt,它们会加盐且计算很慢,防止暴力破解
public string HashPassword(string password)
{// 生成随机的盐值(16字节)byte[] salt = new byte[16];using (var rng = RandomNumberGenerator.Create()){rng.GetBytes(salt);}// 使用PBKDF2进行哈希(迭代10000次)var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 10000, HashAlgorithmName.SHA256);byte[] hash = pbkdf2.GetBytes(20); // 20字节哈希值// 组合盐值和哈希值存储byte[] hashBytes = new byte[36];Array.Copy(salt, 0, hashBytes, 0, 16);Array.Copy(hash, 0, hashBytes, 16, 20);return Convert.ToBase64String(hashBytes);
}// 验证密码
public bool VerifyPassword(string password, string hashedPassword)
{byte[] hashBytes = Convert.FromBase64String(hashedPassword);byte[] salt = new byte[16];Array.Copy(hashBytes, 0, salt, 0, 16);var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 10000, HashAlgorithmName.SHA256);byte[] hash = pbkdf2.GetBytes(20);// 比较哈希值for (int i = 0; i < 20; i++){if (hashBytes[i + 16] != hash[i])return false;}return true;
}
实战场景2:配置文件加密(AES)
数据库连接字符串、API密钥这些敏感信息,千万别明文写在配置文件里!
public class AesHelper
{private readonly byte[] _key; // 256位密钥private readonly byte[] _iv; // 128位初始化向量public AesHelper(string base64Key, string base64Iv){_key = Convert.FromBase64String(base64Key);_iv = Convert.FromBase64String(base64Iv);}public string Encrypt(string plainText){using (var aes = Aes.Create()){aes.Key = _key;aes.IV = _iv;using (var encryptor = aes.CreateEncryptor())using (var ms = new MemoryStream()){using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))using (var sw = new StreamWriter(cs)){sw.Write(plainText);}return Convert.ToBase64String(ms.ToArray());}}}public string Decrypt(string cipherText){using (var aes = Aes.Create()){aes.Key = _key;aes.IV = _iv;using (var decryptor = aes.CreateDecryptor())using (var ms = new MemoryStream(Convert.FromBase64String(cipherText)))using (var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))using (var sr = new StreamReader(cs)){return sr.ReadToEnd();}}}
}// 使用示例
var helper = new AesHelper("你的Base64密钥", "你的Base64IV");
string encrypted = helper.Encrypt("Server=localhost;Database=test;");
string decrypted = helper.Decrypt(encrypted);
重要提醒: 密钥和IV要妥善保管,最好放在环境变量或密钥管理服务中。
实战场景3:数据传输加密(RSA + AES组合拳)
这是最实用的组合方案:用RSA加密AES的密钥,再用AES加密实际数据。
// 发送方
public class Sender
{public (string encryptedData, string encryptedKey) SendData(string data, string receiverPublicKey){// 1. 生成随机的AES密钥using (var aes = Aes.Create()){aes.GenerateKey();aes.GenerateIV();// 2. 用AES加密数据var aesHelper = new AesHelper(Convert.ToBase64String(aes.Key), Convert.ToBase64String(aes.IV));string encryptedData = aesHelper.Encrypt(data);// 3. 用对方的RSA公钥加密AES密钥using (var rsa = RSA.Create()){rsa.ImportFromPem(receiverPublicKey);byte[] encryptedKey = rsa.Encrypt(aes.Key, RSAEncryptionPadding.OaepSHA256);return (encryptedData, Convert.ToBase64String(encryptedKey));}}}
}// 接收方
public class Receiver
{private readonly RSA _privateKey;public Receiver(string privateKey){_privateKey = RSA.Create();_privateKey.ImportFromPem(privateKey);}public string ReceiveData(string encryptedData, string encryptedKey){// 1. 用自己的私钥解密AES密钥byte[] aesKey = _privateKey.Decrypt(Convert.FromBase64String(encryptedKey), RSAEncryptionPadding.OaepSHA256);// 2. 用AES密钥解密数据using (var aes = Aes.Create()){// 注意:IV也需要安全传递,这里简化处理var helper = new AesHelper(Convert.ToBase64String(aesKey), "base64IV");return helper.Decrypt(encryptedData);}}
}
我踩过的坑,希望你避开
-
密钥管理混乱:早期我把密钥硬编码在代码里,换环境的时候欲哭无泪。现在都用环境变量或专门的密钥管理工具。
-
模式选择错误:AES的ECB模式不安全,一定要用CBC或GCM模式。
-
忘记处理异常:加解密失败很常见,一定要做好异常处理,别让密文泄露到日志里。
-
性能问题:RSA加密大量数据慢得要死,所以要用上面那种组合方案。
实用建议
- 密码存储:用PBKDF2、BCrypt或Argon2
- 配置文件加密:AES足够好用
- 网络传输:RSA+AES组合拳
- 数据校验:用HMAC-SHA256而不是简单的MD5
最后提醒一句:除非你是密码学专家,否则不要自己发明加密算法。用.NET框架提供的这些标准实现,已经足够安全了。
需要生成密钥对?评论区告诉我,下次分享一键生成RSA密钥对的实用工具类。