在数据库设计中,尤其在设计用户数据表时,通常都要考虑用户数据加密的情况,数据表中不明文显示用户信息,避免泄露用户隐私。
针对用户姓名、手机号、身份证号等敏感信息,可以采用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);
}
感谢看完全文,比心!