Home About

January 6th, 2009

Encrypting and Decrypting a C# string - 11

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.

            // The message to encrypt.
            string Msg = "This world is round, not flat, don't believe them!";
            string Password = "secret";
            
            string EncryptedString = EncryptString(Msg, Password);
            string DecryptedString = DecryptString(EncryptedString, Password);

            Console.WriteLine("Message: {0}",Msg);
            Console.WriteLine("Password: {0}",Password);
            Console.WriteLine("Encrypted string: {0}",EncryptedString);
            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.

            // Step 1. We hash the passphrase using MD5
            // We use the MD5 hash generator as the result is a 128 bit byte array
            // which is a valid length for the TripleDES encoder we use below

            MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();
            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).

            // Step 2. Create a new TripleDESCryptoServiceProvider object
            TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider();

            // Step 3. Setup the encoder
            TDESAlgorithm.Key = TDESKey;
            TDESAlgorithm.Mode = CipherMode.ECB;
            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

using System;
using System.Text;
using System.Security.Cryptography;

namespace EncryptStringSample
{
    class MainClass
    {
        
        public static string EncryptString(string Message, string Passphrase)
        {
            byte[] Results;
            System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
            
            // Step 1. We hash the passphrase using MD5
            // We use the MD5 hash generator as the result is a 128 bit byte array
            // which is a valid length for the TripleDES encoder we use below

            MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();
            byte[] TDESKey = HashProvider.ComputeHash(UTF8.GetBytes(Passphrase));

            // Step 2. Create a new TripleDESCryptoServiceProvider object
            TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider();

            // Step 3. Setup the encoder
            TDESAlgorithm.Key = TDESKey;
            TDESAlgorithm.Mode = CipherMode.ECB;
            TDESAlgorithm.Padding = PaddingMode.PKCS7;

            // Step 4. Convert the input string to a byte[]
            byte[] DataToEncrypt = UTF8.GetBytes(Message);

            // Step 5. Attempt to encrypt the string
            try
            {
                ICryptoTransform Encryptor = TDESAlgorithm.CreateEncryptor();
                Results = Encryptor.TransformFinalBlock(DataToEncrypt, 0, DataToEncrypt.Length);
            }
            finally
            {
                // Clear the TripleDes and Hashprovider services of any sensitive information
                TDESAlgorithm.Clear();
                HashProvider.Clear();    
            }

            // Step 6. Return the encrypted string as a base64 encoded string
            return Convert.ToBase64String(Results);
        }

        public static string DecryptString(string Message, string Passphrase)
        {
            byte[] Results;
            System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
            
            // Step 1. We hash the passphrase using MD5
            // We use the MD5 hash generator as the result is a 128 bit byte array
            // which is a valid length for the TripleDES encoder we use below

            MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();
            byte[] TDESKey = HashProvider.ComputeHash(UTF8.GetBytes(Passphrase));

            // Step 2. Create a new TripleDESCryptoServiceProvider object
            TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider();

            // Step 3. Setup the decoder
            TDESAlgorithm.Key = TDESKey;               
            TDESAlgorithm.Mode = CipherMode.ECB;       
            TDESAlgorithm.Padding = PaddingMode.PKCS7;

            // Step 4. Convert the input string to a byte[]
            byte[] DataToDecrypt = Convert.FromBase64String(Message);
                
            // Step 5. Attempt to decrypt the string
            try
            {
                ICryptoTransform Decryptor = TDESAlgorithm.CreateDecryptor();
                Results = Decryptor.TransformFinalBlock(DataToDecrypt, 0, DataToDecrypt.Length);
            }
            finally
            {
                // Clear the TripleDes and Hashprovider services of any sensitive information
                TDESAlgorithm.Clear();
                HashProvider.Clear();    
            }

            // Step 6. Return the decrypted string in UTF8 format
            return UTF8.GetString( Results );
        }
    
