Skip to content
Leverages the Newtonsoft extension API to encrypt/decrypt specific nodes at serialization time
C#
Branch: master
Clone or download
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
src Merge branch 'master' of https://github.com/NServiceBusExtensions/New… Aug 19, 2019
.editorconfig GitHubSync update Dec 3, 2018
.gitignore add nsb Sep 25, 2017
license.txt . Dec 2, 2018
readme.md doco Aug 8, 2019

readme.md

Leverages the Newtonsoft extension API to encrypt/decrypt specific nodes at serialization time. So only the notes that require encryption are touched, the remaining content is still human readable. This approach provides an compromise between readability/debugabaility and security.

Already a Patron? skip past this section

Community backed

It is expected that all developers become a Patron to use any of these libraries. Go to licensing FAQ

Sponsors

Support this project by becoming a Sponsors. The company avatar will show up here with a link to your website. The avatar will also be added to all GitHub repositories under this organization.

Patrons

Thanks to all the backing developers! Support this project by becoming a patron.

NuGet package

https://nuget.org/packages/Newtonsoft.Json.Encryption/ NuGet Status

Encryption Algorithms

Any implementation of SymmetricAlgorithm is supported.

Decorating properties

public class ClassToSerialize
{
    [Encrypt]
    public string Property { get; set; }
}

Serialized

{
    "Property":"wSayABpFI3g7a/D6gGTq5g=="
}

Supported property types

  • string
  • byte[]
  • Guid
  • IDictionary<T, string>
  • IDictionary<T, byte[]>
  • IDictionary<T, Guid>
  • IEnumerable<string>
  • IEnumerable<byte[]>
  • IEnumerable<Guid>

Note that only the values in a IDictionary are encrypted.

Usage

The full serialize and deserialization workflow:

// per system (periodically rotated)
var key = Encoding.UTF8.GetBytes("gdDbqRpqdRbTs3mhdZh9qCaDaxJXl+e6");

// per app domain
using (var factory = new EncryptionFactory())
{
    var serializer = new JsonSerializer
    {
        ContractResolver = factory.GetContractResolver()
    };

    // transferred as meta data with the serialized payload
    byte[] initVector;

    string serialized;

    // per serialize session
    using (var algorithm = new RijndaelManaged
    {
        Key = key
    })
    {
        initVector = algorithm.IV;
        using (factory.GetEncryptSession(algorithm))
        {
            var instance = new ClassToSerialize
            {
                Property = "PropertyValue",
            };
            var builder = new StringBuilder();
            using (var writer = new StringWriter(builder))
            {
                serializer.Serialize(writer, instance);
            }
            serialized = builder.ToString();
        }
    }

    // per deserialize session
    using (var algorithm = new RijndaelManaged
    {
        IV = initVector,
        Key = key
    })
    {
        using (factory.GetDecryptSession(algorithm))
        using (var stringReader = new StringReader(serialized))
        using (var jsonReader = new JsonTextReader(stringReader))
        {
            var deserialized = serializer.Deserialize<ClassToSerialize>(jsonReader);
            Console.WriteLine(deserialized.Property);
        }
    }
}

Breakdown

Key

See SymmetricAlgorithm.Key.

Example Key used for RijndaelManaged algorithm in the below sample code:

var key = Encoding.UTF8.GetBytes("gdDbqRpqdRbTs3mhdZh9qCaDaxJXl+e6");

A new valid key can be generated by instanitiating a SymmetricAlgorithm and accessing SymmetricAlgorithm.Key.

EncryptionFactory and JsonSerializer

Generally a single instance of EncryptionFactory will exist per AppDomain.

A single instance of EncryptionFactory is safe to be used for multiple instances of JsonSerializer.

var factory = new EncryptionFactory();

var serializer = new JsonSerializer
{
    ContractResolver = factory.GetContractResolver()
};

Serialization

A single encrypt session is used per serialization instance.

On instantiation the SymmetricAlgorithm will generate a valid IV. This is generally a good value to use for serialization and then stored for deserialization.

string serialized;

// per serialize session
using (var algorithm = new RijndaelManaged
{
    Key = key
})
{
    //TODO: store initVector for use in deserialization
    var initVector = algorithm.IV;
    using (factory.GetEncryptSession(algorithm))
    {
        var instance = new ClassToSerialize
        {
            Property = "PropertyValue",
        };
        var builder = new StringBuilder();
        using (var writer = new StringWriter(builder))
        {
            serializer.Serialize(writer, instance);
        }
        serialized = builder.ToString();
    }
}

Deserialization

A single decrypt session is used per serialization instance.

  • key must be the same as the one use for serialization.
  • initVector must be the same as the one use for serialization. It is safe to be transferred with the serialized text.
using (var algorithm = new RijndaelManaged
{
    IV = initVector,
    Key = key
})
{
    using (factory.GetDecryptSession(algorithm))
    using (var stringReader = new StringReader(serialized))
    using (var jsonReader = new JsonTextReader(stringReader))
    {
        var deserialized = serializer.Deserialize<ClassToSerialize>(jsonReader);
        Console.WriteLine(deserialized.Property);
    }
}

Rebus

NuGet package

https://nuget.org/packages/Rebus.Newtonsoft.Encryption/ NuGet Status

Usage

var activator = new BuiltinHandlerActivator();

activator.Register(() => new Handler());
var configurer = Configure.With(activator);

var encryptionFactory = new EncryptionFactory();
var settings = new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.All,
    ContractResolver = encryptionFactory.GetContractResolver()
};
configurer.Serialization(s => { s.UseNewtonsoftJson(settings); });
configurer.EnableJsonEncryption(
    encryptionFactory: encryptionFactory,
    encryptStateBuilder: () =>
        (
        algorithm: new RijndaelManaged
        {
            Key = key
        },
        keyId: "1"
        ),
    decryptStateBuilder: (keyId, initVector) =>
        new RijndaelManaged
        {
            Key = key,
            IV = initVector
        });

NServiceBus

NuGet package

https://nuget.org/packages/NServiceBus.Newtonsoft.Encryption/ NuGet Status

Usage

var configuration = new EndpointConfiguration("NServiceBusSample");
var serialization = configuration.UseSerialization<NewtonsoftSerializer>();
var encryptionFactory = new EncryptionFactory();
serialization.Settings(
    new JsonSerializerSettings
    {
        ContractResolver = encryptionFactory.GetContractResolver()
    });

configuration.EnableJsonEncryption(
    encryptionFactory: encryptionFactory,
    encryptStateBuilder: () =>
        (
        algorithm: new RijndaelManaged
        {
            Key = key
        },
        keyId: "1"
        ),
    decryptStateBuilder: (keyId, initVector) =>
        new RijndaelManaged
        {
            Key = key,
            IV = initVector
        });

Icon

Lock designed by Mourad Mokrane from The Noun Project.

You can’t perform that action at this time.