【问题标题】:Encrypt/Decrypt property while writing/reading to c# mongo db在写入/读取到 c# mongodb 时加密/解密属性
【发布时间】:2019-03-13 06:30:37
【问题描述】:

我将列出我拥有的所有信息:

简而言之,我正在寻找与 this 完全相同但与 ASP Core (2.2) 和 C# MongoDB 驱动程序 (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) 获取 Serializer。在引导方法中考虑BsonSerializer.RegisterSerializer(type,serializer) 之类的东西,我可以在其中访问服务集合并执行GetInstance,但是我需要string SocialSecurityNumber 才能使用自定义类型(可能是SecureString?) p>

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

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

【问题讨论】:

    标签: c# mongodb encryption asp.net-core


    【解决方案1】:

    我的解决方案:

    型号:

    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);
        }
    }
    

    序列化器(使用Deterministic Encryption):

    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>());
    

    【讨论】:

    • 为了方便起见,您应该添加:'public override string ToString() => $"{_value}";'到 EncryptedString 类。否则,您需要在调用 EncryptedString 时对其进行强制转换。您的回答帮助我完成了我目前正在进行的一个项目 - 感谢您在这里所做的努力。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多