WPF Zip Compression with Password Encryption

Rohit.Agrawal
Posted by in WPF category on for Advance level | Points: 250 | Views : 43408 red flag
Rating: 5 out of 5  
 1 vote(s)

.net 4.5 library has provided a new feature of compression, we can create our own zip without using third party software like winzip, winrar etc. While exploring about compression methods I found lots of articles available on how to exploit different compression classes to achieve multiple zipping operation, but none of the article available which shows how to enforce password in your zip and make it password protected. This is because Microsoft has not provided password protection feature in 4.5 zip library.


 Download source code for WPF Zip Compression with Password Encryption

Introduction

.net 4.5 library has provided a new feature of compression, we can create our own zip without using third party software like winzip, winrar etc. While exploring about compression methods I found lots of articles available on how to exploit different compression classes to achieve multiple zipping operation, but none of the article available which shows how to enforce password in your zip and make it password protected. This is because Microsoft has not provided password protection feature in 4.5 zip library.

This article provides you sufficient information to create a password protected zip using .net 4.5 library. The attached zip contains a working solution of zipping and unzipping the solution.

Objective

What we have done here is merge two different mechanism into one. We have dot net encryption libraries and we have compression library, we merge both the library and created a working solution which provides us the facility of zip with password protection.

We have first created a User Interface to guide our user to give correct inputs so that we don’t end up in exceptions while compressing or decompressing our files. The compression and decompression process is using our custom encryption and decryption methods. We have used Microsoft cryptography classes to encrypt and decrypt our files thus we have limited control over our custom encryption /decryption method. When we say word “limited control” this means we cannot control internal encryption algorithm used by RijndaelManaged class.

Let’s discuss the concept of how did we achieve the password protection mechanism when Microsoft does not have this support in 4.5 library.

To understand this we need to understand .net 4.5 compression classes and also .net cryptography. We have certain classes exposed for compression which can easily unzip and zip. These classes are under below namespaces. (Compression/Zip/Cryptography related content taken from Microsoft Site for information purpose only and hyperlink will redirect you to Microsoft site).

  1. System.IO.Compression
  2. System.Security.Cryptographic
  3. System.Security.Cryptographic.SymmetricAlgorithm

We have used ZipFile and ZipArchive class to create zip. Other developer can use any class as per their requirements.

ZipFileExtensions class has three extension methods with overloads.

  1. CreateEntryFromFile(),
  2. ExtractToDirectory().
  3. ExtractToFile().

These extension methods enable us to compress and decompress the contents of the file into zip or from zip to a file.

The ZipArchive class enables us to work with a package of compressed files.

We have used extension method CreateEntryFromFile() and CreateEntry() , these are used in an iteration to insert file and directory when zipping.

Another extension method is used ExtractToFile() in iteration to extract the files when unzipping.

ZipFile class provides .

The CreateEntry() method enables us to specify a directory hierarchy when adding the entry.

We have also used Zip.Open() method to open the zip in memory and iterate through its entries.

Encryption and Decryption

NameSpaces

  • System.Security.Cryptographic
  • System.Security.Cryptographic.SymmetricAlgorithm

Classes used for encryption/decryptions.

  • Rfc2898DeriveBytes
  • HMACSHA1 (Hash-based Message Authentication Code).
  • HMACSHA1
  • UnicodeEncoding:
  • RijndaelManaged
  • Rijndae
  • CryptoStream :

So till here we discuss about compression classes and cryptography classes now we will discuss about the password mechanism in our tool to achieve our password protected zip.

Solution

In a nutshell we are injecting a text file inside our zip. This text file will contain our key which is supplied as password for generating the zip file. For obvious security reasons this supplied password is encrypted before being appended in the text file.

After this we encrypt each file using the same password and add it into the zip file. The generated file will have all files encrypted which makes this zip safe from unauthorized access.

Let’s discuss in details how we achieve this:

Steps to create password

  • Create a file name Zip.Src
  • Encrypt the password string.
  • Append the encrypted string into Zip.Src file.
  • Insert file Zip.Src into zip.
  • Delete Zip.Src from system.

Password Injection & encrypting files

While processing our zip operation 1st we create a file named zip.src and appended this file with encrypted user’s password (we can always make this file name to some more unique name). The process of encrypting the user password is using an MD5CryptoServiceProvider encryption mechanism, we can add TripleDESCryptoServiceProvider for added security if required.

So once we have user password encrypted and appended in zip.src file, same would be inserted in our zip in its root folder. After this file is inserted the foreach loop will starts iterating other files and folders in the source folder and add them one by one. You must be thinking what happens to that Zip.src which is created and existed on your system and become vulnerable to security, well the code takes care of this file and deletes it from the system immediately once it is added in the zip.

One important point here to note is we are processing our files one by one why not all together? The reason is we are encrypting our each file before adding into zip. This way our zip is encrypted and it is of no use until the correct password of the zip is supplied.

The purpose of whole article is to encrypt the zip using .net 4.5 compression features, there may be more better algorithm available and can be replaced with my algorithm without much efforts.

    

 

Unzip

For unzipping we are first checking the “Overwrite Option” is selected or not. A user has an option of overwriting the existing file. If user do not select overwrite option and if file or folder is found the zip operation would not execute.

While unzipping first we search for our “zip.src” file inside the zip and extract it from the zip. We encrypt the supplied password and try to match the contents of zip.src file. If content matches, it confirms that the supplied password is the real password for this zip and we start processing our unzipping operation.

