Link to home
Start Free TrialLog in
Avatar of Abhishek Modak
Abhishek ModakFlag for India

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.Cryptography;
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)AesCryptoServiceProvider.Create();
            return ASCIIEncoding.ASCII.GetString(aesCrypto.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.DiscoverDevicesInRange();
             Console.Write("printing device list...");
            foreach(BluetoothDeviceInfo device in paired_devices)
             {
                 Console.Write("Inside for each1");
                 Console.WriteLine(device.ToString());
             }
             foreach (BluetoothDeviceInfo d2 in paired_devices)
             {                
                     discoverable_devices_items.Add(d2.DeviceName);
             }
         }


        private void updateUI(string message)
        {
            Func<int> del = delegate ()
            {
                txt_Response.AppendText(message + 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_items);
 
         }


        private static void DirSearch(string sDir)
        {

            try
            {
                foreach (string d in Directory.GetDirectories(sDir))
                {

                    foreach (string f in Directory.GetFiles(d))
                    {
                        Console.WriteLine(f);
                    }

                    DirSearch(d);
                    Console.WriteLine(d);
                }

            }
            catch (System.Exception excpt)
            {
                Console.WriteLine(excpt.Message);
            }
        }
        private void items_compare(List<string> discoverable_devices_items)
         {
            string selected_item = this.cmb_UsersDisplay.GetItemText(this.cmb_UsersDisplay.SelectedItem);
            SqlConnection con = new SqlConnection(@"Data Source = (LocalDB)\MSSQLLocalDB; AttachDbFilename = C:\Users\HP\Documents\Visual Studio 2015\Projects\Folder_Security\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].ToString());

            }
            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_items.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(inputFile);
                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.Message);
            }
        }
        private static void DecryptFile(string inputFile, string key)
        {
            Console.WriteLine("Inside DecryptFile function");
           
            Console.WriteLine("Inside DecryptFile try statements");
            string ext = Path.GetExtension(inputFile);
            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
Avatar of _agx_
_agx_
Flag of United States of America image


AesManaged aesCrypto = new AesManaged();
CryptoStream cs = new CryptoStream(fsCrypt, aesCrypto.CreateEncryptor(), CryptoStreamMode.Write);

Open in new window


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.
Avatar of Abhishek Modak

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?
By what values I must initialize the variables Key and IV?
Update:
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;
        }

Open in new window


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.
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(inputFile);
            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(inputFile);
            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)AesCryptoServiceProvider.Create();
            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
Avatar of _agx_
_agx_
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial