# Tuesday, September 28, 2010
I have a content management system developed in visual basic DotNet which I use for some charities I support.  See

http://www.doncasterstgeorges.org.uk
http://www.DoncasterScouts.org.uk and
http://www.26doncaster.org.uk for examples.

Under the hood the data is stored in XML files rather than in a formal database.  I wanted to ensure that the hosted data is secure so have moved from using plain text XML to compressed and encrypted XML.  This has one main benefit - I feel comfortable using an e-mail message with the files attached to back up the data.

This post explains how I did this.  The encryption is using DES which is good enough and symmetric.  The DES service provider is used in many functions and subroutines so I created it as a function.  The compression is using the inbuilt DotNet GZIP compression routine which uses the standard deflate compression.  It seems particularly efficient on XML.

Imports System.Security.Cryptography
Imports System.IO.Compression
Imports System.Xml


    ' Generic code for encrypting XML serialisations


    Public Function DesSP() As DESCryptoServiceProvider
        Dim locDesSP As New DESCryptoServiceProvider
        locDesSP.IV = ASCIIEncoding.ASCII.GetBytes("ABCDEFGH") ' Any 8 characters
        locDesSP.Key = ASCIIEncoding.ASCII.GetBytes("12345678") ' Any 8 characters
        Return locDesSP
    End Function


I opted for a single routine to save any dataset as a compressed and encrypted file since the generic dataset type would suffice.

    Public Sub SaveXMLds(ByVal FileName As String, ByVal DS As DataSet)

        ' This subroutine serialises the specified data set as encrypted XML to the file specified
        ' It works by
        ' 1. creating a CryptoAPITransform using the DESCryptoServiceProvider which is symmetric
        ' 2. creating an filestream writing to a file
        ' 3. creating an encryption stream which uses the CryptoAPITransform to stream to the filestream
        ' 4. creating a compression stream which uses the gZipStream to stream to the encryption stream
        ' 5. creating a streamwriter to write to the encryption stream
        ' 6. creating an XMLwriter to convert the XML serialisation of the data set into a stream
        ' 7. finally, having all the plumbing in place, creating a simple serialisation of the dataset into the XMLwriter

        ' The flow becomes
        ' DataSet -> XML -> XMLWriter -> streamwriter -> Compression stream -> encryption stream -> filestream -> file

        Dim Encryptor As CryptoAPITransform
        Encryptor = DesSP.CreateEncryptor

        Dim OutFile As New FileStream(FileName, FileMode.Create, FileAccess.Write)
        Dim EncryptStream As New CryptoStream(OutFile, Encryptor, CryptoStreamMode.Write)
        Dim CompressStream As New GZipStream(EncryptStream, CompressionMode.Compress)
        Dim OutgoingStream As New StreamWriter(CompressStream)
        Dim OutgoingXML As XmlWriter = XmlWriter.Create(OutgoingStream)

        ' Save the data

        DS.WriteXml(OutgoingXML)

        ' Now time to tidy up afterwards and clean the pipework
        OutgoingXML.Flush()
        OutgoingXML.Close()
        OutgoingStream.Flush()
        OutgoingStream.Close()
        EncryptStream.Flush()
        EncryptStream.Close()

        ' close the file
        OutFile.Close()

    End Sub

For reading the dataset back in I opted for dataset type specific modules, following this example.  The pdsLibrary object in the example is used to cache the data for reads. 

The function is designed to return an XML file if it exists, and then save the XML dataset as a compressed, encrypted file deleting the XML file.  This is to enable the compressed encrypted data to be initially populated.

If the XML version does not exist, the function sets up the streams and reads the data into the typed dataset.


    Dim pdsLibrary As Library

    Public Function GetLibrary() As Library
        Dim fName As String = GetDBPath() + "\Library"
        Dim fNameDS As String = fName + ".zDS"
        Dim fNameXML As String = fName + ".XML"

        If pdsLibrary Is Nothing Then
            pdsLibrary = New Library

            If File.Exists(fNameXML) Then ' an XML file will be used to oferwrite the encrypted file
                pdsLibrary.ReadXml(fNameXML)
                SaveXMLds(fNameDS, pdsLibrary)
                File.Delete(fNameXML)
            ElseIf File.Exists(fNameDS) Then
                Dim Decryptor As CryptoAPITransform
                Decryptor = DesSP.CreateDecryptor
                Dim InFile As New FileStream(fNameDS, FileMode.Open, FileAccess.Read)
                Dim EncryptStream As New CryptoStream(InFile, Decryptor, CryptoStreamMode.Read)
                Dim CompressStream As New GZipStream(EncryptStream, CompressionMode.Decompress)
                Dim IncomingStream As New StreamReader(CompressStream)
                Dim IncomingXML As XmlReader = XmlReader.Create(IncomingStream)
                pdsLibrary.ReadXml(IncomingXML)
            End If
        End If

        GetLibrary = pdsLibrary
    End Function

If you find this useful or have comments, share them with me.

posted on Tuesday, September 28, 2010 12:14:20 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] Trackback
Related posts:

Referred by:
http://insurancesnames.info/ [Referral]
http://luckyinsurance.info/ [Referral]
http://www.google.com/search [Referral]
Comments are closed.