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;
        }
    }
}

8 Comments

  1. Thanks for this, just what I was after, though needed it in VB:

    Imports System.Text
    Imports System.IO
    Imports System.Security.Cryptography

    Public Class Encryption

    Public Shared Function Encrypt(ByVal decryptedString As String, ByVal password As String) As String
    Dim encryptedString As String = String.Empty

    Dim decryptedBytes As Byte() = UTF8Encoding.UTF8.GetBytes(decryptedString)
    Dim saltBytes As Byte() = Encoding.UTF8.GetBytes(password)

    Using aes As New AesManaged()
    Dim rfc As New Rfc2898DeriveBytes(password, saltBytes)

    aes.BlockSize = aes.LegalBlockSizes(0).MaxSize
    aes.KeySize = aes.LegalKeySizes(0).MaxSize
    aes.Key = rfc.GetBytes(CInt(aes.KeySize / 8))
    aes.IV = rfc.GetBytes(CInt(aes.BlockSize / 8))

    Using encryptTransform As ICryptoTransform = aes.CreateEncryptor()
    Using encryptedStream As New MemoryStream()
    Using encryptor As New CryptoStream(encryptedStream, encryptTransform, CryptoStreamMode.Write)
    encryptor.Write(decryptedBytes, 0, decryptedBytes.Length)
    encryptor.Flush()
    encryptor.Close()

    Dim encryptedBytes() As Byte = encryptedStream.ToArray()
    encryptedString = Convert.ToBase64String(encryptedBytes)
    End Using
    End Using
    End Using

    End Using

    Return encryptedString
    End Function

    Public Shared Function Decrypt(ByVal encryptedString As String, ByVal password As String) As String
    Dim decryptedString As String = String.Empty

    Dim encryptedBytes() As Byte = Convert.FromBase64String(encryptedString)
    Dim saltBytes As Byte() = Encoding.UTF8.GetBytes(password)

    Using aes As New AesManaged()
    Dim rfc As New Rfc2898DeriveBytes(password, saltBytes)

    aes.BlockSize = aes.LegalBlockSizes(0).MaxSize
    aes.KeySize = aes.LegalKeySizes(0).MaxSize
    aes.Key = rfc.GetBytes(CInt(aes.KeySize / 8))
    aes.IV = rfc.GetBytes(CInt(aes.BlockSize / 8))

    Using decryptTransform As ICryptoTransform = aes.CreateDecryptor()
    Using decryptedStream As New MemoryStream()
    Using decryptor As New CryptoStream(decryptedStream, decryptTransform, CryptoStreamMode.Write)
    decryptor.Write(encryptedBytes, 0, encryptedBytes.Length)
    decryptor.Flush()
    decryptor.Close()

    Dim decryptedBytes() As Byte = decryptedStream.ToArray()
    decryptedString = Convert.ToBase64String(decryptedBytes)
    End Using
    End Using
    End Using

    End Using

    Return decryptedString
    End Function

    End Class

  2. Thank you for the code.

    I have aproblem with it, I send am encripted string with your code form a silverlight App, an recive it in a windows service, but alwais have te same error about Padding:

    “Padding is invalid and can not be removed”.

    This error jump in decryptor.Close()

    Do you have an idea about How can I resolve the problem?.

    Thanks

    mge – Spain —

  3. Pingback: SQL Azure, Entity Framework and HIPAA | Sergey Barskiy's Blog

Leave a Reply to Ric Hardacre Cancel reply

Your email address will not be published. Required fields are marked *