In a small inhouse app I wrote recently I store the settings in a json file, using the popular Json.NET library. However, the settings include a password, which should’t appear as clear text in the json file.

I stumbled over this answer at Stack Overflow by Brian Rogers. This solution uses a custom IContractResolver and a new marker attribute JsonEncryptAttribute. Adding the attribute is quite easy:

public class Settings {
    [JsonEncrypt]
    public string Password { get; set; }
}

But you have to remember to add the ContractResolver additionally:

JsonConvert.SerializeObject(book, Formatting.Indented, new JsonSerializerSettings {
    ContractResolver = new EncryptedStringPropertyResolver ("#my*S3cr3t")
});

Though the solution is clever, I don’t like the custom IContractResolver. Therefore I read through Json.NET’s documentation to find an easier way, i.e. by only applying an attribute to the property to encrypt.

In fact, Json.NET supports custom converters by annotating properties with JsonConverterAttribute. That attribute even allows you to pass additional parameters to your custom converter, like in this case the encryption key.

Therefore I took Brian’s code and converted it into a JsonConverter (also published as a Gist):

And the usage is pretty simple:

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

There’s no need for any additional code like a custom ContractResolver. And you can even use different encryption keys for different properties.

My code works only for string properties though, but that’s all I needed.

Tags:

Updated:

Comments

Eddie Shipman

Thomas, thanks for the great article. We are attempting to use this but running into an issue. Our Converter requires an object called EncryptionProvider that does the actual en/decrypting.

Now, with the attribute: [JsonConverter(typeof(EncryptionJsonConverter)] The EncryptionJsonConverter has a constructor where we inject the EncryptionProvider using DI.

The issue we are having is that it is instantiating a new converter for each property that has the attribute instead of using the one that was already created.

Any ideas how to fix this?

Thomas Freudenberg

Eddie, without knowing the Details of your requirements, a simple solution could be to just use a static EncryptionProvider property in your converter. Another, more advanced approach would involve implementing a custom ContractResolver.

Leave a Comment

Your email address will not be published. Required fields are marked *

Loading...