Introducing Data Contract Serialize-Encrypt

Two previous posts of mine focused on Encrypting and Decrypting streams with the BCL class DataContractSerializer

After writing these, I realised that it would be quite nice to build these into a small open source library, and publish it to the world.

So, without further ado, I’d like to introduce the imaginatively titled SerializeEncrypt.

Data Contract Serializer

Recall that to serialize a class instance with DataContractSerializer we need to ensure that the class decorated appropriately with the correct attributes:

[DataContract]
public sealed class SerializableType
{
    [DataMember]
    public int Id { get; set; }

    [DataMember]
    public string Name { get; set; }
}

Then we create a new instance of DataContractSerializer and call .WriteObject(), passing in a stream and the serializable type instance.

var graph = new SerializableType {Id = 1, Name="James"};
var dcs = new DataContractSerializer(graph.GetType());
dcs.WriteObject(stream, graph);

Encrypting With Serialize-Encrypt

The new library decorates DataContractSerializer applying encryption or decryption to the process:

//Setup serializable object and data contract serializer as before
var graph = new SerializableType {Id = 1, Name="James"};
var dcs = new DataContractSerializer(graph.GetType());

//now setup encryptor and apply:
serializerEncryptor = new DataContractSerializerEncrpytor(dcs);
serializerEncryptor.WriteObjectEncrypted(stream, graph);

Decrypting with Serialize-Encrypt

Decrypting a source is a simple case of passing that source as a stream to the decryptor ReadObjectEncrypted():

//Setup DataContractSerializer and DataContractSerializerEncrpytor
var dcs = new DataContractSerializer(typeof(SerializableClass));
var dcsEncryptor = new DataContractSerializerEncrpytor(dcs);

//Setup stream to decrypt and pass this into our encryptor
var stream = new MemoryStream(encrpytedBytes);  //could be a file stream
var decryptedObject = 
    (SerializableClass)dcsEncryptor.ReadObjectEncrypted(stream);

Overriding Default Encryption

By default, the functionality uses AesCryptoServiceProvider with a default encryption key and IV (Initialization Vector). At the very least, it’s advisable to override the Key and IV. There are three overridable items. in the in the following configuration:

  • Override Key and IV
  • Override Key, IV and Algorithm.

To override the default algorithm provider, we must specify one based upon SymmetricAlgorithm. If we do override the default (AesCryptoServiceProvider) we are required to stipulate a different Key and IV. This is because different algorithms require different key sizes. The .LegalKeySizes property of the CryptoServiceProvider instance tells you which key sizes are allowed.

The following code shows how we override all three:

serializerEncryptor.OverrideEncryption(
    new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 },
    new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 },
    new DESCryptoServiceProvider());

We can also do this from the constructor:

var serializerOverriddenEncryptor = new DataContractSerializerEncrpytor(
    dataContractSerializer,
    new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 },
    new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 },
    new DESCryptoServiceProvider());

Naturally, you’ll want to source the Key and IV from elsewhere, as you’ll need them to decrypt, and it’ll not necessarily be part of the same process.

GitHub and NuGet Locations

The source code is hosted on GitHub and is also available through NuGet package manager:

Leave a Reply