This is my encryption/decryption code. It works well but crashes when it encrypts a file even though it still encrypts it. Likewise, the program crashes when it decrypts a file even though it decrypts it.
After encryption or decryption the program gives the error ‘unhandled exception has occurred in your application. It also says “the path is not of a legal form’.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Security;
using System.Security.Cryptography;
using System.Diagnostics;
using Microsoft.VisualBasic;
namespace Encryption_Decryption_Tool
{
public partial class frmMain : Form
{
string strFileToEncrypt, strFileToDecrypt, strOutputEncrypt, strOutputDecrypt;
System.IO.FileStream fsInput;
System.IO.FileStream fsOutput;
public frmMain()
{
InitializeComponent();
}
private byte[] CreateKey(string strPassword)
{
//Convert strPassword to an array and store in chrData.
char[] chrData = strPassword.ToCharArray();
//Use intLength to get strPassword size.
int intLength = chrData.GetUpperBound(0);
//Declare bytDataToHash and make it the same size as chrData.
byte[] bytDataToHash = new byte[intLength + 1];
//Use For Next to convert and store chrData into bytDataToHash.
for (int i = 0; i <= chrData.GetUpperBound(0); i++)
{
bytDataToHash[i] = Convert.ToByte(chrData[i]);
}
//Declare what hash to use.
System.Security.Cryptography.SHA512Managed SHA512 = new System.Security.Cryptography.SHA512Managed();
//Declare bytResult, Hash bytDataToHash and store it in bytResult.
byte[] bytResult = SHA512.ComputeHash(bytDataToHash);
//Declare bytKey(31). It will hold 256 bits.
byte[] bytKey = new byte[32];
//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 (int i = 0; i <= 31; i++)
{
bytKey[i] = bytResult[i];
}
return bytKey;
//Return the key.
}
private byte[] CreateIV(string strPassword)
{
//Convert strPassword to an array and store in chrData.
char[] chrData = strPassword.ToCharArray();
//Use intLength to get strPassword size.
int intLength = chrData.GetUpperBound(0);
//Declare bytDataToHash and make it the same size as chrData.
byte[] bytDataToHash = new byte[intLength + 1];
//Use For Next to convert and store chrData into bytDataToHash.
for (int i = 0; i <= chrData.GetUpperBound(0); i++)
{
bytDataToHash[i] = Convert.ToByte(chrData[i]);
}
//Declare what hash to use.
System.Security.Cryptography.SHA512Managed SHA512 = new System.Security.Cryptography.SHA512Managed();
//Declare bytResult, Hash bytDataToHash and store it in bytResult.
byte[] bytResult = SHA512.ComputeHash(bytDataToHash);
//Declare bytIV(15). It will hold 128 bits.
byte[] bytIV = new byte[16];
//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 (int i = 32; i <= 47; i++)
{
bytIV[i - 32] = bytResult[i];
}
return bytIV;
//return the IV
}
private enum CryptoAction
{
//Define the enumeration for CryptoAction.
ActionEncrypt = 1,
ActionDecrypt = 2
}
private void EncryptOrDecryptFile(string strInputFile, string strOutputFile, byte[] bytKey, byte[] bytIV, CryptoAction Direction)
{
//In case of errors.
try
{
//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.
byte[] bytBuffer = new byte[4097];
//holds a block of bytes for processing
long lngBytesProcessed = 0;
//running count of bytes processed
long lngFileLength = fsInput.Length;
//the input file's length
int intBytesInCurrentBlock = 0;
//current bytes being processed
CryptoStream csCryptoStream = null;
//Declare your CryptoServiceProvider.
System.Security.Cryptography.RijndaelManaged cspRijndael = new System.Security.Cryptography.RijndaelManaged();
//Setup Progress Bar
pbStatus.Value = 0;
pbStatus.Maximum = 100;
//Determine if ecryption or decryption and setup CryptoStream.
switch (Direction)
{
case CryptoAction.ActionEncrypt:
csCryptoStream = new CryptoStream(fsOutput, cspRijndael.CreateEncryptor(bytKey, bytIV), CryptoStreamMode.Write);
break;
case CryptoAction.ActionDecrypt:
csCryptoStream = new CryptoStream(fsOutput, cspRijndael.CreateDecryptor(bytKey, bytIV), CryptoStreamMode.Write);
break;
}
//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 + Convert.ToInt64(intBytesInCurrentBlock);
//Update Progress Bar
pbStatus.Value = Convert.ToInt32((lngBytesProcessed / lngFileLength) * 100);
}
//Close FileStreams and CryptoStream.
csCryptoStream.Close();
fsInput.Close();
fsOutput.Close();
//If encrypting then delete the original unencrypted file.
if (Direction == CryptoAction.ActionEncrypt)
{
FileInfo fileOriginal = new FileInfo(strFileToEncrypt);
fileOriginal.Delete();
}
//If decrypting then delete the encrypted file.
if (Direction == CryptoAction.ActionDecrypt)
{
FileInfo fileEncrypted = new FileInfo(strFileToDecrypt);
fileEncrypted.Delete();
}
//Update the user when the file is done.
string Wrap = "\r\n";
if (Direction == CryptoAction.ActionEncrypt)
{
MessageBox.Show("Encryption Complete" + Wrap + Wrap + "Total bytes processed = " + lngBytesProcessed.ToString(), "Done", MessageBoxButtons.OK, MessageBoxIcon.Information);
//Update the progress bar and textboxes.
pbStatus.Value = 0;
txtFileToEncrypt.Text = "Click Browse to load file.";
txtPassEncrypt.Text = "";
txtConPassEncrypt.Text = "";
txtDestinationEncrypt.Text = "";
btnChangeEncrypt.Enabled = false;
btnEncrypt.Enabled = false;
}
else
{
//Update the user when the file is done.
MessageBox.Show("Decryption Complete" + Wrap + Wrap + "Total bytes processed = " + lngBytesProcessed.ToString(),"Done",MessageBoxButtons.OK,MessageBoxIcon.Information) ;
//Update the progress bar and textboxes.
pbStatus.Value = 0;
txtFileToDecrypt.Text = "Click Browse to load file.";
txtPassDecrypt.Text = "";
txtConPassDecrypt.Text = "";
txtDestinationDecrypt.Text = "";
btnChangeDecrypt.Enabled = false;
btnDecrypt.Enabled = false;
}
//Catch file not found error.
//if file not found
}
catch
{
MessageBox.Show("Please check to make sure the path and filename" + "are correct and if the file exists.", "Invalid Path or Filename", MessageBoxButtons.OK, MessageBoxIcon.Information);
//Catch all other errors. And delete partial files.
}
finally
{
fsInput.Close();
fsOutput.Close();
if (Direction == CryptoAction.ActionDecrypt)
{
FileInfo fileDelete = new FileInfo(txtDestinationDecrypt.Text);
fileDelete.Delete();
pbStatus.Value = 0;
txtPassDecrypt.Text = "";
txtConPassDecrypt.Text = "";
MessageBox.Show("Please check to make sure that you entered the correct" + "password.","Invalid Password", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
else
{
FileInfo fileDelete = new FileInfo(txtDestinationEncrypt.Text);
fileDelete.Delete();
pbStatus.Value = 0;
txtPassEncrypt.Text = "";
txtConPassEncrypt.Text = "";
MessageBox.Show("This file cannot be encrypted.", "File Cannot Be Encrypted", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
}
private void btnBrowseEncrypt_Click(object sender, EventArgs e)
{
//Setup the open dialog.
openFileDialog1.FileName = "";
openFileDialog1.Title = "Choose a file to encrypt";
openFileDialog1.InitialDirectory = "C:\\";
openFileDialog1.Filter = "All Files (*.*) | *.*";
//Find out if the user chose a file.
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
strFileToEncrypt = openFileDialog1.FileName;
txtFileToEncrypt.Text = strFileToEncrypt;
int iPosition = 0;
int i = 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('\\', i) != -1)
{
iPosition = strFileToEncrypt.IndexOf('\\', i);
i = iPosition + 1;
}
//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 "\".
string S = strFileToEncrypt.Substring(0, iPosition + 1);
//Replace the "." in the file extension with "_".
strOutputEncrypt = strOutputEncrypt.Replace('.', '_');
//The final file name. XXXXX.encrypt
txtDestinationEncrypt.Text = S + strOutputEncrypt + ".encrypt";
//Update buttons.
btnEncrypt.Enabled = true;
btnChangeEncrypt.Enabled = true;
}
}
private void btnBrowseDecrypt_Click(object sender, EventArgs e)
{
//Setup the open dialog.
openFileDialog2.FileName = "";
openFileDialog2.Title = "Choose a file to decrypt";
openFileDialog2.InitialDirectory = "C:\\";
openFileDialog2.Filter = "Encrypted Files (*.encrypt) | *.encrypt";
//Find out if the user chose a file.
if (openFileDialog2.ShowDialog() == DialogResult.OK)
{
strFileToDecrypt = openFileDialog2.FileName;
txtFileToDecrypt.Text = strFileToDecrypt;
int iPosition = 0;
int i = 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('\\', i) != -1)
{
iPosition = strFileToDecrypt.IndexOf('\\', i);
i = iPosition + 1;
}
//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 "\".
string S = 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('_', '.');
//Update buttons
btnDecrypt.Enabled = true;
btnChangeDecrypt.Enabled = true;
}
}
private void btnChangeEncrypt_Click(object sender, EventArgs e)
{
//Setup up folder browser.
folderBrowserDialog1.Description = "Select a folder to place the encrypted file in.";
//If the user selected a folder assign the path to txtDestinationEncrypt.
if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
{
txtDestinationEncrypt.Text = folderBrowserDialog1.SelectedPath + "\\" + strOutputEncrypt + ".encrypt";
}
}
private void btnChangeDecrypt_Click(object sender, EventArgs e)
{
//Setup up folder browser.
folderBrowserDialog2.Description = "Select a folder for to place the decrypted file in.";
//If the user selected a folder assign the path to txtDestinationDecrypt.
if (folderBrowserDialog2.ShowDialog() == DialogResult.OK)
{
txtDestinationDecrypt.Text = folderBrowserDialog2.SelectedPath + "\\" + strOutputDecrypt.Replace('_', '.');
}
}
private void btnEncrypt_Click(object sender, EventArgs e)
{
//Make sure the password is correct.
if (txtConPassEncrypt.Text == txtPassEncrypt.Text)
{
//Declare variables for the key and iv.
//The key needs to hold 256 bits and the iv 128 bits.
byte[] bytKey = null;
byte[] bytIV = null;
//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);
}
else
{
MessageBox.Show ("Please re-enter your password.","Error",MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
txtPassEncrypt.Text = "";
txtConPassEncrypt.Text = "";
}
}
private void btnDecrypt_Click(object sender, EventArgs e)
{
//Make sure the password is correct.
if (txtConPassDecrypt.Text == txtPassDecrypt.Text)
{
//Declare variables for the key and iv.
//The key needs to hold 256 bits and the iv 128 bits.
byte[] bytKey = null;
byte[] bytIV = null;
//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);
}
else
{
MessageBox.Show ("Please re-enter your password.","Error",MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
txtPassDecrypt.Text = "";
txtConPassDecrypt.Text = "";
}
}
}
}
Copied exception from duplicate post:
************* Exception Text **************
System.ArgumentException: The path is not of a legal form.
at System.IO.Path.NormalizePathFast(String path, Boolean fullCheck)
at System.IO.FileInfo..ctor(String fileName)
at Encryption_Decryption_Tool.frmMain.EncryptOrDecryptFile(String strInputFile, String strOutputFile, Byte[] bytKey, Byte[] bytIV, CryptoAction Direction) in C:\Users\baffa\Documents\Visual Studio 2008\Projects\Encryption_Decryption_Tool\Encryption_Decryption_Tool\Form1.cs:line 236
at Encryption_Decryption_Tool.frmMain.btnEncrypt_Click(Object sender, EventArgs e) in C:\Users\baffa\Documents\Visual Studio 2008\Projects\Encryption_Decryption_Tool\Encryption_Decryption_Tool\Form1.cs:line 373
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
Either your input or output file name is incorrect.
The way that you are processing the file names in the button click events is massive overkill and is what is likely causing the problems.
It would be much better to use the standard System.IO.Path methods.
Specifically, if you are just trying to take the selected file name and change the extension, all of your file name manipulation code can be replace with one line:
Update
I have substantially cleaned up the EncryptOrDecryptFile code and verified that it works correctly in both directions. I have moved the module-level fsInput and fsOutput into this method and wrapped the primary players in using statements. I also moved the incorrect code in the finally area into the catch area, which is where it belongs. Finally, I also added checking to the beginning of the method to ensure a file is specified and that it is exists.
I also modified the first part of each of the btnChange click events to verify that a file has been selected before this button is pressed:
and: