• 在EF Core中为数据表按列加密存储


    假设有User表

    public class User : Entity<int>
    {
        public int Id { get; set; }
        public string UserName { get; set; }
        public string Name { get; set; }
        public string IdentificationNumber { get; set; }
    }
    

    其中有身份证号码IdentificationNumber列,需要加密存储,该如何实现?

    在这里插入图片描述

    创建一个值转换器,继承ValueConverter类型。其中泛型TModel为实体中属性的类型。

    转换器将实体中属性类型,通过AES加密算法,转换为Base64编码字符串类型,存储到数据库中。当从数据库中读取数据时,再通过AES解密算法,将Base64编码字符串类型转换为实体中属性类型。

    若实体类型为byte[],则不需要转换为Base64编码字符串类型,直接对二进制数据进行加密和解密。此转换器可以用于加密存储图片、文件等二进制数据。

    AES加密算法是一种对称加密算法,加密和解密使用相同的密钥。在加密和解密时,需要指定密钥、初始向量、盐值等参数。在转换器中,将这些参数设置为静态属性,方便在使用时,进行修改。

    代码如下:

    public class EncryptionConverter<TModel> : ValueConverter<TModel, string>
    {
    
        public const int DefaultKeysize = 256;
    
        public static string DefaultPassPhrase { get; set; }
    
        public static byte[] DefaultInitVectorBytes { get; set; }
    
        public static byte[] DefaultSalt { get; set; }
        public EncryptionConverter()
            : base(
                x => Encrypt(x),
                x => Decrypt(x))
        {
            DefaultPassPhrase = "gsKnGZ041HLL4IM8";
            DefaultInitVectorBytes = Encoding.ASCII.GetBytes("jkE49230Tf093b42");
            DefaultSalt = Encoding.ASCII.GetBytes("hgt!16kl");
        }
    
        private static string Encrypt(TModel input)
        {
            try
            {
                byte[] inputData = input switch
                {
                    string => Encoding.UTF8.GetBytes(input.ToString()),
                    byte[] => input as byte[],
                    _ => null,
                };
    
                using (var password = new Rfc2898DeriveBytes(DefaultPassPhrase, DefaultSalt))
                {
                    var keyBytes = password.GetBytes(DefaultKeysize / 8);
                    using (var symmetricKey = Aes.Create())
                    {
                        symmetricKey.Mode = CipherMode.CBC;
                        using (var encryptor = symmetricKey.CreateEncryptor(keyBytes, DefaultInitVectorBytes))
                        {
                            using (var memoryStream = new MemoryStream())
                            {
                                using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
                                {
                                    cryptoStream.Write(inputData, 0, inputData.Length);
                                    cryptoStream.FlushFinalBlock();
                                    var cipherTextBytes = memoryStream.ToArray();
                                    var rawString = Convert.ToBase64String(cipherTextBytes);
                                    return rawString;
    
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {              
                LogHelper.LogException(ex);
                return input.ToString();              
            }
            
        }
    
        private static TModel Decrypt(string input)
        {
            try
            {
                var cipherTextBytes = Convert.FromBase64String(input);
    
                using (var password = new Rfc2898DeriveBytes(DefaultPassPhrase, DefaultSalt))
                {
                    var keyBytes = password.GetBytes(DefaultKeysize / 8);
                    using (var symmetricKey = Aes.Create())
                    {
                        symmetricKey.Mode = CipherMode.CBC;
                        using (var decryptor = symmetricKey.CreateDecryptor(keyBytes, DefaultInitVectorBytes))
                        {
                            using (var memoryStream = new MemoryStream(cipherTextBytes))
                            {
                                using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
                                {
                                    var plainTextBytes = new byte[cipherTextBytes.Length];
                                    int totalDecryptedByteCount = 0;
                                    while (totalDecryptedByteCount < plainTextBytes.Length)
                                    {
                                        var decryptedByteCount = cryptoStream.Read(
                                            plainTextBytes,
                                            totalDecryptedByteCount,
                                            plainTextBytes.Length - totalDecryptedByteCount
                                        );
    
                                        if (decryptedByteCount == 0)
                                        {
                                            break;
                                        }
    
                                        totalDecryptedByteCount += decryptedByteCount;
                                    }
                                    byte[] outputData = null;
                                    if (typeof(TModel) == typeof(string))
                                      {
                                          var outputData = Encoding.UTF8.GetString(plainTextBytes, 0, totalDecryptedByteCount);
                                          return (TModel)Convert.ChangeType(outputData, typeof(TModel));
    
                                      }
                                      else if (typeof(TModel) == typeof(byte[]))
                                      {
                                          var outputData = plainTextBytes as byte[];
                                          return (TModel)Convert.ChangeType(outputData, typeof(TModel));
    
                                      };
                                      return default; 
    
                                }
                            }
                        }
                    }
                }
    
            }
            catch (Exception ex)
            {
            	// 记录异常
                // LogHelper.LogException(ex);
                return (TModel)Convert.ChangeType(input, typeof(TModel));
            }
    
        }
    }
    
    

    DbContext中,重写OnModelCreating方法,为User表的IdentificationNumber列,添加值转换器。

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity().Property(c => c.IdentificationNumber).HasConversionstring>>();
    }
    
    

    再次调用Add方法插入数据时,可以看到IdentificationNumber列已被加密了

    在这里插入图片描述

  • 相关阅读:
    TCP为什么要三次握手?
    网络协议-语义、语法和时序
    深度优先搜索&广度优先搜索
    无限滚动图片懒加载-Infinite-Scroll-Img-笔记学习
    初识Linux
    在VMware Workstation Pro安装win7
    运筹学研究者关注的Github和CSDN账号
    《征服数据结构》目录
    OrangePi Kunpeng Pro 开发板测评 | AI 边缘计算 & 大模型部署
    ELK企业级日志分析平台
  • 原文地址:https://www.cnblogs.com/jevonsflash/p/17288803.html