XML Encryption and the .NET Cryptography Classes
The XML Encryption candidate recommendation by the W3C group specifies how XML data can be encrypted. This specification allows for encrypting arbitrary XML data through a variety of standard encryption algorithms, such as AES or Triple DES. (You can find the complete specification at the W3C site.)
Because the specification is so new, the .NET framework does not yet have native support for XML encryption. However, you can use .NET to encrypt individual XML element values with little coding effort, because the framework contains built-in classes that implement most standard cryptography algorithms.
The sample code in this article encrypts user credentials with the TripleDESCryptoServiceProvider class, which implements the Triple DES symmetric encryption algorithm. This algorithm assumes both the sender and receiver share a secret key and an initialization vector. I'm assuming you have control of both your client and server code, so the samples in this article hard-code a secret key into a utility assembly, and they include the assembly in both server and client programs.
When transmitting encrypted information with SOAP, you should use either hexadecimal or base64 encoding, because the original data is in binary format. The sample code uses base64 encoding to transmit an encrypted stream (see Listing 1).
Listing 1: Encrypting a String and Encoding into Base64 Format
public static String Encrypt(String val)
{
TripleDESCryptoServiceProvider tdes =
new TripleDESCryptoServiceProvider();
//Get an array of bytes in UTF8 format
//corresponding to the input string
byte[] toEncrypt =
Encoding.UTF8.GetBytes(val);
//Encrypt the byte array to memory using a
//secret key
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms,
tdes.CreateEncryptor( sharedkey,
sharedvector ),
CryptoStreamMode.Write);
cs.Write(toEncrypt, 0, toEncrypt.Length);
cs.FlushFinalBlock();
//Convert the memory stream to a base64 string
return Convert.ToBase64String(ms.ToArray());
}
All of the .Net cryptographic encryption classes operate on the CryptoStream class, which in turn operates on another base Stream class and an Encryptor or Decryptor object. The code in Listing 1 creates a memory stream class to seed the CryptoStream class and then calls the Write method with an input byte array. The .Net Encoding class takes care of converting strings into byte arrays, and the Convert class transforms a byte array into a base64-encoded string.
Decryption is a similar process that calls the CreateDecryptor method of the cryptographic service provider instead of the CreateEncryptor (see Listing 2).
Listing 2: Encrypting a String and Encoding into Base64 Format
public static String Decrypt(String val)
{
TripleDESCryptoServiceProvider tdes = new
TripleDESCryptoServiceProvider();
byte[] toDecrypt =
Convert.FromBase64String(val);
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms,
tdes.CreateDecryptor( sharedkey,
sharedvector ),
CryptoStreamMode.Write);
cs.Write(toDecrypt, 0, toDecrypt.Length);
cs.FlushFinalBlock();
return Encoding.UTF8.GetString(ms.ToArray());
}