byrmol Blog

Garbage

Reading and Writing an encrypted Dataset to Disk

I am using Windows Forms for my current project and with so much processing power going to waste on most users desktop, I have been trying to offload network traffic via client side caching.  The requirements stated that the cache needs to be accessible for every user who uses the PC, encrypted and able to be copied between 2 PC’s.

When the app starts and the first successful logon occurs, I reach out to the DB and suck down the primary data domain.  This dataset contains nearly half the database.  It’s only a couple of megabytes and is compromised mostly of slow changing data elements (“look up” tables, user preferences etc…).   In a LAN environment (>10Mb/sec), this primary request is trivial.  But on a VPN (256k/64k) over the Internet, it becomes an issue.

So I decided to use the cache to cut down the primary request at start up.  Serialising and de-serialising a DataSet can be easily achieved by using the WriteXml and ReadXml methods of the DataSet class.  Unfortunately, the ReadXml method when used on a large strongly-typed DataSet is S….L…O….W.  (.NET 1.1)  So slow in fact that in a LAN environment it was faster to go to the DB.

After not much research and testing, I decided on the following methods to save and read an encrypted dataset from disk.

public void SaveDataSetToDisk(string cacheFile, DataSet ds, string eKey)
{
    FileStream fsEncrypted = new FileStream(cacheFile, FileMode.Create, FileAccess.Write);
    try
    {
        DESCryptoServiceProvider des = new DESCryptoServiceProvider();
        des.Key = ASCIIEncoding.ASCII.GetBytes(eKey);
        des.IV = ASCIIEncoding.ASCII.GetBytes(eKey);
        CryptoStream cryptostream = new CryptoStream(fsEncrypted, des.CreateEncryptor(), CryptoStreamMode.Write); 
        BinaryFormatter bin = new BinaryFormatter(null,new StreamingContext(StreamingContextStates.File)); 
        using(StreamWriter dat = new StreamWriter(cryptostream))
        {
            bin.Serialize(dat.BaseStream, ds);
            dat.Flush();
            dat.Close();
        }
    }
    finally
    {
        if(fsEncrypted != null)
            fsEncrypted.Close();
    }
}

And then the Reading…

public DataSet ReadDataSetFromDisk(string cacheFile, string eKey)
{
    if(!File.Exists(cacheFile))
        return null;
    FileStream fsEncrypted = new FileStream(cacheFile, FileMode.Open, FileAccess.Read);
    try
    {
        DESCryptoServiceProvider des = new DESCryptoServiceProvider();
        des.Key = ASCIIEncoding.ASCII.GetBytes(eKey);
        des.IV = ASCIIEncoding.ASCII.GetBytes(eKey);
        CryptoStream cryptostream = new CryptoStream(fsEncrypted, des.CreateDecryptor(), CryptoStreamMode.Read); 
        DataSet ds = null;
        BinaryFormatter bin = new BinaryFormatter(null,new StreamingContext(StreamingContextStates.File)); 
        using(StreamReader reader = new StreamReader(cryptostream))
        {
            ds = (DataSet) bin.Deserialize(reader.BaseStream);
            reader.Close();
        }
        return ds;
    }
    finally
    {
        if(fsEncrypted != null)
            fsEncrypted.Close();
    }
}

Any plot holes would be greatly appreciated.

Legacy Comments


Mladen
2006-06-14
re: Reading and Writing an encrypted Dataset to Disk
so i guess that File.Encrypt woulnd't be helpfull?

BTW, cool stuff!

DavidM
2006-06-14
re: Reading and Writing an encrypted Dataset to Disk
That is a .NET 2.0 feature. I don't think it would help anyway as that method is user specific. It's the "conversion" from from file object to DataSet that is the time consuming part..

I am still programming against .NET 1.1.

CCS
2007-03-12
re: Reading and Writing an encrypted Dataset to Disk
It seems like it does not work, may I know what is the valid of Key that I can put?