Click here to Skip to main content
15,867,488 members
Articles / Programming Languages / C#

Encrypt/Decrypt File or String

Rate me:
Please Sign up or sign in to vote.
3.04/5 (13 votes)
26 Sep 2007CPOL2 min read 118K   5.9K   47   22
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)


Written By
Web Developer
India India
I am a software developer. now i am working microsoft.net technolgy like c#, and asp.net.

Comments and Discussions

 
GeneralOpenfiledialog filter needs to be reset Pin
gherard1-Jan-10 18:46
gherard1-Jan-10 18:46 
NewsTwo other related encryption articles in CodeProject ... Pin
Tony Selke27-Sep-07 6:48
Tony Selke27-Sep-07 6:48 
QuestionIV and Key same for Encryption and Decryption? Pin
Vsree26-Sep-07 18:35
Vsree26-Sep-07 18:35 
AnswerRe: IV and Key same for Encryption and Decryption? Pin
Virendrachandra26-Sep-07 19:08
Virendrachandra26-Sep-07 19:08 
GeneralRe: IV and Key same for Encryption and Decryption? Pin
Virendrachandra26-Sep-07 23:54
Virendrachandra26-Sep-07 23:54 
AnswerRe: IV and Key same for Encryption and Decryption? Pin
Virendrachandra27-Sep-07 0:28
Virendrachandra27-Sep-07 0:28 
GeneralExecutable ZIP is corrupted Pin
OscarTV26-Sep-07 3:41
OscarTV26-Sep-07 3:41 
GeneralRe: Executable ZIP is corrupted Pin
OscarTV26-Sep-07 3:42
OscarTV26-Sep-07 3:42 
GeneralRe: Executable ZIP is corrupted Pin
Virendrachandra26-Sep-07 18:35
Virendrachandra26-Sep-07 18:35 
AnswerRe: Executable ZIP is corrupted Pin
OscarTV26-Sep-07 22:27
OscarTV26-Sep-07 22:27 
GeneralRe: Executable ZIP is corrupted Pin
Sean Ewington9-Oct-07 5:03
staffSean Ewington9-Oct-07 5:03 
GeneralDo Not Calculate the IV; Be Sure to &quot;Chunk&quot; Correctly Pin
Philip J. Smith20-Sep-07 5:13
Philip J. Smith20-Sep-07 5:13 
GeneralRe: Do Not Calculate the IV; Be Sure to &quot;Chunk&quot; Correctly Pin
Virendrachandra21-Sep-07 1:55
Virendrachandra21-Sep-07 1:55 
GeneralRe: Do Not Calculate the IV; Be Sure to &quot;Chunk&quot; Correctly Pin
Philip J. Smith21-Sep-07 5:12
Philip J. Smith21-Sep-07 5:12 
GeneralYou can (re)factor out about 75% of your code Pin
Tony Selke19-Sep-07 2:41
Tony Selke19-Sep-07 2:41 
GeneralRe: You can (re)factor out about 75% of your code Pin
Virendrachandra19-Sep-07 18:52
Virendrachandra19-Sep-07 18:52 
Generalthrow ex is bad Pin
Steve Hansen19-Sep-07 1:45
Steve Hansen19-Sep-07 1:45 
GeneralRe: throw ex is bad Pin
Virendrachandra19-Sep-07 3:02
Virendrachandra19-Sep-07 3:02 
GeneralRe: throw ex is bad Pin
Steve Hansen19-Sep-07 4:26
Steve Hansen19-Sep-07 4:26 
GeneralRe: throw ex is bad Pin
Tony Selke20-Sep-07 2:03
Tony Selke20-Sep-07 2:03 
GeneralRe: throw ex is bad Pin
knuteski9-Oct-07 8:21
knuteski9-Oct-07 8:21 
GeneralRe: throw ex is bad Pin
Virendrachandra9-Oct-07 19:50
Virendrachandra9-Oct-07 19:50 

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.