The code iterates the zip and extract file one at a time, the extracted files are decrypted earlier so again the supplied password is used as key for decryption. At last we get our full directory structure along with all files in same way it was before compressing/zipping.

      

Using the code

Explain the topic of the article with code and description

Block of code should be set style as "Code" like below.

      private void ExecuteZipOperation()
{
if (zipViewModel.Zip)
{
if (zipViewModel.Password != zipViewModel.ConfirmPassword)
{
errorList.Value.Append("Password and Confirm Password not matching");
return;
}
if (zipViewModel.Password.Length < 5)
{
errorList.Value.Append("Password length cannot be less then 5 characters");
return;
}
zipViewModel.OutputDirectory = zipViewModel.InputDirectory;
CreateEncryptedZip(new DirectoryInfo(zipViewModel.InputDirectory));
}
else
{
if (!zipViewModel.OverWrite && Directory.Exists(zipViewModel.OutputDirectory))
errorList.Value.AppendFormat(" {0} already Exists, please delete existing or check overwrite option.", zipViewModel.OutputDirectory);
else
UnZipEncryptedZip(Path.Combine(zipViewModel.InputDirectory, zipViewModel.InputZipName), zipViewModel.OutputDirectory);
}
}
                zipViewModel.OutputDirectory = zipViewModel.InputDirectory;
                CreateEncryptedZip(new DirectoryInfo(zipViewModel.InputDirectory));
            }
            else
            {
                if (!zipViewModel.OverWrite && Directory.Exists(zipViewModel.OutputDirectory))
                    errorList.Value.AppendFormat(" {0} already Exists, please delete existing or check overwrite option.", zipViewModel.OutputDirectory);
                else
                    UnZipEncryptedZip(Path.Combine(zipViewModel.InputDirectory, zipViewModel.InputZipName), zipViewModel.OutputDirectory);
            }
        }

private void CreateEncryptedZip(DirectoryInfo sourceDir)
{
try
{
CurrentFileCount = 0;
FileInfo info = new FileInfo(sourceDir.Name);
RootDirectory = sourceDir.FullName;
string sourceZipName = Path.Combine(sourceDir.FullName, zipViewModel.InputZipName);
File.Delete(sourceZipName);
using (ZipArchive modFile = ZipFile.Open(sourceZipName, ZipArchiveMode.Create))
{
if (!string.IsNullOrEmpty(zipViewModel.ConfirmPassword))
AddPasswordToZip(modFile);


TotalZipFileCount = sourceDir.GetFiles("*.*", SearchOption.AllDirectories).Count();
TotalZipFileCount += sourceDir.GetDirectories("*.*", SearchOption.AllDirectories).Count();

ZipProgressBarDialogResult result = ZipProgressBar.Run(zipViewModel.View as System.Windows.Window, "Zipping.. " + zipViewModel.InputZipName, (bw, we) =>
{

if (ZipProgressBar.ReportWithCancellationCheck(bw, we, CurrentFileCount++ * (100 / TotalZipFileCount), zipViewModel.OutputDirectory, "", TotalZipFileCount))
errorList.Value.Append("Operation Cancelled by user.");

Thread.Sleep(100);
FilesIterate(modFile, sourceDir);
DirectoryIterate(modFile, sourceDir, "");
ZipProgressBar.CheckForPendingCancellation(bw, we);
});
if (!string.IsNullOrEmpty(zipViewModel.ConfirmPassword))
File.Delete(Path.Combine(RootDirectory, "zip.src"));
}
}
catch (Exception ex)
{
errorList.Value.Append(ex.Message + "\n\r");
}
}

Zip Progress Dialog

To update the current processing, we have added a multithreaded progress bar, which display the file name which is currently processing. Also this progress bar dialog calculates the total percentage of completion and update accordingly.

This dialog box is added with another feature of cancelletaion option. A user can any time cancel the zip/unzip operation. The application would check the safe location and cancel the operation, this way the operation would always end in a systematic close thus eliminates the chances of creation of corrupt zip.

 

Zipping the Zip

There is another way to encrypt the zip which is bit faster where create a zip for the given folders or file and then encrypt that zip using the same mechanism. For this I have added two methods in my controller class naming "EncryptExistingZip()" and "DecryptExistingZip()". You can use these methods to add one zip and then encrypt it using encryption algorithm.

Conclusion

Although I have tested this tool with different folders and different types of files and it seems to be working correctly. This encryption and decryption logic requires fine tuning of other “ingredients” to make it work flawlessly. We may have to do a security review of the algorithms/and our implementation to actually see if the implementation is secure enough. In short this article talks about what is possible, and provides a simple algorithm to implement it.  The sample code is far away from production ready code, thus please review it thoroughly before shipping it (if you ever do :o ).  In case you find major flaws, please feel free to leave a note, so that the community could be benefitted.

At last before concluding my article, I would like to thank CodePlex community for their great work on MVVM & MEF solution, and dotNetFunda for providing and hosting great technical contents.

Thanks for reading the article. Please leave feedback/comments and happy coding!

Reference

MVVM Library from www.Waf.CodePlex.com

 

 

Page copy protected against web site content infringement by Copyscape

About the Author

Rohit.Agrawal
Full Name: Rohit Agrawal
Member Level: Starter
Member Status: Member
Member Since: 3/26/2014 3:57:13 AM
Country: India
Rohit Agrawal Email : Roheet.Agrawal@gmail.com
http://www.dotnetfunda.com
.net WPF/WinForm Professional. Working in IT industry from Last 7 Years.

Login to vote for this post.

Comments or Responses

Login to post response

Comment using Facebook(Author doesn't get notification)