Learn to Use the New XML Encryption Class in .NET 2.0

ML is the de-facto language of business transactions. It enables structuring data. And the 2.0 version of the .NET framework, heretofore known by its codename, Whidbey, will finally enable you to encrypt and decrypt XML data. In this article I will explore the implementation of XML encryption in .NET 2.0.

Author’s Note: Throughout this article when I reference .NET I’m referring to .NET Framework 2.0.

Basics of .NET XML Encryption
The first thing to cheer about Microsoft’s implementation of XML encryption is that it’s W3C compliant. What this means to you is that you will be able to exchange data with other implementations with ease. No proprietary nonsense here.

The interesting part is that the implementation supports encryption of arbitrary data i.e. non-XML data. You could encrypt binary data; the input needn’t be XML. However the output/result will be an XML element.

When you’re thinking of encrypting XML data there are two possible scenarios:

  • Encryption of an entire document
  • Encryption of portions of a document

The .NET framework supports both of these scenarios and provides you with multiple types of encryption algorithms:

  • Triple DES
  • AES 128
  • AES 192
  • AES 256
  • RSA
  • X509CertificateEx

XML encryption is driven by the System.Security.Cryptography.Xml.EncryptedXml class.

What You Need
Visual Studio.Net 2005 beta 1 (Whidbey).

Dive into XML Encryption
The XML document, “Order.xml,” below, shows a purchase order:

      .NET Framework Security    Essential XML Quick Reference        Joe Smith    110 Denny Way    Seattle    98109              0000-0000-0000-0000      09/15/80              Microsoft Corporation        1 Microsoft Way        Redmond        98052            

This XML file contains order details, including ordered items, customer data present in the shipping tag, and payment information present in the billing tag (customer credit card information).

In order to encrypt this data or portions of it, you need to follow these steps:

  1. Load the XML document
  2. Create an instance of the encryption algorithm provider
  3. Select the XML element you need to encrypt

  4. Create an EncryptedXML object
  5. Encrypt the element using the key generated by the encryption algorithm object
  6. Create an encrypted data object and specify its properties
  7. Assign the encrypted data to the encrypted data object’s cipher value
  8. Replace the plain text XML element with the encrypted data object
  9. Save the encrypted data to a file (optional)

In order to decrypt data similarly you have to follow these steps:

  1. Load the XML document
  2. Retrieve the encrypted XML element
  3. Create an encrypted data object
  4. Load the encrypted element into the encrypted data object
  5. Create an encrypted XML object
  6. Decrypt the element using the key
  7. Replace the encrypted element with the plain-text XML element
  8. Save the decrypted data to a file (optional)

Encrypting and Decrypting an XML Element
Open up VS.NET 2005 Whidbey, and create a new console project. Add references to the following:

  • System.Security
  • System.XML

Now create a new module called “EncryptDecrypt,” and add the following imports statements:

Imports SystemImports System.Security.CryptographyImports System.Security.Cryptography.XmlImports System.XML

You need to follow the steps below to write code to encrypt a portion of the XML document.

Author’s Note: The Source code for this article includes the final EncryptDecrypt program for your reference.

Encrypting the XML Document

  1. Add a sub main to the module and write code to load the XML document.
  2. 'load the XML Document        Dim xmldoc As New XmlDocument()        Try            xmldoc.Load("order.xml")        Catch ex As Exception            Console.WriteLine(ex.Message)        End Try
  3. Choose an encryption algorithm provider and create an instance. For the sample application I’m using TripleDES.
  4. Dim tDESkey As New TripleDESCryptoServiceProvider()
  5. Select the element (billing) to be encrypted. You need to explicitly cast it to the type XmlElement, as SelectSingleNode returns an XMLNode Type.
  6. Dim billingElem As XmlElement = _CType(xmldoc.SelectSingleNode("/order/billing"), XmlElement)
  7. Create an EncryptedXML object.
  8. Dim exml As EncryptedXml = New EncryptedXml(xmldoc)
  9. Encrypt the billing element. The EncryptedXML object has an EncryptData method, which encrypts the element using the algorithm provided and returns an array of bytes. Here I’ve used the TripleDES algorithm.
  10. Dim encryptedBilling As Byte() = _exml.EncryptData(billingElem, tDESkey, False)
  11. Create an encrypted data object and specify its properties. This encrypted data object represents data that will finally be placed in the XML document. You need to specify properties such as the type of encrypted data and the namespace URI for the algorithm used.
  12. Dim ed As New EncryptedData()' Specify the namespace URI for XML encryption elements.ed.Type = EncryptedXml.XmlEncElementUrl' Specify the namespace URI for the TrippleDES algorithm.ed.EncryptionMethod = _New EncryptionMethod(EncryptedXml.XmlEncTripleDESUrl)' Create a CipherData element.ed.CipherData = New CipherData()
  13. Assign the encrypted data to the encrypted data object’s cipher value.
  14. ed.CipherData.CipherValue = encryptedBilling 
  15. Replace the plain text XML element with the encrypted data object.
  16. EncryptedXml.ReplaceElement(billingElem, ed, False)
  17. Save the encrypted data to file.
  18.             xmldoc.Save("encryptedorder.xml")

You need to build the solution, so don’t run it as yet. Create a file called Orders.xml and populate it as shown in Order.xml (see page 1). Place this file in the bin directory of your solution.

Run the program. When the program has finished running, the “encryptedorder.xml” file will be generated. Then open the file “encryptedorder.xml,” which is shown below, with the billing element encrypted. (Note: You could encrypt the entire file by replacing the element to encrypt, in step 3.)

Editor’s Note: The CipherValue element in the code below should hold a single line of characters, but it’s been wrapped into several lines for this article.
      .NET Framework Security    Essential XML Quick Reference        Joe Smith    110 Denny Way    Seattle    98109                  jmXS8BnRupLdjLndM1wpMaKiuKCUZQt6jyK8pnz0t/iqMQ3eNC8xnIsHXvrLvVVF1hr7      y9WeqM7OzbjZODIJzvPkH/KmsQjA69AIOoIKu4DXYMWXdhYtCojFtoxPpICao0w3GTDhCV2DuZ+Cjn      kV7uDJ5QNTSbsR5q4QbPaYp7uTqAjxX6tAmMZBil2K/I5PUh8TDMf/lsKdk8P21uKZmR+9DBA5gQZ+      MykDFKgaQwa3TkGjf9V+NcpRCjr1I4dI+WkURmNyjXlUAXaai0cdAkBctLi7jK74SGQE+TjLeSKu7gB      fB6lBGolM8CjvpQx0F6WCn8bm6K9oiYpvVvNIYxQfslwwS2OXEDhkOweIs17zpz5MwmzWSQ==            

Understanding the Encrypted XML Document
Any encrypted data in the document is stored in the EncryptedData element. The EncryptionMethod element specifies the kind of encryption used; the CipherValue element contains the encrypted data

Decrypting the XML Document
You need to go through the following steps to decrypt the XML element that you earlier encrypted:

  1. Load the XML document “encryptedorder.xml.” Note that this time around you need to load the encrypted document you generated earlier, not “order.xml.”
  2. Dim encryptedDoc As New XmlDocument()encryptedDoc.Load("encryptedorder.xml")
  3. Retrieve the encrypted XML element by retrieving the EncryptedData tag. The EncryptedData tag is used to store any encrypted data.
  4. Dim encryptedElement As XmlElement = _CType(encryptedDoc.GetElementsByTagName("EncryptedData")(0), _XmlElement)

    Here you need to do a type cast to XmlElement. Because the GetElementsByTagName returns a NodeList, I decided to take the first element by specifying (0).

  5. Create an encrypted data object and
  6. Load the encrypted element into it.
  7. Dim ed2 As New EncryptedData()ed2.LoadXml(encryptedElement)
  8. Create an encrypted XML object.
  9. Dim exml2 As New EncryptedXml()
  10. Decrypt the encrypted data element using the key and calling the DecryptData method of the EncryptedXML object.
  11. Dim decryptedBilling As Byte() = exml2.DecryptData(ed2, tDESkey)
  12. Replace the encrypted element with the plain-text XML element.
  13. exml2.ReplaceData(encryptedElement, decryptedBilling)
  14. Save the decrypted data to a file.
  15. encryptedDoc.Save("DecryptedOrder.xml")

Build the project and run it. You now have three files: the original “Order.xml,” the encrypted “encryptedorder.xml,” and the new “DecryptedOrder.xml” document, which would be created when the program runs.

You’re just encrypted and decrypted a portion of an XML file and at the same time if you desire you could encrypt/decrypt the entire file. The EncryptedXML class makes this extremely easy to do.

Storing the Key
The above example encrypted and decrypted the “order.xml” file in the same module. You might want to store the key used to encrypt the file in a text file that is shared between the sender and the receiver of the encrypted data.

The key generated by the TripleDESCryptoServiceProvider is a byte array. Hence, to store it to a file one would need to convert it to an equivalent string representation (as shown below) first, and then store it to a text file.

Dim sharedkey As New TripleDESCryptoServiceProvider()'sharedkey.GenerateKey()'Save this key to disk to enable the recipient to decryptDim writer2 As IO.StreamWriter =_New IO.StreamWriter("SharedTDESKey.txt")Dim str As String = Convert.ToBase64String(sharedkey.Key)writer2.WriteLine(str)writer2.Close()

While decrypting you would have to similarly retrieve this shared key from the file and then use it as the key to decrypt the XML document. In the source code provided with this article (see left column), I’ve included an example to illustrate this method. There are two separate files: one to encrypt the XML and one to decrypt it.

Advanced Concepts
What we’ve discussed is primarily encrypting and decrypting data with the new EncryptedXML class. If you want to send this data on disk or on the network to another person you would need to provide a means for the other person to decrypt it. In other words, you would need to share the key with the recipient.

In the examples for this article I’ve used symmetric key cryptography. In symmetric cryptography, the encryption algorithm requires the same secret key to be used for both encryption and decryption. (For more information on symmetric and asymmetric cryptography, see “Related Resources,” left column.) Because of the type of key, this is sometimes called secret key encryption. However, in this scheme you have to carefully manage key exchange, that is, the mechanism for safely ensuring both sender and the receiver have the secret key. This is one of the weakest areas of symmetric cryptography.

The solution to this problem is to use asymmetric cryptography, where there are two keys. One key is called the private key and is never revealed, and the other is called the public key and is freely given out to all potential correspondents. A sender uses the receiver’s public key to encrypt the message. Only the receiver has the related private key to decrypt the message. Asymmetric encryption is beyond the scope of this article but is something you should learn about to be able to use encryption in real life scenarios. Check the resources section for further links on this advanced topic.

The new EncryptedXML class, along with the cryptographic API, provides the fundamental blocks to secure XML data. Multiple scenarios are supported whether it’s encrypting part of a document, encrypting an entire document, or similarly decrypting the document. Inclusion of these classes in the standard .NET framework simplifies XML data security.

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Related Posts