.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.
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).
- System.IO.Compression
- System.Security.Cryptographic
- 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.
- CreateEntryFromFile(),
- ExtractToDirectory().
- 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 :
- Rijndael
- 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