首页 > 解决方案 > 在写入/读取到 c# mongo db 时加密/解密属性

问题描述

只是要列出我拥有的所有信息:

简而言之,我正在寻找与 ASP Core (2.2) 和 C# MongoDB Driver (2.7) 完全(字面意思)类似的东西。

这似乎是一个常见的要求,我很惊讶我找不到任何已经建成的东西。

这是我到目前为止所拥有的:

模型:

public class Patient
{
    //comes from the client as XXXXXXXXX, RegEx: "([0-9]{9})"
    //[MongoEncrypt]
    public EncryptedString SocialSecurityNumber { get; set; }  
}

属性:

[AttributeUsage(AttributeTargets.Property)]
public class MongoEncryptAttribute : BsonSerializerAttribute
{
    public MongoEncryptAttribute()
    {
        SerializerType = typeof(MongoEncryptSerializer);
    }
}

自定义序列化器:

public interface IMongoEncryptSerializer : IBsonSerializer<EncryptedString>{ }

public class MongoEncryptSerializer : SerializerBase<EncryptedString>, IMongoEncryptSerializer
{
    private readonly string _encryptionKey;

    public MongoEncryptSerializer(IConfiguration configuration)
    {
        _encryptionKey = configuration.GetSection("MongoDb")["EncryptionKey"];
    }

    public override EncryptedString Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        var encryptedString = context.Reader.ReadString();
        return AesThenHmac.SimpleDecryptWithPassword(encryptedString, _encryptionKey);
    }

    public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, EncryptedString value)
    {
        var encryptedString = AesThenHmac.SimpleEncryptWithPassword(value, _encryptionKey);
        context.Writer.WriteString(encryptedString);
    }
}

未清项目:

  1. 使用 DI (vanilla .net core DI) 获取序列化程序。考虑类似BsonSerializer.RegisterSerializer(type,serializer)在引导方法中的东西,我可以访问服务集合并执行一个GetInstance但是我需要string SocialSecurityNumber使用自定义类型(也许SecureString?)

  2. 在序列化程序中使用 DI 获取密钥(最初来自IConfiguration/appsettings.json ,然后最终来自 Azure KeyVault(对我来说是全新的蠕虫罐头))和 EncryptionProvider

  3. 用于搜索的确定性加密。AesThenHmac来自这个热门帖子。我可以在当前的实现中很好地存储和检索数据。但是为了搜索 SSN,我需要这个库不提供的确定性加密。

标签: c#mongodbencryptionasp.net-core

解决方案


我的解决方案:

模型:

public class Patient
{
    //comes from the client as XXXXXXXXX, RegEx: "([0-9]{9})"
    public EncryptedString SocialSecurityNumber { get; set; }  
}

自定义类型:

public class EncryptedString
{
    private readonly string _value;

    public EncryptedString(string value)
    {
        _value = value;
    }

    public static implicit operator string(EncryptedString s)
    {
        return s._value;
    }

    public static implicit operator EncryptedString(string value)
    {
        if (value == null)
            return null;

        return new EncryptedString(value);
    }
}

序列化器(使用确定性加密):

public interface IEncryptedStringSerializer : IBsonSerializer<EncryptedString> {} 

public class EncryptedStringSerializer : SerializerBase<EncryptedString>, IEncryptedStringSerializer
{
    private readonly IDeterministicEncrypter _encrypter;
    private readonly string _encryptionKey;

    public EncryptedStringSerializer(IConfiguration configuration, IDeterministicEncrypter encrypter)
    {
        _encrypter = encrypter;
        _encryptionKey = configuration.GetSection("MongoDb")["EncryptionKey"];
    }

    public override EncryptedString Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        var encryptedString = context.Reader.ReadString();
        return _encrypter.DecryptStringWithPassword(encryptedString, _encryptionKey);
    }

    public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, EncryptedString value)
    {
        var encryptedString = _encrypter.EncryptStringWithPassword(value, _encryptionKey);
        context.Writer.WriteString(encryptedString);
    }
}

注册序列化器:

collection.AddScoped<IEncryptedStringSerializer, EncryptedStringSerializer>();
//then later...
BsonSerializer.RegisterSerializer<EncryptedString>(sp.GetService<IEncryptedStringSerializer>());

推荐阅读