Encrypting values when serializing with JSON.NET
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.
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 customContractResolver
.Thomas Freudenberg
Eddie, I recommend to read this StackOverflow answer, which I also reference somewhere at the beginning of my post.
Robert Morley
Thank you for this. This is exactly my situation as well!
Leave a Comment
Your email address will not be published. Required fields are marked *