Abhishek Modak
asked on
Implementing an application in c# that encrypts and decrypts files and hide and shows folders based on the selected Bluetooth devices range.
I have developed a c# application that encrypts and decrypts files in a particular folder based on selected Bluetooth device range. If the selected Bluetooth device goes out of range, then the files in the particular folder gets encrypted and when the selected Bluetooth device comes back in range , then the files of the folder that were encrypted gets decrypted.
Here is the source code :
using System;
using System.Collections.Generic ;
using System.Windows.Forms;
using InTheHand.Net.Sockets;
using System.Threading;
using System.Data.SqlClient;
using System.IO;
using System.Security.Cryptograp hy;
using System.Text;
namespace Folder_Security
{
public partial class EncryptDecryptTool : Form
{
List<string> discoverable_devices_items = new List<string>();
BluetoothDeviceInfo[] paired_devices;
string key;
public EncryptDecryptTool()
{
InitializeComponent();
cmb_UsersDisplay.Text = "Device List";
key = generateKey();
}
private const string _IV = "EncryptDecryptFile";
private string generateKey()
{
AesCryptoServiceProvider aesCrypto = (AesCryptoServiceProvider) AesCryptoS erviceProv ider.Creat e();
return ASCIIEncoding.ASCII.GetStr ing(aesCry pto.Key);
}
private void start_devices_scan()
{
discoverable_devices_items .Clear();
Thread bluetoothScanThread = new Thread(new ThreadStart(devices_scan)) ;
bluetoothScanThread.Start( );
}
private void devices_scan()
{
BluetoothClient client = new BluetoothClient();
paired_devices = client.DiscoverDevicesInRa nge();
Console.Write("printing device list...");
foreach(BluetoothDeviceInf o device in paired_devices)
{
Console.Write("Inside for each1");
Console.WriteLine(device.T oString()) ;
}
foreach (BluetoothDeviceInfo d2 in paired_devices)
{
discoverable_devices_items .Add(d2.De viceName);
}
}
private void updateUI(string message)
{
Func<int> del = delegate ()
{
txt_Response.AppendText(me ssage + System.Environment.NewLine );
return 0;
};
Invoke(del);
}
private void btn_Check_for_Range_Click( object sender, EventArgs e)
{
start_devices_scan();
Thread.Sleep(15000);
items_compare(discoverable _devices_i tems);
}
private static void DirSearch(string sDir)
{
try
{
foreach (string d in Directory.GetDirectories(s Dir))
{
foreach (string f in Directory.GetFiles(d))
{
Console.WriteLine(f);
}
DirSearch(d);
Console.WriteLine(d);
}
}
catch (System.Exception excpt)
{
Console.WriteLine(excpt.Me ssage);
}
}
private void items_compare(List<string> discoverable_devices_items )
{
string selected_item = this.cmb_UsersDisplay.GetI temText(th is.cmb_Use rsDisplay. SelectedIt em);
SqlConnection con = new SqlConnection(@"Data Source = (LocalDB)\MSSQLLocalDB; AttachDbFilename = C:\Users\HP\Documents\Visu al Studio 2015\Projects\Folder_Secur ity\Folder _Security\ Database1. mdf; Integrated Security = True");
con.Open();
string Sql = "select File_Path from dbo.Devices where DeviceName='" + selected_item + "'";
SqlCommand cmd = new SqlCommand(Sql, con);
SqlDataReader Dr = cmd.ExecuteReader();
if (Dr.Read())
{
Console.WriteLine(Dr[0].To String());
}
string path = Dr[0].ToString();
DirSearch(path);
foreach (string f in Directory.GetFiles(path))
{
Console.WriteLine(f);
}
if (selected_item == "")
{
MessageBox.Show("Please select a device from the list");
}
if (discoverable_devices_item s.Contains (selected_ item))
{
updateUI("Selected paired device is in range");
foreach (string f in Directory.GetFiles(path))
{
DecryptFile(f, key);
}
}
else
{
updateUI("Selected paired device is now out of range");
foreach (string f in Directory.GetFiles(path))
{
Console.WriteLine("Inside foreach");
EncryptFile(f, key);
}
}
con.Close();
}
private static void EncryptFile(string inputFile, string key)
{
Console.WriteLine("Inside EncryptFile function");
try
{
Console.WriteLine("Inside EncryptFile try statements");
string ext = Path.GetExtension(inputFil e);
string outputFile = inputFile.Replace(ext, "_enc" + ext);
//Prepare the file for encryption by getting it into a stream
string cryptFile = outputFile;
FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create);
//Setup the Encryption Standard using Write mode
AesManaged aesCrypto = new AesManaged();
CryptoStream cs = new CryptoStream(fsCrypt, aesCrypto.CreateEncryptor( ), CryptoStreamMode.Write);
//Write the encrypted file stream
FileStream fsIn = new FileStream(inputFile, FileMode.Open);
int data;
while ((data = fsIn.ReadByte()) != -1)
{
cs.WriteByte((byte)data);
}
//Close all the Writers
fsIn.Close();
cs.Close();
fsCrypt.Close();
//Delete the original file
File.Delete(inputFile);
//Rename the encrypted file to that of the original
File.Copy(outputFile, inputFile);
File.Delete(outputFile);
}
catch (Exception ex)
{
Console.WriteLine(ex.Messa ge);
}
}
private static void DecryptFile(string inputFile, string key)
{
Console.WriteLine("Inside DecryptFile function");
Console.WriteLine("Inside DecryptFile try statements");
string ext = Path.GetExtension(inputFil e);
string outputFile = inputFile.Replace(ext, "_enc" + ext);
//Prepare the file for decryption by getting it into a stream
FileStream fsCrypt = new FileStream(inputFile, FileMode.Open);
//Setup the Decryption Standard using Read mode
AesManaged aesCrypto = new AesManaged();
CryptoStream cs = new CryptoStream(fsCrypt, aesCrypto.CreateDecryptor( ), CryptoStreamMode.Read);
//Write the decrypted file stream
FileStream fsOut = new FileStream(outputFile, FileMode.Create);
try
{
int data;
while ((data = cs.ReadByte()) != -1)
{ fsOut.WriteByte((byte)data ); }
//Close all the Writers
fsOut.Close();
cs.Close();
fsCrypt.Close();
//Delete the original file
File.Delete(inputFile);
//Rename the encrypted file to that of the original
File.Copy(outputFile, inputFile);
File.Delete(outputFile);
}
catch (Exception ex)
{
throw ex;
}
finally
{
fsOut = null;
cs = null;
fsCrypt = null;
}
}
}
}
The program works fine till EncryptFile function is called and it encrypts the selected files when the selected Bluetooth device goes out of range. But when the selected Bluetooth device comes back in range and the DecryptFile function is called , a CryptographicException was unhandled error comes. when i view for additional details , it shows {"Padding is invalid and cannot be removed."}. What might be the errorin the program and how to resolve it. Please help me out.
Check-range-form.PNG
in-range.PNG
out-of-range.PNG
Decryptfile-error.PNG
Here is the source code :
using System;
using System.Collections.Generic
using System.Windows.Forms;
using InTheHand.Net.Sockets;
using System.Threading;
using System.Data.SqlClient;
using System.IO;
using System.Security.Cryptograp
using System.Text;
namespace Folder_Security
{
public partial class EncryptDecryptTool : Form
{
List<string> discoverable_devices_items
BluetoothDeviceInfo[] paired_devices;
string key;
public EncryptDecryptTool()
{
InitializeComponent();
cmb_UsersDisplay.Text = "Device List";
key = generateKey();
}
private const string _IV = "EncryptDecryptFile";
private string generateKey()
{
AesCryptoServiceProvider aesCrypto = (AesCryptoServiceProvider)
return ASCIIEncoding.ASCII.GetStr
}
private void start_devices_scan()
{
discoverable_devices_items
Thread bluetoothScanThread = new Thread(new ThreadStart(devices_scan))
bluetoothScanThread.Start(
}
private void devices_scan()
{
BluetoothClient client = new BluetoothClient();
paired_devices = client.DiscoverDevicesInRa
Console.Write("printing device list...");
foreach(BluetoothDeviceInf
{
Console.Write("Inside for each1");
Console.WriteLine(device.T
}
foreach (BluetoothDeviceInfo d2 in paired_devices)
{
discoverable_devices_items
}
}
private void updateUI(string message)
{
Func<int> del = delegate ()
{
txt_Response.AppendText(me
return 0;
};
Invoke(del);
}
private void btn_Check_for_Range_Click(
{
start_devices_scan();
Thread.Sleep(15000);
items_compare(discoverable
}
private static void DirSearch(string sDir)
{
try
{
foreach (string d in Directory.GetDirectories(s
{
foreach (string f in Directory.GetFiles(d))
{
Console.WriteLine(f);
}
DirSearch(d);
Console.WriteLine(d);
}
}
catch (System.Exception excpt)
{
Console.WriteLine(excpt.Me
}
}
private void items_compare(List<string>
{
string selected_item = this.cmb_UsersDisplay.GetI
SqlConnection con = new SqlConnection(@"Data Source = (LocalDB)\MSSQLLocalDB; AttachDbFilename = C:\Users\HP\Documents\Visu
con.Open();
string Sql = "select File_Path from dbo.Devices where DeviceName='" + selected_item + "'";
SqlCommand cmd = new SqlCommand(Sql, con);
SqlDataReader Dr = cmd.ExecuteReader();
if (Dr.Read())
{
Console.WriteLine(Dr[0].To
}
string path = Dr[0].ToString();
DirSearch(path);
foreach (string f in Directory.GetFiles(path))
{
Console.WriteLine(f);
}
if (selected_item == "")
{
MessageBox.Show("Please select a device from the list");
}
if (discoverable_devices_item
{
updateUI("Selected paired device is in range");
foreach (string f in Directory.GetFiles(path))
{
DecryptFile(f, key);
}
}
else
{
updateUI("Selected paired device is now out of range");
foreach (string f in Directory.GetFiles(path))
{
Console.WriteLine("Inside foreach");
EncryptFile(f, key);
}
}
con.Close();
}
private static void EncryptFile(string inputFile, string key)
{
Console.WriteLine("Inside EncryptFile function");
try
{
Console.WriteLine("Inside EncryptFile try statements");
string ext = Path.GetExtension(inputFil
string outputFile = inputFile.Replace(ext, "_enc" + ext);
//Prepare the file for encryption by getting it into a stream
string cryptFile = outputFile;
FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create);
//Setup the Encryption Standard using Write mode
AesManaged aesCrypto = new AesManaged();
CryptoStream cs = new CryptoStream(fsCrypt, aesCrypto.CreateEncryptor(
//Write the encrypted file stream
FileStream fsIn = new FileStream(inputFile, FileMode.Open);
int data;
while ((data = fsIn.ReadByte()) != -1)
{
cs.WriteByte((byte)data);
}
//Close all the Writers
fsIn.Close();
cs.Close();
fsCrypt.Close();
//Delete the original file
File.Delete(inputFile);
//Rename the encrypted file to that of the original
File.Copy(outputFile, inputFile);
File.Delete(outputFile);
}
catch (Exception ex)
{
Console.WriteLine(ex.Messa
}
}
private static void DecryptFile(string inputFile, string key)
{
Console.WriteLine("Inside DecryptFile function");
Console.WriteLine("Inside DecryptFile try statements");
string ext = Path.GetExtension(inputFil
string outputFile = inputFile.Replace(ext, "_enc" + ext);
//Prepare the file for decryption by getting it into a stream
FileStream fsCrypt = new FileStream(inputFile, FileMode.Open);
//Setup the Decryption Standard using Read mode
AesManaged aesCrypto = new AesManaged();
CryptoStream cs = new CryptoStream(fsCrypt, aesCrypto.CreateDecryptor(
//Write the decrypted file stream
FileStream fsOut = new FileStream(outputFile, FileMode.Create);
try
{
int data;
while ((data = cs.ReadByte()) != -1)
{ fsOut.WriteByte((byte)data
//Close all the Writers
fsOut.Close();
cs.Close();
fsCrypt.Close();
//Delete the original file
File.Delete(inputFile);
//Rename the encrypted file to that of the original
File.Copy(outputFile, inputFile);
File.Delete(outputFile);
}
catch (Exception ex)
{
throw ex;
}
finally
{
fsOut = null;
cs = null;
fsCrypt = null;
}
}
}
}
The program works fine till EncryptFile function is called and it encrypts the selected files when the selected Bluetooth device goes out of range. But when the selected Bluetooth device comes back in range and the DecryptFile function is called , a CryptographicException was unhandled error comes. when i view for additional details , it shows {"Padding is invalid and cannot be removed."}. What might be the errorin the program and how to resolve it. Please help me out.
Check-range-form.PNG
in-range.PNG
out-of-range.PNG
Decryptfile-error.PNG
ASKER
But what should values should I define for the variables Key and IV that you have told me to pass to the aesCrypto.Key and aesCrypto.IV,rather than creating a random key and IV values?
ASKER
By what values I must initialize the variables Key and IV?
Update:
You can still create a random key and IV, but you need to save them, so the code uses the same key and iv for encrypting and decrypting. The current code isn't doing that, and that's why you can't decrypt. For example:
1. Code calls EncryptFile() which generates a new key "ABC" and IV "123".
2. Code calls DecryptFile() which generates another new key, say "EFG" and IV, "456"
So the decrypt fails because the file was encrypted with key "ABC/123", not "EFG/456".
You're already creating a key in the constructor. That's probably what you want to use. However, don't convert it into a string, just save the raw binary value.
Also, don't use a static IV. It's less secure.
Since you need to create both a key and IV, may as well do that in the constructor like this:
Then when you encrypt, apply the saved key and iv like this:
AesManaged aesCrypto = new AesManaged();
aesCrypto.Key = key;
aesCrypto.IV = iv;
CryptoStream cs = new CryptoStream(fsCrypt, aesCrypto.CreateEncryptor( ), CryptoStreamMode.Write);
Do the same thing when you decrypt.
But what should values should I define for the variables Key and IV that you have told me to pass to the aesCrypto.Key and aesCrypto.IV,rather than creating a random key and IV values?
You can still create a random key and IV, but you need to save them, so the code uses the same key and iv for encrypting and decrypting. The current code isn't doing that, and that's why you can't decrypt. For example:
1. Code calls EncryptFile() which generates a new key "ABC" and IV "123".
2. Code calls DecryptFile() which generates another new key, say "EFG" and IV, "456"
So the decrypt fails because the file was encrypted with key "ABC/123", not "EFG/456".
key = generateKey();
You're already creating a key in the constructor. That's probably what you want to use. However, don't convert it into a string, just save the raw binary value.
private const string _IV = "EncryptDecryptFile";
Also, don't use a static IV. It's less secure.
Since you need to create both a key and IV, may as well do that in the constructor like this:
byte[] iv;
byte[] key;
public EncryptDecryptTool()
{
// ..... other code
AesCryptoServiceProvider aesCrypto = (AesCryptoServiceProvider)AesCryptoServiceProvider.Create();
key = aesCrypto.Key;
iv = aesCrypto.IV;
}
Then when you encrypt, apply the saved key and iv like this:
AesManaged aesCrypto = new AesManaged();
aesCrypto.Key = key;
aesCrypto.IV = iv;
CryptoStream cs = new CryptoStream(fsCrypt, aesCrypto.CreateEncryptor(
Do the same thing when you decrypt.
ASKER
Now I am trying to use this code for enrypt and decrypt functions:
private static void EncryptFile(string inputFile, byte[] key, byte[] Iv)
{
Console.WriteLine("Inside EncryptFile function");
string ext = Path.GetExtension(inputFil e);
string targetFile = inputFile.Replace(ext, "_enc" + ext);
AesManaged AES = new AesManaged();
AES.Key = key;
AES.IV = Iv;
using (MD5CryptoServiceProvider MD5 = new MD5CryptoServiceProvider() )
{
AES.KeySize = MD5.HashSize;
AES.BlockSize = MD5.HashSize;
AES.IV = MD5.ComputeHash(Iv);
AES.Key = MD5.ComputeHash(key);
}
using (FileStream reader = new FileStream(inputFile, FileMode.Open, FileAccess.Read))
{
using (FileStream writer = new FileStream(targetFile, FileMode.OpenOrCreate, FileAccess.Write))
{
using (CryptoStream cs = new CryptoStream(writer, AES.CreateEncryptor(), CryptoStreamMode.Write))
{
int bufferSize = 4096;
byte[] buffer = new byte[bufferSize];
int bytesRead;
do
{
bytesRead = reader.Read(buffer, 0, bufferSize);
if (bytesRead != 0)
{
cs.Write(buffer, 0, bufferSize);
}
}
while (bytesRead != 0);
cs.FlushFinalBlock();
}
}
}
}
private static void DecryptFile(string inputFile, byte[] key, byte[] Iv)
{
Console.WriteLine("Inside DecryptFile function");
string ext = Path.GetExtension(inputFil e);
string targetFile = inputFile.Replace(ext, "_enc" + ext);
AesManaged AES = new AesManaged();
AES.Key = key;
AES.IV = Iv;
using (MD5CryptoServiceProvider MD5 = new MD5CryptoServiceProvider() )
{
AES.KeySize = MD5.HashSize;
AES.BlockSize = MD5.HashSize;
AES.IV = MD5.ComputeHash(Iv);
AES.Key = MD5.ComputeHash(key);
}
using (FileStream reader = new FileStream(inputFile, FileMode.Open, FileAccess.Read))
{
using (FileStream writer = new FileStream(targetFile, FileMode.OpenOrCreate, FileAccess.Write))
{
using (CryptoStream cs = new CryptoStream(reader, AES.CreateDecryptor(), CryptoStreamMode.Read))
{
int bufferSize = 4096;
byte[] buffer = new byte[bufferSize];
int bytesRead;
do
{
bytesRead = cs.Read(buffer, 0, bufferSize);
if (bytesRead != 0)
{
writer.Write(buffer, 0, bytesRead);
}
}
while (bytesRead != 0);
}
}
}
}
Also I have set the values of Iv and key as specified by you in the code:
byte[] key;
byte[] Iv;
public EncryptDecryptTool()
{
InitializeComponent();
cmb_UsersDisplay.Text = "Device List";
key = generatekey();
}
private byte[] generatekey()
{
AesCryptoServiceProvider aesCrypto = (AesCryptoServiceProvider) AesCryptoS erviceProv ider.Creat e();
key = aesCrypto.Key;
Iv = aesCrypto.IV;
return key;
}
But Now i am getting an error "Length of the data to decrypt is invalid" at the line bytesRead = cs.Read(buffer, 0, bufferSize); in the DecryptFile function. What may be the way to rectify this error . Please help me out.
private static void EncryptFile(string inputFile, byte[] key, byte[] Iv)
{
Console.WriteLine("Inside EncryptFile function");
string ext = Path.GetExtension(inputFil
string targetFile = inputFile.Replace(ext, "_enc" + ext);
AesManaged AES = new AesManaged();
AES.Key = key;
AES.IV = Iv;
using (MD5CryptoServiceProvider MD5 = new MD5CryptoServiceProvider()
{
AES.KeySize = MD5.HashSize;
AES.BlockSize = MD5.HashSize;
AES.IV = MD5.ComputeHash(Iv);
AES.Key = MD5.ComputeHash(key);
}
using (FileStream reader = new FileStream(inputFile, FileMode.Open, FileAccess.Read))
{
using (FileStream writer = new FileStream(targetFile, FileMode.OpenOrCreate, FileAccess.Write))
{
using (CryptoStream cs = new CryptoStream(writer, AES.CreateEncryptor(), CryptoStreamMode.Write))
{
int bufferSize = 4096;
byte[] buffer = new byte[bufferSize];
int bytesRead;
do
{
bytesRead = reader.Read(buffer, 0, bufferSize);
if (bytesRead != 0)
{
cs.Write(buffer, 0, bufferSize);
}
}
while (bytesRead != 0);
cs.FlushFinalBlock();
}
}
}
}
private static void DecryptFile(string inputFile, byte[] key, byte[] Iv)
{
Console.WriteLine("Inside DecryptFile function");
string ext = Path.GetExtension(inputFil
string targetFile = inputFile.Replace(ext, "_enc" + ext);
AesManaged AES = new AesManaged();
AES.Key = key;
AES.IV = Iv;
using (MD5CryptoServiceProvider MD5 = new MD5CryptoServiceProvider()
{
AES.KeySize = MD5.HashSize;
AES.BlockSize = MD5.HashSize;
AES.IV = MD5.ComputeHash(Iv);
AES.Key = MD5.ComputeHash(key);
}
using (FileStream reader = new FileStream(inputFile, FileMode.Open, FileAccess.Read))
{
using (FileStream writer = new FileStream(targetFile, FileMode.OpenOrCreate, FileAccess.Write))
{
using (CryptoStream cs = new CryptoStream(reader, AES.CreateDecryptor(), CryptoStreamMode.Read))
{
int bufferSize = 4096;
byte[] buffer = new byte[bufferSize];
int bytesRead;
do
{
bytesRead = cs.Read(buffer, 0, bufferSize);
if (bytesRead != 0)
{
writer.Write(buffer, 0, bytesRead);
}
}
while (bytesRead != 0);
}
}
}
}
Also I have set the values of Iv and key as specified by you in the code:
byte[] key;
byte[] Iv;
public EncryptDecryptTool()
{
InitializeComponent();
cmb_UsersDisplay.Text = "Device List";
key = generatekey();
}
private byte[] generatekey()
{
AesCryptoServiceProvider aesCrypto = (AesCryptoServiceProvider)
key = aesCrypto.Key;
Iv = aesCrypto.IV;
return key;
}
But Now i am getting an error "Length of the data to decrypt is invalid" at the line bytesRead = cs.Read(buffer, 0, bufferSize); in the DecryptFile function. What may be the way to rectify this error . Please help me out.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Doesn't look like you're applying a Key when creating the encryptor (or decryptor). I'd guess it's creating a random key each time. (Same applies to IV). That would explain the error, since you must use the same key to decrypt as was used to encrypt.
Try applying the key and IV using
aesCrypto.Key = Key;
aesCrypto.Key = IV;
or the overloaded CreateEncryptor(key, iv) method.