Click here to Skip to main content
15,881,248 members
Articles / Programming Languages / Visual Basic
Article

Encrypt/Decrypt Files in VB.NET (Using Rijndael)

Rate me:
Please Sign up or sign in to vote.
4.79/5 (85 votes)
4 Nov 2005Apache4 min read 632.6K   41.1K   109   106
How to encrypt and decrypt files using Rijndael.

Sample Image - EncryptFile.jpg

Introduction

This is a sample application that will encrypt and decrypt files in VB.NET using Rijndael Managed. I started this project because I had several files on my computer that I didn’t want accessible to anyone but me. Sure I could have downloaded a free encryption program off the net, but what fun would that be? So being the hobbyist that I am, I decided to create my own.

Background

Here are some brief descriptions of the cryptographic concepts relevant to this application. I am going to keep things as simple and basic as possible. If you want further details there is a ton of information on the web. Also check out “.NET Encryption Simplified” by: wumpus1 right here at Code Project. These descriptions are based on how the concepts are used in this application.

  1. The Key:

    The password used to encrypt/decrypt data.

  2. The IV:

    Initialization Vector. This is used to encrypt the first portion of the data to be encrypted.

  3. Rijndael:

    The algorithm used for encryption/decryption. In this application, Rijndael is using a 256 bit key and a 128 bit IV.

  4. SHA512 Hashing:

    This takes a string (the password) and transforms it into a fixed size (512 bits) of “encrypted data”. The same string will always “hash” into the same 512 bits of data.

Using the code

In this section I will cover the following:

  • Creating the Key
  • Creating the IV
  • Encryption and decryption
  • Changing file extensions
  • Putting it all together

My explanations will be brief because my code is heavily commented. Before we begin, we will need the following Imports statements:

VB
Imports System
Imports System.IO
Imports System.Security
Imports System.Security.Cryptography

Now let's declare our global variables:

VB
'*************************
'** Global Variables
'*************************

Dim strFileToEncrypt As String
Dim strFileToDecrypt As String
Dim strOutputEncrypt As String
Dim strOutputDecrypt As String
Dim fsInput As System.IO.FileStream
Dim fsOutput As System.IO.FileStream

Creating the Key

Of course, the most secure Key would be a randomly generated Key. But I prefer to make up my own. The following code is a function that will create a 256 bit Hashed Key from the user’s password. Here is what happens in the function:

  • The function receives a string (the password).
  • Converts the string to an array.
  • Converts the array to a byte.
  • Uses SHA512 to hash the byte.
  • Stores the first 256 bits of the hashed byte into a new byte (the key).
  • Returns the key.

For a more in-depth description, read the ‘comments' in the following code:

VB
'*************************
'** Create A Key
'*************************

Private Function CreateKey(ByVal strPassword As String) As Byte()
    'Convert strPassword to an array and store in chrData.
    Dim chrData() As Char = strPassword.ToCharArray
    'Use intLength to get strPassword size.
    Dim intLength As Integer = chrData.GetUpperBound(0)
    'Declare bytDataToHash and make it the same size as chrData.
    Dim bytDataToHash(intLength) As Byte
    
    'Use For Next to convert and store chrData into bytDataToHash.
    For i As Integer = 0 To chrData.GetUpperBound(0)
        bytDataToHash(i) = CByte(Asc(chrData(i)))
    Next

    'Declare what hash to use.
    Dim SHA512 As New System.Security.Cryptography.SHA512Managed
    'Declare bytResult, Hash bytDataToHash and store it in bytResult.
    Dim bytResult As Byte() = SHA512.ComputeHash(bytDataToHash)
    'Declare bytKey(31).  It will hold 256 bits.
    Dim bytKey(31) As Byte
    
    'Use For Next to put a specific size (256 bits) of 
    'bytResult into bytKey. The 0 To 31 will put the first 256 bits
    'of 512 bits into bytKey.
    For i As Integer = 0 To 31
        bytKey(i) = bytResult(i)
    Next

    Return bytKey 'Return the key.
End Function

Here is an alternate example of creating a Key without using SHA512 hashing:

VB
Private Function CreateKey(ByVal strPassword As String) As Byte()
    Dim bytKey As Byte()
    Dim bytSalt As Byte() = System.Text.Encoding.ASCII.GetBytes("salt")
    Dim pdb As New PasswordDeriveBytes(strPassword, bytSalt)
        
    bytKey = pdb.GetBytes(32)

    Return bytKey 'Return the key.
End Function

Creating the IV

OK, so we used the first 256 bits of our hashed byte to create the key. We will use the next 128 bits of our hashed byte to create our IV. This way the key will be different from the IV. This function is almost identical to the previous one.

VB
'*************************
'** Create An IV
'*************************

Private Function CreateIV(ByVal strPassword As String) As Byte()
    'Convert strPassword to an array and store in chrData.
    Dim chrData() As Char = strPassword.ToCharArray
    'Use intLength to get strPassword size.
    Dim intLength As Integer = chrData.GetUpperBound(0)
    'Declare bytDataToHash and make it the same size as chrData.
    Dim bytDataToHash(intLength) As Byte

    'Use For Next to convert and store chrData into bytDataToHash.
    For i As Integer = 0 To chrData.GetUpperBound(0)
        bytDataToHash(i) = CByte(Asc(chrData(i)))
    Next

    'Declare what hash to use.
    Dim SHA512 As New System.Security.Cryptography.SHA512Managed
    'Declare bytResult, Hash bytDataToHash and store it in bytResult.
    Dim bytResult As Byte() = SHA512.ComputeHash(bytDataToHash)
    'Declare bytIV(15).  It will hold 128 bits.
    Dim bytIV(15) As Byte

    'Use For Next to put a specific size (128 bits) of bytResult into bytIV.
    'The 0 To 30 for bytKey used the first 256 bits of the hashed password.
    'The 32 To 47 will put the next 128 bits into bytIV.
    For i As Integer = 32 To 47
        bytIV(i - 32) = bytResult(i)
    Next

    Return bytIV 'Return the IV.
End Function

Here is an alternate example of creating an IV without using SHA512 hashing:

VB
Private Function CreateIV(ByVal strPassword As String) As Byte()
    Dim bytIV As Byte()
    Dim bytSalt As Byte() = System.Text.Encoding.ASCII.GetBytes("salt")
    Dim pdb As New PasswordDeriveBytes(strPassword, bytSalt)

    bytIV = pdb.GetBytes(16)

    Return bytIV 'Return the IV.
End Function

Encryption and Decryption

Here is the meat and potatoes of the encryption/decryption process. This block of code has been modified from an article called “Tales from the Crypto” by Billy Hollis. Here is what happens in this procedure:

  • Define the enumeration for CryptoAction (encrypt/decrypt).
  • Begin with an encrypted/unencrypted file.
  • Use a FileStream object to open and read the file.
  • Use a CryptoStream object to perform encryption/decryption.
  • Use another FileStream object to write the encrypted/decrypted file.

For a more in-depth description read the ‘comments' in the following code:

VB
'****************************
'** Encrypt/Decrypt File
'****************************

Private Enum CryptoAction
    'Define the enumeration for CryptoAction.
    ActionEncrypt = 1
    ActionDecrypt = 2
End Enum

