C#加解密:从入门到放弃?不,是到实战!
刚接触加密那会儿,我被那些术语绕得头晕——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密钥对的实用工具类。

浙公网安备 33010602011771号