AES对称加密

在数据库设计中,尤其在设计用户数据表时,通常都要考虑用户数据加密的情况,数据表中不明文显示用户信息,避免泄露用户隐私。

针对用户姓名、手机号、身份证号等敏感信息,可以采用AES对称加密。与Hash加密不同的是,AES对称加密是可逆的,通过解密数据库的信息,可以还原完整信息显示。

为了防止数据库泄露,窃取者还原用户信息,在使用AES加密时需要用到密钥文件。这里建议密钥文件单独保存。

代码文件结构:AesKeyManager(密钥管理器);AesHelper(密钥工具类)。

一、密钥文件

C#内置AES, 不需要添加第三方依赖。

csharp 复制代码
 /// <summary>
 /// 密钥管理器
 /// </summary>
 public static class AesKeyManager
 {
     private static readonly string appPath = Path.Combine(
         Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
         "MyPro");

     private static readonly string KeyFile =
         Path.Combine(
             appPath,
             "aes.key");

     /// <summary>
     /// 获取AES Key
     /// 首次获取自动生成
     /// </summary>
     /// <returns></returns>
     public static byte[] GetKey()
     {
         if(!File.Exists(KeyFile))
         {
             CreateKey();
         }

         byte[] protectedKey = File.ReadAllBytes(KeyFile);

         return ProtectedData.Unprotect(protectedKey, null, DataProtectionScope.CurrentUser);
     }

     public static void CreateKey()
     {
         Directory.CreateDirectory(appPath);

         byte[] aseKey = RandomNumberGenerator.GetBytes(32);

         byte[] protectedKey = ProtectedData.Protect(aseKey, null,DataProtectionScope.CurrentUser);

         File.WriteAllBytes(KeyFile, protectedKey);
     }

     /// <summary>
     /// AES Key 文件路径
     /// </summary>
     public static string KeyFilePath => KeyFile;
 }

二、密钥工具类

csharp 复制代码
/// <summary>
/// AES 工具类
/// </summary>
public static class AesHelper
{
    /// <summary>
    /// 加密
    /// </summary>
    /// <param name="plainText"></param>
    /// <returns></returns>
    public static string Encrypt(string plainText)
    {
        byte[] key = AesKeyManager.GetKey();

        using Aes aes = Aes.Create();

        aes.Key = key;
		
        aes.GenerateIV();// 每次随机生成 IV

        using MemoryStream ms = new();

        ms.Write(aes.IV);

        using CryptoStream cs = new(ms, aes.CreateEncryptor(), CryptoStreamMode.Write);

        using StreamWriter sw = new(cs);

        sw.Write(plainText);

        sw.Close();

        return Convert.ToBase64String(ms.ToArray());

    }

    /// <summary>
    /// 解密
    /// </summary>
    /// <param name="plainText"></param>
    /// <returns></returns>
    public static string Decrypt(string cipherText) 
    {
        byte[] key = AesKeyManager.GetKey();

        byte[] buffer = Convert.FromBase64String(cipherText);

        using Aes aes = Aes.Create();

        aes.Key = key;

        byte[] iv = new byte[16];// 提取前 16 字节为 IV

        Array.Copy(buffer, 0, iv, 0, 16);

        aes.IV = iv;

        using MemoryStream ms = new(buffer, 16, buffer.Length - 16);

        using CryptoStream cs = new(ms, aes.CreateDecryptor(), CryptoStreamMode.Read);

        using StreamReader sr = new(cs);

        return sr.ReadToEnd();
    }
}

附赠一个手机号脱敏显示,也作为自己的学习记录。

csharp 复制代码
 /// <summary>
 ///  手机号脱敏显示
 /// </summary>
 /// <param name="phone"></param>
 /// <returns></returns>
 public static string MaskPhone(string phone)
 {
     if (string.IsNullOrWhiteSpace(phone))
         return phone;

     if (phone.Length != 11)
         return phone;

     return phone.Substring(0, 3) + "****" + phone.Substring(7);
 }

感谢看完全文,比心!