Encryption in Silverlight and .NET Applications

Today I would like to cover a specific use case that came up a few times in Silverlight applications I wrote.  For example, I wand a user to enter some sensitive information, encrypt it in Silverlight client, transfer it over to the server, then decrypt it and perforation some operations on that data.

First step of course is to find sufficiently strong encryption protocol that can be implemented in both Silverlight and .NET and be completely compatible between both run times.  I am going to go for AES encryption.  AES stands for “Advanced Encryption Standard”.  This standard is widely used and approved by US government and standard bodies.  See this article for details.

Luckily, AES encryption is implemented in both Silverlight and .NET run times, using exact same set of classes, primary one being AesManaged class.  My goal is to create a class that I can cross-compile in both runt times, so this comes in super handy.  Second, I wand to implement two methods Decrypt and Encrypt, while paying attention to IDisposable interfaces that the vast majority of classes inside Cryptography namespace implement.  Both static methods take two parameters, input string and a password to be used.  Of course, you have to make sure you use the same password in both methods while encrypting and decrypting information.  You should probably dynamically generate a password during handshake process between a Silverlight client and a .NET server.  I will also use maximum key size and block size of encryption.  I will also dynamically generate key (Key) and initialization vector(IV) properties.    I am going to now spare everyone a number of boring details, and will simply post final version of my utility class:  You can include this class in both .NET and Silverlight project, and even link the physical .cs file from one to the other to ensure that you only have a single version in source control.

Thanks

using System;
using System.Text;
using System.Security.Cryptography;
using System.IO;
 
namespace Encryption
{
    public static class EncryptionUtility
    {
 
        /// <summary>
        /// Encrypt the data
        /// </summary>
        /// <param name="input">String to encrypt</param>
        /// <returns>Encrypted string</returns>
        public static string Encrypt(string input, string password)
        {
 
            byte[] utfData = UTF8Encoding.UTF8.GetBytes(input);
            byte[] saltBytes = Encoding.UTF8.GetBytes(password);
            string encryptedString = string.Empty;
            using (AesManaged aes = new AesManaged())
            {
                Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(password, saltBytes);
 
                aes.BlockSize = aes.LegalBlockSizes[0].MaxSize;
                aes.KeySize = aes.LegalKeySizes[0].MaxSize;
                aes.Key = rfc.GetBytes(aes.KeySize / 8);
                aes.IV = rfc.GetBytes(aes.BlockSize / 8);
 
                using (ICryptoTransform encryptTransform = aes.CreateEncryptor())
                {
                    using (MemoryStream encryptedStream = new MemoryStream())
                    {
                        using (CryptoStream encryptor = 
                            new CryptoStream(encryptedStream, encryptTransform, CryptoStreamMode.Write))
                        {
                            encryptor.Write(utfData, 0, utfData.Length);
                            encryptor.Flush();
                            encryptor.Close();
 
                            byte[] encryptBytes = encryptedStream.ToArray();
                            encryptedString = Convert.ToBase64String(encryptBytes);
                        }
                    }
                }
            }
            return encryptedString;
        }
 
        /// <summary>
        /// Decrypt a string
        /// </summary>
        /// <param name="input">Input string in base 64 format</param>
        /// <returns>Decrypted string</returns>
        public static string Decrypt(string input, string password)
        {
 
            byte[] encryptedBytes = Convert.FromBase64String(input);
            byte[] saltBytes = Encoding.UTF8.GetBytes(password);
            string decryptedString = string.Empty;
            using (var aes = new AesManaged())
            {
                Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(password, saltBytes);
                aes.BlockSize = aes.LegalBlockSizes[0].MaxSize;
                aes.KeySize = aes.LegalKeySizes[0].MaxSize;
                aes.Key = rfc.GetBytes(aes.KeySize / 8);
                aes.IV = rfc.GetBytes(aes.BlockSize / 8);
 
                using (ICryptoTransform decryptTransform = aes.CreateDecryptor())
                {
                    using (MemoryStream decryptedStream = new MemoryStream())
                    {
                        CryptoStream decryptor = 
                            new CryptoStream(decryptedStream, decryptTransform, CryptoStreamMode.Write);
                        decryptor.Write(encryptedBytes, 0, encryptedBytes.Length);
                        decryptor.Flush();
                        decryptor.Close();
 
                        byte[] decryptBytes = decryptedStream.ToArray();
                        decryptedString = 
                            UTF8Encoding.UTF8.GetString(decryptBytes, 0, decryptBytes.Length);
                    }
                }
            }
 
            return decryptedString;
        }
    }
}