Свойство Encrypt / Decrypt при записи / чтении в c # mongo db - PullRequest
1 голос
/ 13 марта 2019

Просто собираюсь выложить всю имеющуюся у меня информацию:

Короче говоря, я ищу что-то в точности (буквально), например 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), чтобы получить Сериализатор. думать о чем-то вроде BsonSerializer.RegisterSerializer(type,serializer) в методе начальной загрузки, где я могу получить доступ к коллекции сервисов и выполнить GetInstance, но тогда мне понадобится string SocialSecurityNumber, чтобы использовать пользовательский тип (может быть SecureString?)

  2. Используйте DI в сериализаторе для получения ключа (сначала от IConfiguration / appsettings.json , а затем в конечном итоге от Azure KeyVault (для меня совершенно новая банка червей)) и EncryptionProvider

  3. детерминированное шифрование для поиска. AesThenHmac взято из этой популярной записи . Я могу хранить и извлекать данные обратно в порядке в его текущей реализации. Но для поиска SSN мне нужно детерминированное шифрование, которое эта библиотека не предоставляет.

1 Ответ

0 голосов
/ 19 марта 2019

Мое решение:

Модель:

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>());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...