Encryption and Decryption in .NET

Not all information should be carelessly thrown about the internet.  Bits of information can be re-created easily .  So, what if we don't want the world to have access? Time to put on our cryptographer hats!  Here are some things I learned about encrypting and decrypting plain-text in .NET.  

To summarize briefly... encryption (aka the "cipher" process) involves moving or shifting bytes around in a specific algorithm so as to make the original meaning unknown.  Decryption uses the same algorithm to re-create the original text.

Security Standards

Many examples for .NET security use a special .NET class called Rijndael.  What a strange name, and what is it exactly? Well, it is the cipher behind the current Advanced Encryption Standard (AES).  The name is simply a combination of the names of the two cryptographers who created it, Vincent Rijmen and Joan Daemen.

"The AES cipher is specified as a number of repetitions of transformation rounds that convert the input plaintext into the final output of ciphertext"... and it is approved for "top secret" information.

Rijndael is a symmetric key algorithm, meaning the same "key" is used to create and decipher the information.

Rijndael in .NET

The .NET framework has its own implementation of Rijndael and it is found in the System.Security.Cryptography namespace.  MSDN page on Rijndael Managed. The class has to methods which create encryption and decryption classes... CreateEncryptor() and CreateDecryptor().  These must be called with the proper key and initialization vector (IV).

Here is sample code for Encryption...

            RijndaelManaged aesAlg = null;
            try
            {
                aesAlg = new RijndaelManaged();
                aesAlg.BlockSize = 128;         // 128 (for AES), 192 and 256 (Rijndael only), default = 128
                aesAlg.Padding = PaddingMode.PKCS7;
                aesAlg.KeySize = keySize;       // 128, 192, or 256; Key size must be set BEFORE actual Key
                aesAlg.Key = key;               // Secret Key
                aesAlg.IV = iv;                 // Initialization Vector (bit length must match BlockSize)

                // create a decryptor
                ICryptoTransform decryptor = aesAlg.CreateDecryptor(key, iv);

                // create streams used for encryption
                using (MemoryStream msDecrypt = new MemoryStream(cipherText))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (BinaryReader rdr = new BinaryReader(csDecrypt))
                        {
                            result = rdr.ReadBytes(cipherText.Length);
                        }
                    }
                }
            }
            finally
            {
                if (aesAlg != null)
                    aesAlg.Dispose();
            }

I have hard-coded some values for clarity. The BlockSize defaults to 128 bits. Rijndael does support sizes of 192 or 256, but these are not included in the actual AES standard as mentioned here.

The padding mode determines how extra bits are filled in, and the library's default is PKCS7

The KeySize can be set to 128, 192, or 256 bits, and it must be set BEFORE you set the Key

The Initialization Vector (IV) is a random string which must be the same length (in bits) as the BlockSize

A Unique Key

In order to create a unique key to pass to the CreateEncryptor and CreateDecryptor methods, you can use the PasswordDeriveBytes class. This class will generate a unique key based on a password and salt. This is done through its CryptDeriveKey method. But this method requires the name of the cryptography algorithm.

If the CryptDeriveKey method does not work for you, such as the case with Rijndael, you can use the GetBytes method instead.

                PasswordDeriveBytes pdb = new PasswordDeriveBytes(pwdBytes, saltBytes, hashType, iterations);

                // For other encryption algorithms, pdb.CryptDeriveKey() is preferred instead of GetBytes(length), 
                // but I could not get this to work with Rijndael

                // Use the password to generate pseudo-random bytes for the encryption
                // key. Specify the size of the key in bytes (instead of bits).
                result = pdb.GetBytes(keyLength / 8);

Here is a link to a sample Visual Studio 2010 windows form project. Unzip, open in VS 2010 and hit F5.

BasicEncryption.zip (66.20 kb)

Tags:

 

SQL Server Sample Databases

On occasion, I have downloaded a sample project for Visual Studio which requires a reference to a sample database.  Of course, I never have that database installed, so I have to go on a hunt to find the database creation files.

The two most common samples I come across are the Northwind database (old sample for Sql Server 200) and the AdventureWorks database (sample for Sql Server 2008). If you need to install one of these sample db's, you can find them all on this CodePlex project...

Microsoft SqlServer Community Projects and Product Samples (databases and sample projects)

and

Microsoft SqlServer Database Product Samples (just the databases)

Tags: