ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

C# 加密解密

C# 加密解密

在 C# 中实现MD5、RSA和DES的加解密封装,需要针对每种算法的特性选择合适的 .NET API。

MD5 是哈希算法(摘要算法),不可逆,主要用于数据完整性校验或生成指纹,MD5 一般不用于密码存储。密码存储通常使用PBKDF2、BCrypt或Argon2。由于存在碰撞风险,MD5也不常用于高安全需求的数字签名。

MD5 哈希计算封装

  • 使用 MD5.Create() 而非过时的 MD5CryptoServiceProvider。
  • 必须统一编码(推荐 UTF-8),否则中英文混合字符串在不同环境下的哈希值会不一致。
  • 输出通常转换为小写十六进制字符串。
using System; using System.Security.Cryptography; using System.Text; public static class Md5Helper { /// <summary> /// 计算字符串的 MD5 哈希值 /// </summary> /// <param>原始字符串</param> /// <returns>32位小写十六进制字符串</returns> public static string ComputeMd5(string input) { if (string.IsNullOrEmpty(input)) throw new ArgumentException("Input cannot be null or empty."); // 1. 将字符串转换为字节数组 (务必指定 UTF-8 编码) byte[] inputBytes = Encoding.UTF8.GetBytes(input); // 2. 计算哈希 using (MD5 md5 = MD5.Create()) { byte[] hashBytes = md5.ComputeHash(inputBytes); // 3. 转换为十六进制字符串并移除短横线,转为小写 return BitConverter.ToString(hashBytes).Replace("-", "").ToLower(); } } /// <summary> /// 计算文件的 MD5 哈希值 (流式处理,适合大文件) /// </summary> public static string ComputeFileMd5(string filePath) { if (!System.IO.File.Exists(filePath)) throw new System.IO.FileNotFoundException("File not found.", filePath); using (MD5 md5 = MD5.Create()) using (var stream = System.IO.File.OpenRead(filePath)) { byte[] hashBytes = md5.ComputeHash(stream); return BitConverter.ToString(hashBytes).Replace("-", "").ToLower(); } } }

RSA 非对称加密与签名封装

  • 加密场景:公钥加密,私钥解密。适用于传输少量敏感数据(如会话密钥)。2048位密钥下,OAEP-SHA256 填充模式最多加密约 190 字节数据。超长数据应采用“混合加密”(RSA 加密 AES 密钥,AES 加密数据)。
  • 签名场景:私钥签名,公钥验签。用于验证数据来源和完整性。
  • 使用 RSA.Create() 以确跨平台兼容性(Windows 使用 CNG,Linux/macOS 使用 OpenSSL)。
  • 避免使用 PKCS#1 v1.5 进行加密(存在 Bleichenbacher 攻击风险),推荐使用 OAEP。
using System; using System.Security.Cryptography; using System.Text; public class RsaHelper : IDisposable { private readonly RSA _rsa; public RsaHelper(int keySize = 2048) { _rsa = RSA.Create(keySize); } // 如果已有密钥对,可通过构造函数导入 public RsaHelper(RSA rsaInstance) { _rsa = rsaInstance; } #region 密钥管理 /// <summary> /// 导出公钥 (PKCS#8 SubjectPublicKeyInfo 格式, Base64) /// </summary> public string ExportPublicKey() { byte[] publicKeyBytes = _rsa.ExportSubjectPublicKeyInfo(); return Convert.ToBase64String(publicKeyBytes); } /// <summary> /// 导出私钥 (PKCS#8 PrivateKeyInfo 格式, Base64) /// 注意:生产环境中私钥应受保护,不要明文持久化 /// </summary> public string ExportPrivateKey() { byte[] privateKeyBytes = _rsa.ExportPkcs8PrivateKey(); return Convert.ToBase64String(privateKeyBytes); } /// <summary> /// 从 Base64 字符串导入私钥 /// </summary> public void ImportPrivateKey(string privateKeyBase64) { byte[] privateKeyBytes = Convert.FromBase64String(privateKeyBase64); _rsa.ImportPkcs8PrivateKey(privateKeyBytes, out _); } #endregion #region 加密与解密 (公钥加密,私钥解密) /// <summary> /// 使用公钥加密数据 /// </summary> /// <param>明文</param> /// <param>公钥 Base64 字符串</param> public string Encrypt(string plainText, string publicKeyBase64) { using (RSA rsaPublic = RSA.Create()) { rsaPublic.ImportSubjectPublicKeyInfo(Convert.FromBase64String(publicKeyBase64), out _); byte[] data = Encoding.UTF8.GetBytes(plainText); // 使用 OAEP with SHA-256,安全性高于 PKCS1 byte[] encryptedData = rsaPublic.Encrypt(data, RSAEncryptionPadding.OaepS
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进