Introduction
XML is an easy, portable way to save DataSet
s within the .NET Framework. All methods to handle the XML are contained within .NET, so the end user will not need proprietary data handling software or server to read in the data.
I recently needed the ability to save encrypted DataSet
s to track a student's learning progress. Obviously, the XML format was too accessible to save this sort of information which needed to be kept from tampering, so I needed encryption, which comes standard with .NET. However, I was still facing a few challenges:
- I wanted to be able to accomplish all encryption and decryption with just a few calls to a special "crypto" class library.
- While decrypting a file in .NET is very easy, I wanted to avoid having temporary unencrypted files written to disk in the process.
- The start of every XML file is quite standard, so it can potentially be used to "guess" the encryption key and crack the code.
- Finally, I needed a mechanism to recognize encrypted files so the
DataSet
would not load erroneous data.
I set out to develop a class library (XMLEncryptor
) to encrypt and decrypt DataSet
s using a username and password. The challenges above were handled as follows:
The XMLEncryptor
class is instantiated using two strings, a user name and password. The constructor creates the encryption key and initialization vector, as well as a 16-byte signature.
The signature, which is written as a file header without encryption, is used by the XMLEncryptor
to identify files as having been encrypted using its methods. Also, the signature serves as a mask for to push the standard XML header to the 17th byte in the file, which should offer some level of protection against "guessing" the XML header (see 3 above).
The XMLEncryptor
exposes two public functions, one for reading in the encrypted XML file and one for writing the DataSet
back to a file:
public DataSet ReadEncryptedXML(string fileName)
public void WriteEncryptedXML(DataSet dataset, string encFileName)
The ReadEncryptedXML
function will return a DataSet
if all goes as intended. The encrypted XML data is decrypted into a MemoryStream
, which is subsequently used to load a DataSet
which can then be returned to the caller without having intermediary files written to disk. If an error is encountered during reading, decryption etc., the ReadEncryptedXML
function returns null
.
The WriteEncryptedXML
function takes the DataSet
and writes it to a file using the same encryption key and IV as was used for the decryption. Once again, no temporary files are involved.
A typical use of the XMLEncryptor
would be as follows:
{
XMLEncryptor XMLenc = new XMLEncryptor("myname", "mypassword");
DataSet myDataSet = XMLenc.ReadEncryptedXML("myfile.enc");
if (myDataSet == null)
{
return;
}
XMLEnc.WriteEncryptedXML(myDataSet, "myfile.enc");
}
Limitations of the application are:
- The handling of the username and password is left up to the parent application.
- Files of more than 2 GB cannot be handled. However, since the process involves in-memory handling of data, practical size limits may be smaller.
That's all!
Enjoy.