A custom converter for Json.NET to encrypt values, see https://thomasfreudenberg.com/archive/2017/02/11/encrypting-values-when-serializing-with-json-net/
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); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment