namespace SaurabhCrypto { using System; using System.Drawing; using System.ComponentModel; using System.WinForms; using System.IO ; using System.Security; using System.Security.Cryptography; // Class which will Encrypt and Decrypt files public class SymEncryptor : System.WinForms.Form { // Required by the Win Forms designer private System.ComponentModel.Container components; private System.WinForms.SaveFileDialog saveFileDialog1; private System.WinForms.OpenFileDialog openFileDialog1; private System.WinForms.StatusBar statusBar1; private System.WinForms.Button decryptb; private System.WinForms.Button encryptb; private System.WinForms.RadioButton radioButton2; private System.WinForms.RadioButton radioButton1; private System.WinForms.Label infol; private System.WinForms.TextBox passt; private System.WinForms.Label passl; private System.WinForms.Button saveb; private System.WinForms.Button openb; private System.WinForms.TextBox savet; private System.WinForms.TextBox opent; private System.WinForms.Label savel; private System.WinForms.Label openl; //these byte arrays will contain the 'KEY' and 'Vector' used in //encryption and decryption . private byte[] symKey ; private byte[] symIV ; //This is the constructor of the class. //It calls only one method 'InitlizeComponent' which draws the WinForm . public SymEncryptor() { // Call the method to make the WinForm InitializeComponent(); } //This method is called when the WinForm exits and it //Cleans up any resources being used public override void Dispose() { base.Dispose(); components.Dispose(); } // The main entry point for the application. public static void Main(string[] args) { Application.Run(new SymEncryptor()); } //Method called from the constructor //It initialises all the WinForm components private void InitializeComponent() { //Here the WinForm components are placed //I have removed this code for explanation purpose //You can get the full code when you download the example } //This method is called when the 'Decrypt' button is clicked by the user. //It first checks the file type and then calls the required methods to //decrypt the file . protected void decryptb_click(object sender, System.EventArgs e) { //call the method 'ValidateBoxes()' which checks all the fields of the WinForm and //returns a 'true' if everything is filled properly //if there are some errors it returns a 'false' if(ValidateBoxes()) { //if all the Fields of the WinForm are valid then call the method 'DecryptData() ' //this method takes care of all the decrypting to do DecryptData(); //after decrypting set all the TextBoxes to their default values //this is not necessary but more user friendly... opent.Text=""; savet.Text="" ; passt.Text="" ; radioButton1.Checked=true ; } } //This method is called when the 'Encrypt' button is pressed in the WinForm. //It checks the file and encrypts it according to the algoritm specified by the user. protected void encryptb_click(object sender, System.EventArgs e) { //a method 'ValidateBoxes()' is called which returns a true only if all the fields of the //WinForm are properly filled if(ValidateBoxes()) { //Here we make a call the a method 'GenerateKee(bool variable)' //this method takes in a bool value and generates the Hash 'Key' //and 'Initialization Vector' which will be used in encryption / decryption //it returns a 'true' if everything is properly generated //Here we Pass the 'radioButton1.Checked' as an argument since the method generates //'key' and 'vector' depending on which algorithm to use //so if 'radioButton1.Checked=true' it means we are using the 'DES' algorithm //else we are using the 'RC2' algorithm if(GenerateKee(radioButton1.Checked)) { //call the method 'EncryptData()' which will take care of all the encrypting EncryptData() ; //Set the TextBoxes to their default values //this can be omitted , but its more user friendly opent.Text=""; savet.Text="" ; passt.Text="" ; radioButton1.Checked=true ; } } } //This method is called when the 'Save' button is clicked // It opens a 'SaveFileDialog' and takes the file to be saved to protected void saveb_click(object sender, System.EventArgs e) { //different parameters of the 'SaveFileDialog' are set here saveFileDialog1.Filter = "All files (*.*)|*.* | Encryptor files (*.enc)|*.enc" ; saveFileDialog1.FilterIndex = 2 ; saveFileDialog1.RestoreDirectory = true ; //check if the user has already typed a file to save in the TextBox if(savet.Text!="") { //if the user has typed a filename in the TextBox then assign that //to the dialogs 'FileName' property saveFileDialog1.FileName=savet.Text ; } if(saveFileDialog1.ShowDialog() == DialogResult.OK) { //when the user presses 'Ok' on the 'SaveFileDialog' then set the //text of the TextBox 'savet' to the file selected savet.Text = saveFileDialog1.FileName ; } } //This method is called when the 'Open' button is clicked by the user protected void openb_click(object sender, System.EventArgs e) { //Set the various properties of the 'OpenFileDialog' openFileDialog1.Filter = "Encryptor files (*.enc)|*.enc|All files (*.*)|*.*" ; openFileDialog1.FilterIndex = 2 ; openFileDialog1.RestoreDirectory = true ; //check if the user has already typed the file to open in the textbox if(opent.Text!="") { //Then assign the Dialog the Filename from the TextBox openFileDialog1.FileName = opent.Text ; } if(openFileDialog1.ShowDialog() == DialogResult.OK) { //if the user presses 'Ok' in the 'OpenFileDialog' then assign the //file selected to the textbox opent.Text = openFileDialog1.FileName ; } } //this method checks if any of the TextBoxes are left empty by the user //and it generates the error required //it returns 'true' if all values are proper private bool ValidateBoxes() { //check the 'Open' File textbox if(opent.Text=="") { MessageBox.Show("Please Enter the file to Encrypt / Decrypt !") ; return false ; } //check the 'Save' file textbox if(savet.Text=="") { MessageBox.Show("Please Enter the filename to save !") ; return false ; } //check the password textbox if(passt.Text=="") { MessageBox.Show("Please Enter the Password Encrypt / Decrypt your file with.") ; return false ; } //if everything is alright return true return true ; } //This Method computes the 'Key' and the 'Vector' to be used in encrypting / decrypting. //It generates the key according to the algorithm. //It returns is key generation is successful // If the algorithm to be used is 'DES' then it generates a 64bit Key and 64bit Vector //from the provided 'Password' .Then this is stored in to a 'byte' array having length '8'. //since 1 byte = 8 bits , hence a byte array having length '8' will contain a key of //8 x 8 =64 bits. //We use a 64bit key since DES supports a minimum 64 bit key // If the algorithm to be used is 'RC2' then it generates a 40bit Key and a 40 bit Vector //from the provided 'Password'. //We use a 40 bit key here since RC2 supports a minimum 40 bit key //(it does not support a 64bit key). private bool GenerateKee(bool isDES) { //try-catch block try { //store the password in a string string pass =passt.Text ; int i ; int len ; //convert the password in to a Char array char[] cp = pass.ToCharArray() ; len = cp.GetLength(0) ; //initialize a byte array byte[] bt = new byte[len] ; //convert the Char array of the Password to a byte array for(i=0 ; i//if we are producing a Key-Vector for the 'DES' algorithm if(isDES) { //initialize the byte arrays which will contain the 'Key' and the 'Vector' //to a length of '8' (see above why we use a array of length '8') symKey=new byte[8] ; symIV = new byte[8] ; //make a instance of the class 'SHA1_CSP()' //this class is useful in converting 'byte' into 'Hash'. SHA1_CSP sha = new SHA1_CSP() ; //write the Hash of the byte array containing the password sha.Write(bt) ; //close the stream sha.CloseStream() ; //now Initialize the 'Key' array with the lower 64bits of the Hash of //the 'Password' provided by the user for(i=0 ; i<8 color="#0000ff">//initialize the 'Vector' array with the higher 64 bits of Hash of the //'Password' provided by the user for(i=8 ; i<16 color="#0000ff">//if the algorithm is 'RC2' then generate the following Key //initialize the Key and Vector arrays to a length of '5' (see above why we use '5') symKey=new byte[5] ; symIV = new byte[5] ; //make a instance of the class 'SHA1_CSP' //this class writes the hash of a given byte SHA1_CSP sha = new SHA1_CSP() ; //write the Hash of the byte array containing the user password sha.Write(bt) ; //close the stream sha.CloseStream() ; //now Initialize the Key array to lower 40 bits of the Hash of the 'Password'. for(i=0 ; i<5 color="#0000ff">//initilize the Vector array to 40bits of hash for(i=5 ; i<10 color="#0000ff">//since every thing went properly return 'true' return true ; } catch(Exception e) { MessageBox.Show("A Exception Occured in Generating Keys :"+e.ToString()) ; //return false since there was a error return false ; } } //This method encrypts the given input file in either of the 2 algorithms 'DES' or 'RC2'. //Then it writes out the encrypted file //This method first reads the input file to check to see if its already encrypted by this //same program. If its already encrypted it gives a error. //According to the algorithm specified it then encrypts the file. //Also in the first 8 bytes of the new Encrypted it writes out "[saudes]" or "[saurc2]" //This is done so the while decrypting the program can know which algorithm was used to // encrypt the file. Also it used to check if the file has already encrypted private void EncryptData() { //try-catch block try { bool algo ; //a boolean variable to check which algorithm to use in encrypting //open the 'FileStream' on the file to be encrypted FileStream fin = new FileStream(opent.Text , FileMode.Open , FileAccess.Read) ; //Make a file to save the encrypted data to and open a 'FileStream' on it FileStream fout = new FileStream(savet.Text , FileMode.OpenOrCreate , FileAccess.Write); //set the position of the 'cursor' to the start of the file fout.SetLength(0) ; //make a byte array of the size 64 bits //this is called the 'Buffer Size' of the algorithm //i.e. while encrypting blocks of the size 64bits are processed at a single time //later other blocks are of the same size. //we use 64bits because both 'DES' and 'RC2' both algorithms have 64 bit 'Buffer Size' byte[] bin = new byte[4096] ; //set the total length of the file to me encrypted to a variable long totlen = fin.Length ; long rdlen=0; int len ; //the code below is used to check if the file has already been encrypted //make a byte array of length '4' byte[] tag = new byte[4]; //read the first 4 bytes from the file to be encrypted fin.Read(tag,0,tag.Length); //if it contains the chars "[sau" then it has been already encrypted by this program if ((tag[0]==(byte)'[')&&(tag[1]==(byte)'S')&&(tag[2]==(byte)'a')&&(tag[3]==(byte)'u')) { //generate a error to let the user know of the error MessageBox.Show("This file is already Encrypted or in Invalid format!") ; statusBar1.Text="Error - Invalid File Format !!" ; } else { //if the file if ok the proceed with encryption statusBar1.Text="Encrypting..."; //set the file read cursor back to the 'Beginning' of the opened file fin.Seek(0, SeekOrigin.Begin); } //make a object of the class 'SymmetricAlgorithm' SymmetricAlgorithm des ; if(radioButton1.Checked) { //if the algorithm to be used is 'DES' then initialize the 'SymmetricAlgorithm' //to 'DES_CSP' des = new DES_CSP(); //set the variable to true because we are using 'DES' algorithm. algo=true ; } else { //if the algorithm to be used is 'RC2' then initialize the variable 'des' //to 'RC2_CSP' des=new RC2_CSP() ; //set the key size of the algorithm to 40 bits since we are using a 40 bit key des.KeySize=40 ; //uncomment the below code to find out the bits of keys supported by RC2 algorithm /*KeySizes[] ks = des.LegalKeySizes ; Console.WriteLine("Key Sizes Supported :") ; Console.WriteLine("Minimum Size:" +ks[0].MinSize) ; Console.WriteLine("Skip size of key: "+ks[0].SkipSize) ; Console.WriteLine("Maximum Size: "+ks[0].MaxSize) ; */ //set the bool variable to false since we are using the RC2 algorithm algo=false ; } //Make a object of the inner class 'StoreCryptoStream' we pass the bool variable //containing the algorithm information and the FileStream StoreCryptoStream scs = new StoreCryptoStream(algo,fout); //make an object of the 'SymmetricStreamEncryptor' class and pass it the //'Key' and the 'Vector' this stream helps to encrypt data according to the algorithm SymmetricStreamEncryptor sse = des.CreateEncryptor(symKey, symIV); // a little extra feature here to show how to compose crypto // components that support ICryptoStream SHA1_CSP sha = new SHA1_CSP(); // wire up the encryptor - hash - StoreCryptoStream sse.SetSink(sha); sha.SetSource(sse); sha.SetSink(scs); scs.SetSource(sha); //read from the file to encrypt while (rdlen < color="#0000ff">//set the number of bytes read len = fin.Read(bin,0,4096); //write the encrypted data sse.Write(bin,0,len); //increase the size of bytes read rdlen = rdlen + len; } //free up the resources sse.CloseStream(); fin.Close(); fout.Close() ; statusBar1.Text="Encryption Compelete !" ; } catch(Exception e) { MessageBox.Show("An exception occured while encrypting :"+e.ToString()) ; statusBar1.Text="Error" ; } } //This method decrypts the given input file in either of the 2 algorithms 'DES' or 'RC2'. //Then it writes out the decrypted file //This method first reads the input file to check to see if its encrypted by which //algorithm. then it automatically decrypts the file. //It reads the first 8 bytes of the encrypted file to find the custom tag that we place //while encrypting. //If it finds "[saudes]" it uses the 'DES' algorithm to decrypt //If it finds "[saurc2]" it uses the 'RC2' algorithm to decrypt private void DecryptData() { //try-catch block try { statusBar1.Text="Decrypting...." ; //open file streams to the input and outfiles FileStream fin = new FileStream(opent.Text , FileMode.Open , FileAccess.Read) ; FileStream fout = new FileStream(savet.Text ,FileMode.OpenOrCreate ,FileAccess.Write); fout.SetLength(0) ; //a variable to check the validity of the input file bool filecheck = false ; //make a byte array of the size 64 bits //this is called the 'Buffer Size' of the algorithm //i.e. while encrypting blocks of the size 64bits are processed at a single time //later other blocks are of the same size. //we use 64bits because both 'DES' and 'RC2' both algorithms have 64 bit 'Buffer Size' byte[] bin = new byte[4096] ; long totlen = fin.Length ; long rdlen=8; int len ; // declare a object of type 'SymmetricAlgorithm' SymmetricAlgorithm des ; //set a temporary variable to length '8' (we use '8' since the size of //the tag put in the file is 8) byte[] tag = new byte[8]; //read the first 8 bytes from the input file to check which algorithm is used to //encrypt the file fin.Read(tag,0,tag.Length); if ((tag[0]==(byte)'[')&&(tag[1]==(byte)'S')&&(tag[2]==(byte)'a')&&(tag[3]==(byte)'u') &&(tag[4]==(byte)'d')&&(tag[5]==(byte)'e')&&(tag[6]==(byte)'s')&&(tag[7]==(byte)']')) { //If this is true then the 'DES' algorithm has been used to encrypt the file //so set the variable 'des' to new 'DES_CSP' des = new DES_CSP() ; //set the variable to true since the file is encrypted filecheck=true ; //generate the Key and Vector from the given password //we send 'true' here since the algorithm used is 'DES' GenerateKee(true) ; } else if((tag[0]==(byte)'[')&&(tag[1]==(byte)'S')&&(tag[2]==(byte)'a') &&(tag[3]==(byte)'u')&&(tag[4]==(byte)'r')&&(tag[5]==(byte)'c') &&(tag[6]==(byte)'2')&&(tag[7]==(byte)']')) { //if this is true then the 'RC2' algorithm has been used to encrypt the file //so we set the variable 'des' to new 'RC2_CSP' des = new RC2_CSP() ; //set the keysize of the algorithm des.KeySize=40 ; //set the variable to true since it is encrypted filecheck=true ; //generate the Key and Vector from the password given by the user //we pass false here since we are using 'RC2' algorithm GenerateKee(false) ; } else { MessageBox.Show("File Error !! File is not encrypted by SymEncryptor !!") ; //set the des to null so no encryption occurs des=null ; statusBar1.Text="Error "; } //if the file is encrypted then decrypt it if(filecheck){ //create a object of the inner class 'StoreCryptoStream' //we pass it the FileStream StoreCryptoStream scs = new StoreCryptoStream(fout); //make a object of this stream passing the Key and Vector //we use this stream since it helps us decrypt data from a //encrypted file SymmetricStreamDecryptor ssd = des.CreateDecryptor(symKey, symIV); //set up the streams ssd.SetSink(scs); scs.SetSource(ssd); //read the full encrypted file and decrypt while (rdlen < color="#0000ff">//set the length of the number of bytes read len = fin.Read(bin,0,4096); //write the decrypted data ssd.Write(bin,0,len); //increase the total read bytes variable rdlen = rdlen + len; } //free up the resources ssd.CloseStream(); } fin.Close(); fout.Close(); statusBar1.Text="Decryption Compelete" ; } catch(Exception e) { MessageBox.Show("An exception occured while decrypting :"+e.ToString()) ; statusBar1.Text="Error" ; } } //This is a inner class which Implements the 'ICryptoStream' interface //we write this class so that it will provide us with a custom stream //which will write and read the way we want it to public class StoreCryptoStream : ICryptoStream { //two byte arrays containing the bytes to be written while encrypting static byte[] tag1 = {(byte)'[',(byte)'S',(byte)'a',(byte)'u' ,(byte)'d' ,(byte)'e',(byte)'s' ,(byte)']'}; static byte[] tag2= {(byte)'[',(byte)'S',(byte)'a',(byte)'u' ,(byte)'r' ,(byte)'c',(byte)'2' ,(byte)']'}; FileStream fs; //This is the constructor of this class //it takes 2 parameters //1)a bool varable to indicate which algorithm has called it //if it 'true' then 'DES' has called it , if its 'false' then //'RC2' has called it. //2)the FileStream to the output file public StoreCryptoStream(bool algo, FileStream fout) { fs = fout; if (algo){ //we are here since the variable 'algo' is 'true' indicating that 'DES' algorithm //is being used //hence it writes the byte array 'tag1' to the output file fs.Write(tag1,0,8); } else { //we are here since the variable 'algo' is 'false' indicating that 'RC2'algorithm //is being used //hence it writes the byte array 'tag2' to the output file fs.Write(tag2,0,8) ; } } //This is another constructor which takes one parameter "FileStream" //It is called from the decrypting method public StoreCryptoStream(FileStream fout) { fs=fout ; } //other methods which have to be implemented public virtual void CloseStream() {fs.Close();} public virtual void CloseStream(Object obj) {fs.Close();} public virtual void SetSink(ICryptoStream pstm) {} public virtual void SetSource(CryptographicObject co) {} public virtual ICryptoStream GetSink () {return null;} // Write routines just copy output to the target file public virtual void Write(byte[] bin) { int len = bin.GetLength(0); Write(bin, 0, len); } public virtual void Write(byte[] bin, int start, int len ) { fs.Write(bin,start,len); } }//StoreCryptoStream class }//SymEncryptor class } |
No comments:
Post a Comment