SkillAgentSearch skills...

Newtonsoft.Json.Encryption

Leverages the Newtonsoft extension API to encrypt/decrypt specific nodes at serialization time

Install / Use

/learn @NServiceBusCommunity/Newtonsoft.Json.Encryption
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

<!-- GENERATED FILE - DO NOT EDIT This file was generated by [MarkdownSnippets](https://github.com/SimonCropp/MarkdownSnippets). Source File: /readme.source.md To change this file edit the source file and then run MarkdownSnippets. -->

<img src="/src/icon.png" height="25px"> Newtonsoft.Json.Encryption

Build status NuGet Status NuGet Status NuGet Status

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

<!--- StartOpenCollectiveBackers -->

Already a Patron? skip past this section

Community backed

It is expected that all developers either become a Patron to use NServiceBusExtensions. Go to licensing FAQ

Sponsors

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

Patrons

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

<img src="https://opencollective.com/nservicebusextensions/tiers/patron.svg?width=890&avatarHeight=60&button=false">

<a href="#" id="endofbacking"></a>

<!--- EndOpenCollectiveBackers --> <!-- toc -->

Contents

NuGet packages

  • https://nuget.org/packages/Newtonsoft.Json.Encryption/
  • https://nuget.org/packages/Rebus.Newtonsoft.Encryption/
  • https://nuget.org/packages/NServiceBus.Newtonsoft.Encryption/

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:

<!-- snippet: Workflow -->

<a id='snippet-workflow'></a>

// 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
})
{
    //TODO: store initVector for use in deserialization
    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);
    }
}

<sup><a href='/src/Newtonsoft.Json.Encryption.Tests/Snippets/Snippets.cs#L9-L70' title='Snippet source file'>snippet source</a> | <a href='#snippet-workflow' title='Start of snippet'>anchor</a></sup>

<!-- endSnippet -->

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.

<!-- snippet: serialize -->

<a id='snippet-serialize'></a>

// per serialize session
using (var algorithm = new RijndaelManaged
{
    Key = key
})
{
    //TODO: store initVector for use in deserialization
    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();
    }
}

<sup><a href='/src/Newtonsoft.Json.Encryption.Tests/Snippets/Snippets.cs#L26-L50' title='Snippet source file'>snippet source</a> | <a href='#snippet-serialize' title='Start of snippet'>anchor</a></sup>

<!-- endSnippet -->

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.
<!-- snippet: deserialize -->

<a id='snippet-deserialize'></a>

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

<sup><a href='/src/Newtonsoft.Json.Encryption.Tests/Snippets/Snippets.cs#L52-L69' title='Snippet source file'>snippet source</a> | <a href='#snippet-deserialize' title='Start of snippet'>anchor</a></sup>

<!-- endSnippet -->

Rebus

<!-- snippet: RebugsUsage -->

<a id='snippet-rebugsusage'></a>

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

<sup><a href='/src/Rebus.Newtonsoft.Encryption.Tests/Snippets/Snippets.cs#L16-L45' title='Snippet source file'>snippet source</a> | <a href='#snippet-rebugsusage' title='Start of snippet'>anchor</a></sup>

<!-- endSnippet -->

NServiceBus

<!-- snippet: NsbUsage -->

<a id='snippet-nsbusage'></a>

var configuration = new EndpointConfiguration("NServiceBusSample");
var serializa

Related Skills

View on GitHub
GitHub Stars49
CategoryProduct
Updated2y ago
Forks11

Languages

C#

Security Score

75/100

Audited on Jan 23, 2024

No findings