2020-02-17

Introducing JsonCryption!

I couldn't find a useful .NET library for easy and robust JSON property-level encryption/decryption, so I made one.

The GitHub page covers more details, but this is the gist:

Installation:

Install-Package JsonCryption.Newtonsoft
// There's also a version for System.Text.Json, but the implementation
// for Newtonsoft.Json is better, owing to the greater feature surface
// and customizability of the latter at this time.

Configuration:

// pseudo code (assuming using Newtonsoft.Json for serialization)
container.Register<JsonSerializer>(() => new JsonSerializer() {
  ContractResolver = new JsonCryptionContractResolver(container.Resolve<IDataProtectionProvider>())
});

Usage:

var myFoo = new Foo("some important value", "something very public");
class Foo
{
    [Encrypt]
    public string EncryptedString { get; }
    public string UnencryptedString { get; }

    public Foo(string encryptedString, string unencryptedString)
    {
        ...
    }
}
var serializer = // resolve JsonSerializer
using var textWriter = ...
serializer.Serialize(textWriter, myFoo);
// pseudo output: 
// {
//   "encryptedString": "akjdfkldjagkldhtlfkjk...",
//   "UnencryptedString": "something very public"
// }

Why I need JsonCryption

Discovery path

First Stop: Newtonsoft.Json.Encryption

Overriding JsonConverter

public class Settings {
    [JsonConverter(typeof(EncryptingJsonConverter), "#my*S3cr3t")]
    public string Password { get; set; }
}

Initial Attempt for System.Text.Json

public sealed class EncryptAttribute : JsonConverterAttribute
{
    public EncryptAttribute() : ElementsBase(typeof(EncryptedJsonConverterFactory))
    {
    }
}
  • Overriding the JsonConverterAttribute ultimately required using a Singleton pattern rather than clean Dependency Injection
  • System.Text.Json currently offers no ability to serialize non-public properties, nor fields of any visibility. For most DDD scenarios, this was also a non-starter.

Newtonsoft.Json

Adding support for Cryptography best practices

Switching to Microsoft.AspNetCore.DataProtection underneath

a simple, easy to use cryptographic API a developer can use to protect data, including key management and rotation

Closing