首页 > 其他分享 >在EF Core中为数据表按列加密存储

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

时间:2023-04-05 09:01:58浏览次数:41  
标签:Core EF 数据表 TModel input var using byte public

假设有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列,需要加密存储,该如何实现?
![在这里插入图片描述](/i/ll/?i=a9edb9793cc841ff91391ec7d4d298d7.png

在这里插入图片描述

创建一个值转换器,继承ValueConverter<TModel, string>类型。其中泛型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))
                                {
                                    outputData = Encoding.UTF8.GetBytes(plainTextBytes.ToString());
                                }
                                else if (typeof(TModel) == typeof(byte[]))
                                {
                                    outputData = plainTextBytes as byte[];
                                };

                                var rawString = Encoding.UTF8.GetString(outputData, 0, totalDecryptedByteCount);

                                return (TModel)Convert.ChangeType(rawString, typeof(TModel));

                            }
                        }
                    }
                }
            }

        }
        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<User>().Property(c => c.IdentificationNumber).HasConversion<EncryptionConverter<string>>();
}

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

在这里插入图片描述

标签:Core,EF,数据表,TModel,input,var,using,byte,public
From: https://www.cnblogs.com/jevonsflash/p/17288803.html

相关文章

  • Defi开发简介
    Defi开发简介介绍Defi是去中心化金融的缩写,是一项旨在利用区块链技术和智能合约创建更加开放,可访问和透明的金融体系的运动.这与传统金融形成鲜明对比,传统金融通常由少数大型银行和金融机构控制在Defi的世界里,用户可以直接从他们的电脑或移动设备上访问广泛的金融服务,而不需......
  • 解决Abp设置DefaultLanguage默认语言不生效的问题
    @目录现象原因分析解决问题现象默认地,Abp的语言提供程序将返回的CultureInfo为En,在一些默认实现的接口(比如/api/TokenAuth/Authenticate)返回的错误信息是英文目标是改成简体中文显示,但是即便我们在AbpSettings表中加入了DefaultLanguage为"zh-Hans"AddSettingIfNotExists(L......
  • Huananzhi X99-AD3 Intel E5-2696v3黑苹果efi引导文件
    原文来源于黑果魏叔官网,转载需注明出处。(下载请直接百度黑果魏叔)硬件型号驱动情况主板HuananzhiX99-AD3处理器IntelE5-2696v3已驱动内存64GB(2*32)DDR3ECC1866Samsung已驱动硬盘SamsungPM961512GBNVMe已驱动显卡GigabyteRadeonRX5600XTWindForceOC6GB已驱动声卡......
  • mac remove system default short cut
    ......
  • Codeforces Round 862 A-E
    CodeforcesRound862(Div.2)先简单写一下A-E的题解。A异或的经典性质:\(x\oplusx=0\)。B显然要把字典序最小的那个字母放到最前面。如果这个字母出现了很多次,那么应该选择最后一次出现的位置。这也很容易证明。C联立以后计算一下就行了。比赛的时候爆了一次int。......
  • vue数组和对象进行 watch 和 watchEffect 对比
    constarr1=ref([]);constarr2=reactive([]);constobj1=ref({});constobj2=reactive({});watchEffect(()=>{console.log("watchEffectarr1",arr1.value);console.log("watchEffectarr2",arr2)......
  • 在AspNet Core项目中集成Serilog
    1.引入Nuget包Serilog.AspNetCore2.配置SerilogusingSerilog;Log.Logger=newLoggerConfiguration().WriteTo.Console()//添加console日志输出.WriteTo.Debug()//添加debug日志输出.CreateLogger();try{Log.Information("Startingwebapplicat......
  • 记几次 [线上环境] Dubbo 线程池占满原因分析(第二次:CompletableFuture)
    转载:https://blog.csdn.net/wsmalltiger/article/details/124236189文章目录[线上环境]Dubbo线程池占满原因排查系列前言一、问题分析1、分析日志2、定位原因二、解决方案三、总结前言  某天早上9点左右收到线上故障报警,超过3个商家反馈“无法正常进入功能页面,点击相关操作提......
  • cramfs-1.1/mkcramfs.c:446: undefined reference to `minor'
    在编译cramfs-1.1时报如下错误:/usr/bin/ld:/tmp/ccMb5KDC.o:infunction`print_node':/root/cramfs-1.1/mkcramfs.c:446:undefinedreferenceto`minor'/usr/bin/ld:/root/cramfs-1.1/mkcramfs.c:446:undefinedreferenceto`major'collect2:error:ldr......
  • Codeforces Round 717 (Div. 2) B. AGAGA XOOORRR(位运算)
    https://codeforces.com/contest/1516/problem/B题目大意:给定长度为n的数组a,问我们能不能一直选择两个相邻的元素进行异或后,删除这两个值,把异或值留下来,最后剩下>=2个数字,它们都是相同的?可以做到输出YES,不能的话输出NO。input23022423110outputYESNO题......