Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Encrypt/Decrypt File or String

3.04/5 (13 votes)
27 Sep 2007CPOL2 min read 1   6K  
This article describes the encrypt/decrypt of any type of file or any string value (like data from textbox) using the secret key (password). Here I have used RijndaelManaged class for encryption/decryption.
Snapshot for text encryption/decryption using the secret key

Screenshot - EncDec_string.jpg

Snapshot for file encryption using the secret key

Screenshot - EncryptFile.jpg

Snapshot for decryption using the secret key

Screenshot - DecryptFile.jpg

Introduction

I found a lot of articles in many sites, even many articles on CodeProject itself. An article Encrypt <--> Decrypt Data with C# written by Syed Moshiur Murshed is based on MD5CryptoServiceProvider class and it describes the encrypting/decrypting of text. I did nothing special. I was working on custom functoid for BizTalk Server 2006. Then I came across the problem with encryption of string and got the solution in this way.

Cryptography Classes

We have a number of cryptography classes which are used to encrypt and decrypt the data under the using System.Security.Cryptography namespace, e.g. DESCryptoServiceProvider class, DSACryptoServiceProvider, MD5CryptoServiceProvider, RNGCryptoServiceProvider, RSACryptoServiceProvider, SHA1CryptoServiceProvider, TripleDESCryptoServiceProvider blah! blah! Each has its own algorithm. So there are many ways to encrypt/decrypt data by using any of the cryptography classes. To know more about cryptography, click here.

Using the Code

In this sample project, I have two types of encryption/decryption:

  1. Encryption/decryption of string using secret key
  2. Encryption/decryption of file using secret key

The code itself is self descriptive. There is nothing special which needs to be explained.

Overview

This is the simple example of encrypting/decrypting of any kind of file, data or string object. you can customize it in your own way. Here I have used the Transform() method. It works in two different ways:

  1. If you want to encrypt/decrypt a small size of string, data, or files then in this case you can pass byte array as input. So before calling this method, you will have to convert input object into byte array.
  2. If you want to encrypt/decrypt any big file like avi, Word document, mpg file, then you will have to pass input as null, but you have to specify an input and output file name with complete path.
C#
/*****************************************************************
* Transform one form to anoter based on CryptoTransform
* It is used to encrypt to decrypt as well as decrypt to encrypt
* Parameters:  input <byte /> - which needs to be transform 
*              transformType - encrypt/decrypt transform
* 
* Return Val:  byte array - transformed value.
***************************************************************/
private byte[] Transform(byte[] input, TransformType transformType)
{
    CryptoStream cryptoStream = null;      	// Stream used to encrypt
    RijndaelManaged rijndael = null;        // Rijndael provider
    ICryptoTransform rijndaelTransform = null;// Encrypting object            
    FileStream fsIn = null;                	//input file
    FileStream fsOut = null;               	//output file
    MemoryStream memStream = null;         	// Stream to contain data
    try
    {
        // Create the crypto objects
        rijndael = new RijndaelManaged();
        rijndael.Key = this._Key;
        rijndael.IV = this._IV;
        if (transformType == TransformType.ENCRYPT)
        {
            rijndaelTransform = rijndael.CreateEncryptor();
        }
        else
        {
            rijndaelTransform = rijndael.CreateDecryptor();
        }

        if ((input != null) && (input.Length > 0))
        {
            memStream = new MemoryStream();
            cryptoStream = new CryptoStream(
                memStream, rijndaelTransform, CryptoStreamMode.Write);

                cryptoStream.Write(input, 0, input.Length);

                cryptoStream.FlushFinalBlock();

                return memStream.ToArray();
        }
        else if ((_inputFile.Length > 0) && (_outputFile.Length > 0))
        {
            // First we are going to open the file streams 
            fsIn = new FileStream(_inputFile,
                FileMode.Open, FileAccess.Read);
            fsOut = new FileStream(_outputFile,
                FileMode.OpenOrCreate, FileAccess.Write);

            cryptoStream = new CryptoStream(
                fsOut, rijndaelTransform, CryptoStreamMode.Write);

            // Now will initialize a buffer and will be 
            // processing the input file in chunks. 
            // This is done to avoid reading the whole file (which can be
            // huge) into memory. 
            int bufferLen = 4096;
            byte[] buffer = new byte<bufferlen />;
            int bytesRead;
            do
            {
                // read a chunk of data from the input file 
                bytesRead = fsIn.Read(buffer, 0, bufferLen);
                // Encrypt it 
                cryptoStream.Write(buffer, 0, bytesRead);
            } 
            while (bytesRead != 0);

            cryptoStream.FlushFinalBlock();
        }
        return null;
    }
    catch (CryptographicException)
    {
        throw new CryptographicException(
            "Password is invalid. Please verify once again.");
    }
    finally
    {
        if (rijndael != null) rijndael.Clear();
        if (rijndaelTransform != null) rijndaelTransform.Dispose();
        if (cryptoStream != null) cryptoStream.Close();
        if (memStream != null) memStream.Close();
        if (fsOut != null) fsOut.Close();
        if (fsIn != null) fsIn.Close();
    }
}

Here you can see the complete class with name EncryptDecrypt.cs. See the code below:

C#
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
/*********************************************
 * Created by Virendra on 13-Sep-2007
 * mail id: virendra.chandra@gmail.com
 *********************************************/
namespace EncryptDecrypt
{
    public class MyEncryptor
    {
        // Internal value of the phrase used to generate the secret key
        private string _Phrase = "";
        //contains input file path and name
        private string _inputFile = "";
        //contains output file path and name
        private string _outputFile = "";
        enum TransformType { ENCRYPT = 0, DECRYPT = 1 }

        /// <value>Set the phrase used to generate the secret key.</value>
        public string Phrase
        {
            set
            {
                this._Phrase = value;
                this.GenerateKey(this._Phrase);
            }
        }

        // Internal initialization vector value to 
        // encrypt/decrypt the first block
        private byte[] _IV;

        // Internal secret key value
        private byte[] _Key;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="SecretPhrase">Secret phrase to generate key</param>
        public MyEncryptor(string SecretPhrase)
        {
            this.Phrase = SecretPhrase;
        }

        /// <summary>
        /// Encrypt the given value with the Rijndael algorithm.
        /// </summary>
        /// <param name="EncryptValue">Value to encrypt</param>
        /// <returns>Encrypted value. </returns>
        public string Encrypt(string EncryptValue)
        {
            try
            {
                if (EncryptValue.Length > 0)
                {
                    // Write the encrypted value into memory
                    byte[] input = Encoding.UTF8.GetBytes(EncryptValue);

                    // Retrieve the encrypted value and return it
                    return (Convert.ToBase64String(Transform(input, 
                        TransformType.ENCRYPT)));
                }
                else
                {
                    return "";
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Decrypt the given value with the Rijndael algorithm.
        /// </summary>
        /// <param name="DecryptValue">Value to decrypt</param>
        /// <returns>Decrypted value. </returns>
        public string Decrypt(string DecryptValue)
        {

            try
            {
                if (DecryptValue.Length > 0)
                {
                    // Write the encrypted value into memory                    
                    byte[] input = Convert.FromBase64String(DecryptValue);

                    // Retrieve the decrypted value and return it
                    return (Encoding.UTF8.GetString(Transform(input, 
                        TransformType.DECRYPT)));
                }
                else
                {
                    return "";
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Encrypt the given value with the Rijndael algorithm.
        /// </summary>
        /// <param name="EncryptValue">Value to encrypt</param>
        /// <returns>Encrypted value. </returns>
        public void Encrypt(string InputFile, string OutputFile)
        {
            try
            {
                if ((InputFile != null) && (InputFile.Length > 0))
                {
                    _inputFile = InputFile;
                }
                if ((OutputFile != null) && (OutputFile.Length > 0))
                {
                    _outputFile = OutputFile;
                }
                Transform(null, TransformType.ENCRYPT);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Decrypt the given value with the Rijndael algorithm.
        /// </summary>
        /// <param name="DecryptValue">Value to decrypt</param>
        /// <returns>Decrypted value. </returns>
        public void Decrypt(string InputFile, string OutputFile)
        {
            try
            {
                if ((InputFile != null) && (InputFile.Length > 0))
                {
                    _inputFile = InputFile;
                }
                if ((OutputFile != null) && (OutputFile.Length > 0))
                {
                    _outputFile = OutputFile;
                }
                Transform(null, TransformType.DECRYPT);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /*****************************************************************
         * Generate an encryption key based on the given phrase.  The 
         * phrase is hashed to create a unique 32 character (256-bit) 
         * value, of which 24 characters (192 bit) are used for the
         * key and the remaining 8 are used for the initialization 
         * vector (IV).
         * 
         * Parameters:  SecretPhrase - phrase to generate the key and 
         * IV from.
         * 
         * Return Val:  None  
         ***************************************************************/
        private void GenerateKey(string SecretPhrase)
        {
            // Initialize internal values
            this._Key = new byte[24];
            this._IV = new byte[16];

            // Perform a hash operation using the phrase.  This will 
            // generate a unique 32 character value to be used as the key.
            byte[] bytePhrase = Encoding.ASCII.GetBytes(SecretPhrase);
            SHA384Managed sha384 = new SHA384Managed();
            sha384.ComputeHash(bytePhrase);
            byte[] result = sha384.Hash;

            // Transfer the first 24 characters of the hashed value to the key
            // and the remaining 8 characters to the initialization vector.
            for (int loop = 0; 
                loop < 24; loop++) this._Key[loop] = result[loop];
            for (int loop = 24; 
                loop < 40; loop++) this._IV[loop - 24] = result[loop];
        }

        /*****************************************************************
         * Transform one form to anoter based on CryptoTransform
         * It is used to encrypt to decrypt as well as decrypt to encrypt
         * Parameters:  input <byte /> - which needs to be transform 
         *              transformType - encrypt/decrypt transform
         * 
         * Return Val:  byte array - transformed value.
         ***************************************************************/
        private byte[] Transform(byte[] input, TransformType transformType)
        {
            CryptoStream cryptoStream = null;      // Stream used to encrypt
            RijndaelManaged rijndael = null;        // Rijndael provider
            ICryptoTransform rijndaelTransform = null;// Encrypting object 
            FileStream fsIn = null;                 //input file
            FileStream fsOut = null;                //output file
            MemoryStream memStream = null;          // Stream to contain data
            try
            {
                // Create the crypto objects
                rijndael = new RijndaelManaged();
                rijndael.Key = this._Key;
                rijndael.IV = this._IV;
                if (transformType == TransformType.ENCRYPT)
                {
                    rijndaelTransform = rijndael.CreateEncryptor();
                }
                else
                {
                    rijndaelTransform = rijndael.CreateDecryptor();
                }

                if ((input != null) && (input.Length > 0))
                {
                    memStream = new MemoryStream();
                    cryptoStream = new CryptoStream(
                         memStream, rijndaelTransform, 
                         CryptoStreamMode.Write);

                    cryptoStream.Write(input, 0, input.Length);

                    cryptoStream.FlushFinalBlock();

                    return memStream.ToArray();
                }
                else if ((_inputFile.Length > 0) && (_outputFile.Length > 0))
                {
                    // First we are going to open the file streams 
                    fsIn = new FileStream(_inputFile,
                                FileMode.Open, FileAccess.Read);
                    fsOut = new FileStream(_outputFile,
                                FileMode.OpenOrCreate, FileAccess.Write);

                    cryptoStream = new CryptoStream(
                        fsOut, rijndaelTransform, CryptoStreamMode.Write);

                    // Now will initialize a buffer and will be 
                    // processing the input file in chunks. 
                    // This is done to avoid reading the whole file 
                    // (which can be huge) into memory. 
                    int bufferLen = 4096;
                    byte[] buffer = new byte<bufferlen />;
                    int bytesRead;
                    do
                    {
                        // read a chunk of data from the input file 
                        bytesRead = fsIn.Read(buffer, 0, bufferLen);
                        // Encrypt it 
                        cryptoStream.Write(buffer, 0, bytesRead);

                    } while (bytesRead != 0);

                    cryptoStream.FlushFinalBlock();
                }
                return null;
            }
            catch (CryptographicException)
            {
                throw new CryptographicException(
                    "Password is invalid. Please verify once again.");
            }
            finally
            {
                if (rijndael != null) rijndael.Clear();
                if (rijndaelTransform != null) rijndaelTransform.Dispose();
                if (cryptoStream != null) cryptoStream.Close();
                if (memStream != null) memStream.Close();
                if (fsOut != null) fsOut.Close();
                if (fsIn != null) fsIn.Close();
            }
        }
    }
}

License

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