Encrypting and Decrypting a C# string

The .NET C# library provides all the basic elements for encrypting a string with a passphrase and decrypting it later. Doing this however requires a few steps in between. This post show a simple set of routines to help you do just that. We use the TripleDES encryption suite to do the actual encryption, with a little help from the MD5 hash sum generator.

The complete source code is listed below, but lets have a little look at how it works first.

 

The problem

I want to take a string, and then encrypt it using a password. The result should be a Base64 encoded string that I can store somewhere relatively safe.

01.// The message to encrypt.
02.string Msg = "This world is round, not flat, don't believe them!";
03.string Password = "secret";
04.
05.string EncryptedString = EncryptString(Msg, Password);
06.string DecryptedString = DecryptString(EncryptedString, Password);
07.
08.Console.WriteLine("Message: {0}",Msg);
09.Console.WriteLine("Password: {0}",Password);
10.Console.WriteLine("Encrypted string: {0}",EncryptedString);
11.Console.WriteLine("Decrypted string: {0}",DecryptedString);

In the EncryptString function we apply the TripleDES algorithm with a 128 bit key. But first we need to turn the above passphrase (’secret’) into a 128 bit key. One useful coincidence is that the MD5 hash algorithm accepts a set of bytes of any length and turns them into a 128 bit hash. So by running the password through the MD5 hashing algorithm we create our key.

1.// Step 1. We hash the passphrase using MD5
2.// We use the MD5 hash generator as the result is a 128 bit byte array
3.// which is a valid length for the TripleDES encoder we use below
4.
5.MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();
6.byte[] TDESKey = HashProvider.ComputeHash(UTF8.GetBytes(Passphrase));

The TripleDES algorithm itself turns a byte array into an encrypted byte array. So we first need to convert our C# message string (which is Unicode encoded) into a byte array through the System.Text.UTF8Encoding encoder.

The key is used to initialize the TripleDES algorithm. In addition we need to specify that we will only encode something once (CipherMode.ECB) and because its unlikely that our source string fits into a single TripleDES block we need to specify how we want to pad any remaining bytes (PaddingMode.PKCS7).

1.// Step 2. Create a new TripleDESCryptoServiceProvider object
2.TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider();
3.
4.// Step 3. Setup the encoder
5.TDESAlgorithm.Key = TDESKey;
6.TDESAlgorithm.Mode = CipherMode.ECB;
7.TDESAlgorithm.Padding = PaddingMode.PKCS7;

The encrypted byte array is finally converted into a Base64 encoded string for easy storage. The DecryptString function is very similar to the encryption function, except that it turns the Base64 encoded encrypted message back into the original UTF8 string.

Drawbacks to the above method

To keep the code above straightforward we made use of the fact that an MD5 hash is exactly 128 bits in length. The C# TripleDES code accepts three possible key lengths: 64 bit, 128 bit and 192 bit. Only 192 bit keys are truly TripleDES, the 128 bit key length we obtain from the MD5 hash is only sufficient for Double DES. According to Wikipedia, that would make its real key strength only equivalent to 80 bits.

The Source code

001.using System;
002.using System.Text;
003.using System.Security.Cryptography;
004.
005.namespace EncryptStringSample
006.{
007.class MainClass
008.{
009.
010.public static string EncryptString(string Message, string Passphrase)
011.{
012.byte[] Results;
013.System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
014.
015.// Step 1. We hash the passphrase using MD5
016.// We use the MD5 hash generator as the result is a 128 bit byte array
017.// which is a valid length for the TripleDES encoder we use below
018.
019.MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();
020.byte[] TDESKey = HashProvider.ComputeHash(UTF8.GetBytes(Passphrase));
021.
022.// Step 2. Create a new TripleDESCryptoServiceProvider object
023.TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider();
024.
025.// Step 3. Setup the encoder
026.TDESAlgorithm.Key = TDESKey;
027.TDESAlgorithm.Mode = CipherMode.ECB;
028.TDESAlgorithm.Padding = PaddingMode.PKCS7;
029.
030.// Step 4. Convert the input string to a byte[]
031.byte[] DataToEncrypt = UTF8.GetBytes(Message);
032.
033.// Step 5. Attempt to encrypt the string
034.try
035.{
036.ICryptoTransform Encryptor = TDESAlgorithm.CreateEncryptor();
037.Results = Encryptor.TransformFinalBlock(DataToEncrypt, 0, DataToEncrypt.Length);
038.}
039.finally
040.{
041.// Clear the TripleDes and Hashprovider services of any sensitive information
042.TDESAlgorithm.Clear();
043.HashProvider.Clear();
044.}
045.
046.// Step 6. Return the encrypted string as a base64 encoded string
047.return Convert.ToBase64String(Results);
048.}
049.
050.public static string DecryptString(string Message, string Passphrase)
051.{
052.byte[] Results;
053.System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
054.
055.// Step 1. We hash the passphrase using MD5
056.// We use the MD5 hash generator as the result is a 128 bit byte array
057.// which is a valid length for the TripleDES encoder we use below
058.
059.MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();
060.byte[] TDESKey = HashProvider.ComputeHash(UTF8.GetBytes(Passphrase));
061.
062.// Step 2. Create a new TripleDESCryptoServiceProvider object
063.TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider();
064.
065.// Step 3. Setup the decoder
066.TDESAlgorithm.Key = TDESKey;
067.TDESAlgorithm.Mode = CipherMode.ECB;
068.TDESAlgorithm.Padding = PaddingMode.PKCS7;
069.
070.// Step 4. Convert the input string to a byte[]
071.byte[] DataToDecrypt = Convert.FromBase64String(Message);
072.
073.// Step 5. Attempt to decrypt the string
074.try
075.{
076.ICryptoTransform Decryptor = TDESAlgorithm.CreateDecryptor();
077.Results = Decryptor.TransformFinalBlock(DataToDecrypt, 0, DataToDecrypt.Length);
078.}
079.finally
080.{
081.// Clear the TripleDes and Hashprovider services of any sensitive information
082.TDESAlgorithm.Clear();
083.HashProvider.Clear();
084.}
085.
086.// Step 6. Return the decrypted string in UTF8 format
087.return UTF8.GetString( Results );
088.}
089.
090.public static void Main(string[] args)
091.{
092.// The message to encrypt.
093.string Msg = "This world is round, not flat, don't believe them!";
094.string Password = "secret";
095.
096.string EncryptedString = EncryptString(Msg, Password);
097.string DecryptedString = DecryptString(EncryptedString, Password);
098.
099.Console.WriteLine("Message: {0}",Msg);
100.Console.WriteLine("Password: {0}",Password);
101.Console.WriteLine("Encrypted string: {0}",EncryptedString);
102.Console.WriteLine("Decrypted string: {0}",DecryptedString);
103.}
104.}
105.}

 

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s