Sunday 22 June 2008

Silverlight Encryption (Part 3)

In part 1, we showed an application that I built to encrypt/decrypt data. In part 2, we discussed encryption algorithms and key management.

In this final part of the series, having generated a symmetric-key to encrypt/decrypt our data we will now look at encryption / decryption code.

Encryption

The code below is what I used to encrypt the data. The data to be encrypted is passed in, as well as the encryption key (previous article), and it will return the encryped data as a Base64 string.

The important thing to note is that i use the encryption key as both the InitializationVector (IV), and the Key. You will need to do this also for the decryption.

internal static string Encrypt(byte[] key, string dataToEncrypt)
{
// Initialise
AesManaged encryptor = new AesManaged();

// Set the key
encryptor.Key = key;
encryptor.IV = key;

// create a memory stream
using (MemoryStream encryptionStream = new MemoryStream())
{
// Create the crypto stream
using (CryptoStream encrypt = new CryptoStream(encryptionStream, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
// Encrypt
byte[] utfD1 = UTF8Encoding.UTF8.GetBytes(dataToEncrypt);
encrypt.Write(utfD1, 0, utfD1.Length);
encrypt.FlushFinalBlock();
encrypt.Close();

// Return the encrypted data
return Convert.ToBase64String(encryptionStream.ToArray());
}
}
}

Finally if to decrypt (an encrypted base64 string) we use the following method:

internal static string Decrypt(byte[] key, string encryptedString)
{
// Initialise
AesManaged decryptor = new AesManaged();
byte[] encryptedData = Convert.FromBase64String(encryptedString);

// Set the key
decryptor.Key = key;
decryptor.IV = key;

// create a memory stream
using (MemoryStream decryptionStream = new MemoryStream())
{
// Create the crypto stream
using (CryptoStream decrypt = new CryptoStream(decryptionStream, decryptor.CreateDecryptor(), CryptoStreamMode.Write))
{
// Encrypt
decrypt.Write(encryptedData, 0, encryptedData.Length);
decrypt.Flush();
decrypt.Close();

// Return the unencrypted data
byte[] decryptedData = decryptionStream.ToArray();
return UTF8Encoding.UTF8.GetString(decryptedData, 0, decryptedData.Length);
}
}

}

If we passed in the same string that we got back from the encrypt, and run it through the decrypt we will get our original data back.

Again please note that the same key used for encryption is used as the key for decryption (and we again set the Initialization Vector (IV) to the key).

Anyways, I hope you found these series of articles useful, and you can view an online demo here or you can download the source from my skydrive

1 comment:

Anonymous said...

Hi there, thanks a million for your post!

I have used your example but I'm having a problem when the Decrypt method on the webservice side is called twice. The first time it works fine, the second time when calling decrypt.Close() I get System.Security.Cryptography.CryptographicException: Padding is invalid and cannot be removed.

I've had no luck with solutions given in http://forums.msdn.microsoft.com/en-US/netfxbcl/thread/d1788582-bf8c-43ec-a686-49647c359136/

The Silverlight's AES implementation doesn't have the Padding property, so I can't set it to None on both sides.

My code is exactly like yours. Your help would be greatly appreciated!