Click here to Skip to main content
15,886,017 members
Articles / Programming Languages / C# 4.0
Tip/Trick

How to Use Rijndael ManagedEncryption with C#

Rate me:
Please Sign up or sign in to vote.
4.87/5 (17 votes)
1 Jan 2014CPOL1 min read 184.2K   5.9K   32   33
To encrypt or not to encrypt with C# .NET

Introduction

This example shows you how to use the RijndaelManaged class that is available in .NET since version 1.1.

Using the Code   

Using encryption with .NET is very easy. For this, we use the RijnDaelManaged class. We need to initialize this class by calling <code>NewRijndaelManaged() after the class is created we have to create our secret key by creating a class called Rfc2898DeriveBytes like this Rfc2898DeriveBytes(Inputkey, salt). The constructor on this class needs 2 input parameters, a password and a salt key. In the code below, we use two GUIDs as the pasword and salt key.

When we call the EncryptRijndael(string text) function with the following text "My super secret text", this will result in the following string "sBJUwV7Vo+ou9kYds6HfqFRHLcGf5MLiRUZk8ICt9h8=" to decrypt this string we call the DecryptRijndael(string cipherText) which will give back the original text. To make everything super simple, I wrapped everything up in a simple static class that does all the work (the little that needs to be done).

C#
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;

namespace RijndaelManagedEncryption
{
    public class RijndaelManagedEncryption
    {
        #region Consts
        /// <summary>
        /// Change the Inputkey GUID when you use this code in your own program.
        /// Keep this inputkey very safe and prevent someone from decoding it some way!!
        /// </summary>
        internal const string Inputkey = "560A18CD-6346-4CF0-A2E8-671F9B6B9EA9";
        #endregion

        #region Rijndael Encryption

        /// <summary>
        /// Encrypt the given text and give the byte array back as a BASE64 string
        /// </summary>
        /// <param name="text" />The text to encrypt
        /// <param name="salt" />The pasword salt
        /// <returns>The encrypted text</returns>
        public static string EncryptRijndael(string text, string salt)
        {
            if (string.IsNullOrEmpty(text))
                throw new ArgumentNullException("text");

            var aesAlg = NewRijndaelManaged(salt);

            var encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
            var msEncrypt = new MemoryStream();
            using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
            using (var swEncrypt = new StreamWriter(csEncrypt))
            {
                swEncrypt.Write(text);
            }

            return Convert.ToBase64String(msEncrypt.ToArray());
        }
        #endregion

        #region Rijndael Dycryption
        /// <summary>
        /// Checks if a string is base64 encoded
        /// </summary>
        /// <param name="base64String" />The base64 encoded string
        /// <returns>Base64 encoded stringt</returns>
        public static bool IsBase64String(string base64String)
        {
            base64String = base64String.Trim();
            return (base64String.Length%4 == 0) &&
                   Regex.IsMatch(base64String, @"^[a-zA-Z0-9\+/]*={0,3}$", RegexOptions.None);

        }
        
        /// <summary>
        /// Decrypts the given text
        /// </summary>
        /// <param name="cipherText" />The encrypted BASE64 text
        /// <param name="salt" />The pasword salt
        /// <returns>The decrypted text</returns>
        public static string DecryptRijndael(string cipherText, string salt)
        {
            if (string.IsNullOrEmpty(cipherText))
                throw new ArgumentNullException("cipherText");

            if (!IsBase64String(cipherText))
                throw new Exception("The cipherText input parameter is not base64 encoded");

            string text;

            var aesAlg = NewRijndaelManaged(salt);
            var decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
            var cipher = Convert.FromBase64String(cipherText);

            using (var msDecrypt = new MemoryStream(cipher))
            {
                using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                {
                    using (var srDecrypt = new StreamReader(csDecrypt))
                    {
                        text = srDecrypt.ReadToEnd();
                    }
                }
            }
            return text;
        }
        #endregion

        #region NewRijndaelManaged
        /// <summary>
        /// Create a new RijndaelManaged class and initialize it
        /// </summary>
        /// <param name="salt" />The pasword salt
        /// <returns></returns>
        private static RijndaelManaged NewRijndaelManaged(string salt)
        {
            if (salt == null) throw new ArgumentNullException("salt");
            var saltBytes = Encoding.ASCII.GetBytes(salt);
            var key = new Rfc2898DeriveBytes(Inputkey, saltBytes);

            var aesAlg = new RijndaelManaged();
            aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);
            aesAlg.IV = key.GetBytes(aesAlg.BlockSize / 8);