        public static void Main(string[] args)
        {
            // The message to encrypt.
            string Msg = "This world is round, not flat, don't believe them!";
            string Password = "secret";
            
            string EncryptedString = EncryptString(Msg, Password);
            string DecryptedString = DecryptString(EncryptedString, Password);

            Console.WriteLine("Message: {0}",Msg);
            Console.WriteLine("Password: {0}",Password);
            Console.WriteLine("Encrypted string: {0}",EncryptedString);
            Console.WriteLine("Decrypted string: {0}",DecryptedString);
        }
    }
}
Be Sociable, Share!

Tags: , , , ,

11 Responses to “Encrypting and Decrypting a C# string”

  1. cliff Says:

    thanks for the encrypt/decrypt lesson. thanks a lot. GOD Bless!

  2. Mike Knowles Says:

    Great example, just what I needed for encrypting a timestamp in a URL parameter. Just to confirm – the rendered string is always UTF-8 and thus safe for inclusion in a link, correct?

  3. Justin Says:

    Just as the last person said, this is an excellent demonstration of how to encrypt and decrypt strings. This one helped me with a fun little program where i wanted to encrypt a credit card number, thanks again!!!

  4. Jon Berenguer Says:

    Thanks for the lesson and source code. While using the above codes I experience some errors decrypting some messages, especially when it contained some spaces. After searching the internets, I found a fix. Apparently when converting from a Base64 string to byte, it does not like the space in the message. I inserted this line of code, in between Step 3 and 4 for the decrypt method:

    Message = Message.Replace(” “, “+”);

    Hope this helps others who experience this issue.

  5. Vance Says:

    Thanks! Good to find simple encryption techniques for stings, as they are useful for keeping cookies private. Many other pages just deal with https instead of manually encrypting strings.

  6. Osama Mortada Says:

    Hi,

    Thanks for this tutorial it’s really good but sometimes I get this error:

    // Step 4. Convert the input string to a byte[]
    byte[] DataToDecrypt = Convert.FromBase64String(Message);

    Invalid length for a Base-64 char array.

    I tried it with this string “wwwrw”
    secret string “jomaih”

    Thank you,

  7. Jon Berenguer Says:

    Thanks for the Post.
    I started to get some errors when the encrypted message had a space character into.

    After doing some research, it seems that the convert part in step 4 of the decryption method does not like spaces.

    Before step 4, I replace the space to a “+”, according to other sources the plus sign is the same as a space and it works perfectly.

    // Step 3. Setup the decoder
    TDESAlgorithm.Key = TDESKey;
    TDESAlgorithm.Mode = CipherMode.ECB;
    TDESAlgorithm.Padding = PaddingMode.PKCS7;

    //Fix for base64 error when message has a space, This is the line of code to add
    Message = Message.Replace(” “, “+”);

    // Step 4. Convert the input string to a byte[]
    byte[] DataToDecrypt = Convert.FromBase64String(Message);

  8. Samir Says:

    Thanks a lot for nice and easy to use functions.

  9. An Says:

    another issue that if message string contain special characters then Error occurs

    Example: message=”ѳ÷YïÁ¡g/”;

    Invalid character in a Base-64 string

    // Step 4. Convert the input string to a byte[]
    byte[] DataToDecrypt = Convert.FromBase64String(Message);

  10. Edson Catugy Says:

    Very useful information!!

  11. bian Says:

    how to get passphase if i have encrypt and decrypt string??
    Thanks alot


Most popular

    Sorry. No data so far.

Recent Comments
  • Juan Romero: Hi there, it’s a neat little class, but I believe you could do the same thing with the WebClient...
  • anthosh: Hey, THank you very much for your tutorial. It was awesome. But i have a problem that i am not able to...
  • bian: how to get passphase if i have encrypt and decrypt string?? Thanks alot
  • Michael: Hi, I really like your post, thanks a lot, it really helped clear up a few things I could not remember how...
  • Bharat Prajapati: i was trying to import keyword dictionary to this plugin which is in csv format, but i get an error...