![]() |
General Programming »
Cryptography & Security »
Encryption
Intermediate
Encrypt/Decrypt Files in VB.NET (Using Rijndael)By Thad Van den BoschHow to encrypt and decrypt files using Rijndael. |
VB, Windows, .NET 1.1VS.NET2003, Dev
|
|
Advanced Search |
|
|
|
||||||||||||||||

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.
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.
The password used to encrypt/decrypt data.
Initialization Vector. This is used to encrypt the first portion of the data to be encrypted.
The algorithm used for encryption/decryption. In this application, Rijndael is using a 256 bit key and a 128 bit IV.
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.
In this section I will cover the following:
My explanations will be brief because my code is heavily commented. Before we begin, we will need the following Imports statements:
Imports System
Imports System.IO
Imports System.Security
Imports System.Security.Cryptography
Now let's declare our global variables:
'*************************
'** 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
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:
For a more in-depth description, read the �comments' in the following code:
'*************************
'** 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:
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
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.
'*************************
'** 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:
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
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:
CryptoAction (encrypt/decrypt).
FileStream object to open and read the file.
CryptoStream object to perform encryption/decryption.
FileStream object to write the encrypted/decrypted file. For a more in-depth description read the �comments' in the following code:
'****************************
'** 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()
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:
'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:
'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.
OK, so this is where everything comes together with the �Encrypt� and �Decrypt� buttons. Basically what happens here is:
CreateKey function.
CreateIV function.
CryptoAction are passed to the EncryptOrDecryptFile procedure. Encrypting would go as follows:
'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:
'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)
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.
CreateKey/IV added, thanks to Vlad Tepes.
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 4 Nov 2005 Editor: Smitha Vijayan |
Copyright 2005 by Thad Van den Bosch Everything else Copyright © CodeProject, 1999-2009 Web13 | Advertise on the Code Project |