Private Sub EncryptOrDecryptFile(ByVal strInputFile As String, _
                                 ByVal strOutputFile As String, _
                                 ByVal bytKey() As Byte, _
                                 ByVal bytIV() As Byte, _
                                 ByVal Direction As CryptoAction)
    Try 'In case of errors.
      
        'Setup file streams to handle input and output.
        fsInput = New System.IO.FileStream(strInputFile, FileMode.Open, _
                                              FileAccess.Read)
        fsOutput = New System.IO.FileStream(strOutputFile, _
                                               FileMode.OpenOrCreate, _
                                               FileAccess.Write)
        fsOutput.SetLength(0) 'make sure fsOutput is empty

        'Declare variables for encrypt/decrypt process.
        Dim bytBuffer(4096) As Byte 'holds a block of bytes for processing
        Dim lngBytesProcessed As Long = 0 'running count of bytes processed
        Dim lngFileLength As Long = fsInput.Length 'the input file's length
        Dim intBytesInCurrentBlock As Integer 'current bytes being processed
        Dim csCryptoStream As CryptoStream
        'Declare your CryptoServiceProvider.
        Dim cspRijndael As New System.Security.Cryptography.RijndaelManaged
        'Setup Progress Bar
        pbStatus.Value = 0
        pbStatus.Maximum = 100

        'Determine if ecryption or decryption and setup CryptoStream.
        Select Case Direction
            Case CryptoAction.ActionEncrypt
                csCryptoStream = New CryptoStream(fsOutput, _
                cspRijndael.CreateEncryptor(bytKey, bytIV), _
                CryptoStreamMode.Write)

            Case CryptoAction.ActionDecrypt
                csCryptoStream = New CryptoStream(fsOutput, _
                cspRijndael.CreateDecryptor(bytKey, bytIV), _
                CryptoStreamMode.Write)
        End Select

        'Use While to loop until all of the file is processed.
        While lngBytesProcessed < lngFileLength
            'Read file with the input filestream.
            intBytesInCurrentBlock = fsInput.Read(bytBuffer, 0, 4096)
            'Write output file with the cryptostream.
            csCryptoStream.Write(bytBuffer, 0, intBytesInCurrentBlock)
            'Update lngBytesProcessed
            lngBytesProcessed = lngBytesProcessed + _
                                    CLng(intBytesInCurrentBlock)
            'Update Progress Bar
            pbStatus.Value = CInt((lngBytesProcessed / lngFileLength) * 100)
        End While

        'Close FileStreams and CryptoStream.
        csCryptoStream.Close()
        fsInput.Close()
        fsOutput.Close()

Changing File Extensions

Basically, what we are doing here is taking the path name of the file to encrypt/decrypt and adding or removing an “.encrypt” extension. This is not really necessary for encrypting files, but I think it looks cool.

When encrypting a file we would add an “.encrypt” extension as follows:

VB
'Setup the open dialog.
OpenFileDialog.FileName = ""
OpenFileDialog.Title = "Choose a file to encrypt"
OpenFileDialog.InitialDirectory = "C:\"
OpenFileDialog.Filter = "All Files (*.*) | *.*"