            return aesAlg;
        }
        #endregion
    }
}

To test the above class, I added an example program that looks like this:

Image 1  

History

  • 2013-12-31 - First version
  • 2013-01-02 - Version 1.1, changed the code so a random generated salt could be used

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Netherlands Netherlands
Programming since I was a kid. Started on the Commodore 64 with BASIC. Since then I used programming languages like Turbo Pascal, Delphi, C++ and Visual Basic 6.

Now a days I do a lot of programming in C# with underlying databases like MS SQL

Comments and Discussions

 
GeneralRe: By far the best (and flawless) Rijndael Managed implementation I've seen. Pin
Kees van Spelde16-Jan-15 7:38
professionalKees van Spelde16-Jan-15 7:38 
QuestionMessage Closed Pin
3-Apr-14 0:39
sunayv3-Apr-14 0:39 
AnswerRe: Hard coded keys annoys me! Pin
Kees van Spelde3-Apr-14 1:41
professionalKees van Spelde3-Apr-14 1:41 
QuestionBase64 string? Pin
charles henington5-Jan-14 7:55
charles henington5-Jan-14 7:55 
AnswerRe: Base64 string? Pin
Kees van Spelde5-Jan-14 21:09
professionalKees van Spelde5-Jan-14 21:09 
GeneralRe: Base64 string? Pin
charles henington10-Jan-14 13:26
charles henington10-Jan-14 13:26 
GeneralRe: Base64 string? Pin
Kees van Spelde13-Jan-14 6:42
professionalKees van Spelde13-Jan-14 6:42 
GeneralRe: Base64 string? Pin
charles henington17-Jan-14 17:09
charles henington17-Jan-14 17:09 
I must Disagree, When writing a text file we are still writing bytes to the file as the System.Char and System.Int16 aka
Objective-C
short
as the short and <code>char can be cast as one another making them inner-changable so to say and using a BinaryWriter but we really don't even need this unless special occasion or even as a preferred method which i for one prefer. but back to <code>char and short a collection of char or <code>short values can be cast as a string(although the short[] would need to be converted to a char[]) which is quite simple.
but in the simplest form of writing bytes and text(string bytes) to file there both just as simple since System.IO gives us System.IO.File.WriteAllBytes(<code>string path, <code><code>byte[] bytes) and <code><code>System.IO.File.WriteAllText(string path, string contents). There's no reason to reinvent a wheel that's already been invented .Net is a very complex yet rewarding language and it's really a matter of preference as i have already stated earlier but by writing our bytes directly to file we don't receive an error during conversion if the value being passed in is not a text file or the file being passed in is a text file but the contents are not base64. In my honest opinion the base64 string in a file(except *.html) looks lazy, but again is only my opinion.
a quick example
C#
public static void Encrypt(string srcPath, string destPath,  string password)
        {
            byte[] read = System.IO.File.ReadAllBytes(srcPath);
            System.Security.Cryptography.RijndaelManaged rindaelManaged =
                (System.Security.Cryptography.RijndaelManaged)System.Security.Cryptography.RijndaelManaged.Create();
            using(System.Security.Cryptography.PasswordDeriveBytes passwordDeriveBytes =
                new System.Security.Cryptography.PasswordDeriveBytes(
                password, System.Text.Encoding.ASCII.GetBytes(password)))
            {
                rindaelManaged.IV = passwordDeriveBytes.GetBytes(16);
                rindaelManaged.Key = passwordDeriveBytes.GetBytes(32);
            }
            using(System.IO.MemoryStream memoryStream = new System.IO.MemoryStream())
            {
                using(System.Security.Cryptography.CryptoStream cryptoStream =
                    new System.Security.Cryptography.CryptoStream(memoryStream,rindaelManaged.CreateEncryptor(), 
System.Security.Cryptography.CryptoStreamMode.Write))
                {
                    cryptoStream.Write(read, 0, read.Length);
                }
                byte[] bytes = memoryStream.ToArray();
                System.IO.File.WriteAllBytes(destPath, bytes);
            }
        }

GeneralRe: Base64 string? Pin
Kees van Spelde17-Jan-14 19:29
professionalKees van Spelde17-Jan-14 19:29 
QuestionA couple of things Pin
Garth J Lancaster31-Dec-13 11:17
professionalGarth J Lancaster31-Dec-13 11:17 
AnswerRe: A couple of things Pin
Kees van Spelde31-Dec-13 19:45
professionalKees van Spelde31-Dec-13 19:45 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.