Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Mobile

Don't touch my log, how to protect your XML data with Xml-DSig

4.44/5 (10 votes)
1 Aug 20054 min read 1   608  
Shows a simple class for digital signature generation and verificacion.

Introduction

Recently one of our costumers wanted us to protect a log file from being tampered. The requirement was to maintain a log file of the main activities done by the user inside the system. For different reasons, no database was allowed, so we had to make this log using plain files. Some of the fields needed to be encrypted, and a check mechanism was required to assure that no data was altered.

Well, we built our application and mapped the log file to an XML DataSet. We defined an XML Schema File (XDS) for the log file. This allowed us to use a Typed DataSet, and the program worked as if a database existed. .NET Typed DataSets in conjunction with XML and XSD are a good combination. For example, with these we could use our Grid components.

Integrity of data

This article shows how we solved the anti tampering of the log file. We have XML data, an XSD and classes in C# generated by Visual Studio from XSD. These classes allowed us to read/write the log file. For integrity check, we decided to use digital signatures. The standards for digital signatures are defined by W3C and IETF, you can read all about this standard in this link.

A class for Xml-DSig

XmlSigner is a class that implements two methods:

C#
public static void SignXml (string fileName);
 
public static bool CheckSignXml (string fileName)

Both the methods receive a fileName. SignXml aggregates a Digital Signature Block at the bottom of the file, this block element is called Signature. CheckSignXml looks into the file specified and returns true if the signature is correct. You can download the full implementation and adapt it for your use.

Key management

We use public-private key pairs for signature generation. In this class, the signature is stored in the machine storage. This is done by the private internal method GenCsp. The code for the method is given below:

C#
private static  RSACryptoServiceProvider GenCsp()
  {
   CspParameters cp = new CspParameters();
   cp.KeyContainerName = keyStorage;
   cp.Flags = CspProviderFlags.UseMachineKeyStore;
   cp.KeyNumber = 2;
   return new RSACryptoServiceProvider(cp);
  }

keyStorage is a private string variable that defines the name of the storage for the keys, it's accessible through a static property named KeyStorage. This code assumes that the check will be made in the same machine over and over again. If you want to use other storages you can export the public key and sign with this, and check with the private key, perhaps in a future modification I will show you how to do this.

Usage

We use the XmlSigner class with our Typed Dataset in this way:

C#
MyTypedDataSet myDataset;
 
void SaveData()
{
  myDataset.WriteXml(logFileName);
  XmlSigner.SignXml(logFileName);
}
 

void LoadData()
{
   if (XmlSigner.CheckSignXml(logFileName))
      throw new Exception("Bad Digital Signature, 
                               file was tampered");
   myDataset.ReadXml(logFileName);
}

Problems

This class suffers from the following problems:

  1. Uses files on disk, so somebody can take the files before signing (in a very paranoiac scenario this can be done using System.IO.FileSystemWatcher.
  2. The keys are stored in the machine storage, suppose you want access the file across a LAN, you need an outside key, perhaps in a smartcard or a certificate.

Extensions

I will extend the class to sign XmlDocuments and DataSets.

Encrypting XML elements

This article is a good starting point; in fact this article inspired and guided me to cryptography with C#. Using the class EncDec, described in that article, you can make cryptography of elements. Remember, we where signing a Typed DataSet. In this case a Typed DataRow is generated from the original XSD, so an alternative is to modify the gets and sets of the Typed DataRow fields. Of course, if you modify your XSD, then you could lose your code. The code here shows how I solved changing my get and set of the fields I wanted to encrypt:

C#
public string Id {
    get {
        try {
            return EncDec.Decrypt(
                ((string)(this[this.tableMyTable.IdColumn]), 
                                               "my password");
        }
        catch (InvalidCastException e) {
            throw new StrongTypingException("Cannot get " + 
                            "value because it is DBNull.", e);
        }
    }
    set {
        this[this.tableVerificacion.IdColumn] = 
          EncDec.Encrypt(((string)(this[this.tableMyTable.IdColumn]), 
                                                       "my password");
    }
}

If you are generating your data via XmlSerialization, you can use the same approach. If you are using DOM, then it's more difficult, but feasible.

Other encryption tools

Here, you can find the XML Security API, in both C++ and Java. I will write a wrapper for use in C# shortly, so stay tuned....

Conclusion

The Signature Element added to the data doesn't interfere with its content, and all the mechanism of Typed Dataset works without any problems. When sensitive data is stored in a file, and you don't want this data to be altered the best alternative is to use Digital Signatures. In this article we used XML Digital Signatures because we needed to use XML DataSet, and in this case this was the best alternative.

Source code

If you don't want to download the code, read it and analyze it, I'll keep a printable copy in my blog.

History

  • 3rd Aug, 2005

    We added some tips for element encryption. We also identified the problems of the current implementation.

  • 6thAug, 2005

    Added a reference to "Welcome to XML Security".

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here