'Find out if the user chose a file.
If OpenFileDialog.ShowDialog = DialogResult.OK Then
    strFileToEncrypt = OpenFileDialog.FileName
    txtFileToEncrypt.Text = strFileToEncrypt

    Dim iPosition As Integer = 0
    Dim i As Integer = 0

    'Get the position of the last "\" in the OpenFileDialog.FileName path.
    '-1 is when the character your searching for is not there.
    'IndexOf searches from left to right.
    While strFileToEncrypt.IndexOf("\"c, i) <> -1
        iPosition = strFileToEncrypt.IndexOf("\"c, i)
        i = iPosition + 1
    End While

    'Assign strOutputFile to the position after the last "\" in the path.
    'This position is the beginning of the file name.
    strOutputEncrypt = strFileToEncrypt.Substring(iPosition + 1)
    'Assign S the entire path, ending at the last "\".
    Dim S As String = strFileToEncrypt.Substring(0, iPosition + 1)
    'Replace the "." in the file extension with "_".
    strOutputEncrypt = strOutputEncrypt.Replace("."c, "_"c)
    'The final file name.  XXXXX.encrypt
    txtDestinationEncrypt.Text = S + strOutputEncrypt + ".encrypt"

When decrypting a file we would remove the “.encrypt” extension as follows:

VB
'Setup the open dialog.
OpenFileDialog.FileName = ""
OpenFileDialog.Title = "Choose a file to decrypt"
OpenFileDialog.InitialDirectory = "C:\"
OpenFileDialog.Filter = "Encrypted Files (*.encrypt) | *.encrypt"

'Find out if the user chose a file.
If OpenFileDialog.ShowDialog = DialogResult.OK Then
    strFileToDecrypt = OpenFileDialog.FileName
    txtFileToDecrypt.Text = strFileToDecrypt
    Dim iPosition As Integer = 0
    Dim i As Integer = 0
    'Get the position of the last "\" in the OpenFileDialog.FileName path.
    '-1 is when the character your searching for is not there.
    'IndexOf searches from left to right.

    While strFileToDecrypt.IndexOf("\"c, i) <> -1
        iPosition = strFileToDecrypt.IndexOf("\"c, i)
        i = iPosition + 1
    End While

    'strOutputFile = the file path minus the last 8 characters (.encrypt)
    strOutputDecrypt = strFileToDecrypt.Substring(0, _
                                            strFileToDecrypt.Length - 8)
    'Assign S the entire path, ending at the last "\".
    Dim S As String = strFileToDecrypt.Substring(0, iPosition + 1)
    'Assign strOutputFile to the position after the last "\" in the path.
    strOutputDecrypt = strOutputDecrypt.Substring((iPosition + 1))
    'Replace "_" with "."
    txtDestinationDecrypt.Text = S + strOutputDecrypt.Replace("_"c, "."c)

Keep in mind that the above code is geared towards my sample application.

Putting It All Together

OK, so this is where everything comes together with the “Encrypt” and “Decrypt” buttons. Basically what happens here is:

  • Variables are declared for the Key and IV.
  • The user’s password is passed to the CreateKey function.
  • The user’s password is passed to the CreateIV function.
  • The input path name, output path name, Key, IV, and CryptoAction are passed to the EncryptOrDecryptFile procedure.

Encrypting would go as follows:

VB
'Declare variables for the key and iv.
'The key needs to hold 256 bits and the iv 128 bits.
Dim bytKey As Byte()
Dim bytIV As Byte()
'Send the password to the CreateKey function.
bytKey = CreateKey(txtPassEncrypt.Text)
'Send the password to the CreateIV function.
bytIV = CreateIV(txtPassEncrypt.Text)
'Start the encryption.
EncryptOrDecryptFile(strFileToEncrypt, txtDestinationEncrypt.Text, _
                     bytKey, bytIV, CryptoAction.ActionEncrypt)

Decrypting would go as follows:

VB
'Declare variables for the key and iv.
'The key needs to hold 256 bits and the iv 128 bits.
Dim bytKey As Byte()
Dim bytIV As Byte()
'Send the password to the CreateKey function.
bytKey = CreateKey(txtPassDecrypt.Text)
'Send the password to the CreateIV function.
bytIV = CreateIV(txtPassDecrypt.Text)
'Start the decryption.
EncryptOrDecryptFile(strFileToDecrypt, txtDestinationDecrypt.Text, _
                     bytKey, bytIV, CryptoAction.ActionDecrypt)

Points of Interest

This application uses the Rijndael algorithm to encrypt and decrypt files. You could also use Data Encryption Standard (DES) or Triple DES to do the same. All you would need to change is the Key size, IV size and the Crypto Service Provider. I hope that you can have some fun with this code. Questions and comments are appreciated.

History

  • October 28, 2005: Posted.
  • October 31, 2005: File size issue fixed, thanks to Moonark.
  • November 1, 2005: Alternate examples of CreateKey/IV added, thanks to Vlad Tepes.
  • November 4, 2005: Array issue fixed, thanks to ccady.

License

This article, along with any associated source code and files, is licensed under The Apache License, Version 2.0


Written By
United States United States
I was introduced to VB.Net while serving in the U.S. Army Infantry. Since then I enjoy writing small applications in my spare time.

Comments and Discussions

 
QuestionWord Document Pin
Member 962658210-Sep-21 11:27
Member 962658210-Sep-21 11:27 
QuestionUsing Triple DES Encyption Pin
Member 107319315-Aug-19 14:34
Member 107319315-Aug-19 14:34 
SuggestionKey creation code is obsolete Pin
MTeefy9-May-17 23:39
MTeefy9-May-17 23:39 
QuestionWhat type of encryption of this? Pin
Member 1251121830-Nov-16 6:25
Member 1251121830-Nov-16 6:25 
QuestionUser Login Pin
Member62727-Apr-15 14:14
Member62727-Apr-15 14:14 
QuestionRegarding the same i want to give it as a minor project Pin
Member 1154137921-Mar-15 20:07
Member 1154137921-Mar-15 20:07 
QuestionRegarding the code and full project demo Pin
Member 1154137921-Mar-15 20:02
Member 1154137921-Mar-15 20:02 
QuestionCrypt all the files of a directory Pin
Member 1147112122-Feb-15 23:57
Member 1147112122-Feb-15 23:57 
QuestionVb.NET to JAVA Pin
Member 1089597610-Jan-15 5:57
Member 1089597610-Jan-15 5:57 
QuestionEmail Attached Pin
Member 108959769-Jan-15 12:23
Member 108959769-Jan-15 12:23 
QuestionThanks message and Java Code Rquested Pin
Member 108959769-Jan-15 12:18
Member 108959769-Jan-15 12:18 
QuestionI NEED YOUR HELP SIR Pin
omer bhutta30-Nov-14 23:29
omer bhutta30-Nov-14 23:29 
QuestionThank you for this article :) Pin
NavaneethaKrishnan A13-Nov-14 21:11
NavaneethaKrishnan A13-Nov-14 21:11 
SuggestionSimpler way to generate IV and Key Pin
1337Architect22-Aug-14 19:51
professional1337Architect22-Aug-14 19:51 
Questionauto encryption Pin
Member 1028014522-Aug-14 8:37
Member 1028014522-Aug-14 8:37 
General:) Pin
Widgets23-May-14 9:45
Widgets23-May-14 9:45 
QuestionOpen encrypted file without decrypting Pin
Ranganath Deshpande7-Jan-14 11:00
Ranganath Deshpande7-Jan-14 11:00 
AnswerRe: Open encrypted file without decrypting Pin
Member 1403683831-Jul-20 7:26
Member 1403683831-Jul-20 7:26 
QuestionGood Pin
Member 850494129-Dec-13 16:23
Member 850494129-Dec-13 16:23 
Questioni forget the password is there anyway to retrieve my password Pin
michael nabil11-Aug-13 5:52
michael nabil11-Aug-13 5:52 
Questionhelllo.... Pin
Basiliso11-Jul-13 23:23
Basiliso11-Jul-13 23:23 
QuestionMy heart felt thanks... Pin
Member 1013340330-Jun-13 15:33
Member 1013340330-Jun-13 15:33 
QuestionRijndael cryptography to secure a text message or a text?? Pin
Evangeline Cristian Van Haven30-Jun-13 8:15
Evangeline Cristian Van Haven30-Jun-13 8:15 
hai ...
want to ask, if there is no text to the security algorithm Rijndael 256-bit key?
Rijndael cryptography to secure a text message or a text??

thanks you.
GeneralMy vote of 5 Pin
Jayke Huempfner13-Jun-13 22:44
Jayke Huempfner13-Jun-13 22:44 
QuestionGood Apps and Works Pin
sug1anto5-Mar-13 20:47
sug1anto5-Mar-13 20:47 

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.