Last active
June 12, 2023 07:10
-
-
Save thoemmi/e118c15e7588750b1cc18dab00be31fd to your computer and use it in GitHub Desktop.
A custom converter for Json.NET to encrypt values, see https://thomasfreudenberg.com/archive/2017/02/11/encrypting-values-when-serializing-with-json-net/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class EncryptingJsonConverter : JsonConverter { | |
private readonly byte[] _encryptionKeyBytes; | |
public EncryptingJsonConverter(string encryptionKey) { | |
if (encryptionKey == null) { | |
throw new ArgumentNullException(nameof(encryptionKey)); | |
} | |
// Hash the key to ensure it is exactly 256 bits long, as required by AES-256 | |
using (var sha = new SHA256Managed()) { | |
_encryptionKeyBytes = | |
sha.ComputeHash(Encoding.UTF8.GetBytes(encryptionKey)); | |
} | |
} | |
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { | |
var stringValue = (string)value; | |
if (string.IsNullOrEmpty(stringValue)) { | |
writer.WriteNull(); | |
return; | |
} | |
var buffer = Encoding.UTF8.GetBytes(stringValue); | |
using (var inputStream = new MemoryStream(buffer, false)) | |
using (var outputStream = new MemoryStream()) | |
using (var aes = new AesManaged { | |
Key = _encryptionKeyBytes | |
}) { | |
var iv = aes.IV; // first access generates a new IV | |
outputStream.Write(iv, 0, iv.Length); | |
outputStream.Flush(); | |
var encryptor = aes.CreateEncryptor(_encryptionKeyBytes, iv); | |
using (var cryptoStream = new CryptoStream(outputStream, encryptor, CryptoStreamMode.Write)) { | |
inputStream.CopyTo(cryptoStream); | |
} | |
writer.WriteValue(Convert.ToBase64String(outputStream.ToArray())); | |
} | |
} | |
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { | |
var value = reader.Value as string; | |
if (string.IsNullOrEmpty(value)) { | |
return reader.Value; | |
} | |
try { | |
var buffer = Convert.FromBase64String(value); | |
using (var inputStream = new MemoryStream(buffer, false)) | |
using (var outputStream = new MemoryStream()) | |
using (var aes = new AesManaged { | |
Key = _encryptionKeyBytes | |
}) { | |
var iv = new byte[16]; | |
var bytesRead = inputStream.Read(iv, 0, 16); | |
if (bytesRead < 16) { | |
throw new CryptographicException("IV is missing or invalid."); | |
} | |
var decryptor = aes.CreateDecryptor(_encryptionKeyBytes, iv); | |
using (var cryptoStream = new CryptoStream(inputStream, decryptor, CryptoStreamMode.Read)) { | |
cryptoStream.CopyTo(outputStream); | |
} | |
var decryptedValue = Encoding.UTF8.GetString(outputStream.ToArray()); | |
return decryptedValue; | |
} | |
} | |
catch { | |
return string.Empty; | |
} | |
} | |
/// <inheritdoc /> | |
public override bool CanConvert(Type objectType) { | |
return objectType == typeof(string); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Settings { | |
[JsonConverter(typeof(EncryptingJsonConverter), "#my*S3cr3t")] | |
public string Password { get; set; } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment