Create a password protected zip file using zlib and ZipEngine

If you want to create a zip file from your C/C++ application the first solution you can consider is to use the famous zlib library. This library is open source, permissive license and can be compiled in different operating systems. It allow to easily manage a zip file but, currently, doesn't have the feature for create zip file password protected. To fill this lack another developer created a small wrapper over zlib allowing to bypass this problem. Let's go to see how to use both these product.



First you need to download zlib package from here and ZipEngine from here.


Once got the sources put all the files in your project folder. There are no duplicate files name than you can keep all the files in the same path. As said before ZipEngine is a wrapper over zlib. This mean using this wrapper you don't need to use the zlib directly but sources (or precompiled library) are needed.

The first step is to create a new zip file or open an existing one with the following code:

#include "zip.h"

zipFile hZipFile;

m_ZipFile = zipOpen("myfile.zip", APPEND_STATUS_CREATE);

if(m_hZipFile == NULL)
{
     // Error here
}

The flags available for open a zip file are:

  • APPEND_STATUS_CREATE
    Create a new zip file from scratch
  • APPEND_STATUS_CREATEAFTER
    If file exist the zip will be created at the end of the file (useful if the file contain a self extractor code)
  • APPEND_STATUS_ADDINZIP
    Open an existing zip file and add the new files inside it

Now we have our zip handle we can proceed to add file inside the zip just created.Basically the procudure used by ZipEgine is to create a new item inside the zip file with the name of the file you want to insert. Once successfully create this new item you can write the content of the file connected to the item name. However, since in your example we want to protect our zip file with a password, we need also to have the CRC value of the file content we are going to insert. This mean we have to precalculate the CRC by reading all the file content with the following algorithm:

unsigned long CRC = crc32(0L, Z_NULL, 0);
const unsigned int BufferSize = 10000;
unsigned char Buffer[BufferSize];
size_t nRead; 
FILE* pFile; 

pFile = fopen("myfile.bin", "rb");

while((nRead = fread(Buffer, BufferSize, 1, pFile)) > 0)
{
     CRC = crc32(CRC, Buffer, nRead);
}

fclose(pFile);

Now we have our CRC number we can proceed to create a new item inside the zip with the name the the file we want to store inside:

zip_fileinfo zipInfo;
int Result;

zipInfo.dosDate = 0;
zipInfo.tmz_date.tm_sec = 0;
zipInfo.tmz_date.tm_min = 10;
zipInfo.tmz_date.tm_hour = 12;
zipInfo.tmz_date.tm_mday = 01;
zipInfo.tmz_date.tm_mon = 05;
zipInfo.tmz_date.tm_year = 2012;
zipInfo.internal_fa = 0;
zipInfo.external_fa = 0;

Result = zipOpenNewFileInZip3(hZipFile, 
                              "myfile.bin", 
                              &zipInfo, NULL, 0, 
                              NULL, 0, NULL,
                              Z_DEFLATED, Z_DEFAULT_COMPRESSION,
                              0,
                              15,
                              8,
                              Z_DEFAULT_STRATEGY,
                              "mypassword",
                              CRC
                              );

if(Result != ZIP_OK)
{
       // Error 
}

The function for create a new item get a lot of params. If you wan to have more info regarding the meaning of these params you can check the documentation provided with the ZipEngine package. Anyway, if you are not interested to read boring info regarding how many ways you have for "customize" a zip file and want to simply create a normal zip file, you can get the params above and live happy. The zipInfo structure must be filled with the date and time of the item you want to be saved as file info (in the example we used random date and time). Once successfully create the item you can proceed to fill them with the content of the file:

const unsigned int BufferSize = 10000;
unsigned char Buffer[BufferSize];
size_t nRead; 
FILE* pFile; 

pFile = fopen("myfile.bin", "rb");

while(Result == ZIP_OK && (nRead = fread(Buffer, BufferSize, 1, pFile)) > 0)
{
      Result = zipWriteInFileInZip(hZipFile, Buffer, nRead);
}

fclose(pFile);

Operation done. Now close the item:

zipCloseFileInZip(hZipFile);

and, if you have no other file to add, close the zip file itself:

zipClose(hZipFile, NULL);

This is a really simply tutorial. As already said, if you are interested in more info regarding the possible params to change in zip file management, you can check the documentation provided with both products. If you are not interested at all simply get these pieces of code and used them in your software. Enjoy!


Comments

  1. Should I compile this code on C or C++?
    MinGW also gave me a bunch of errors. I guess that something is missing.

    ReplyDelete
  2. The code is in C style than you can compile in both C or C++. The snippets are very simple, which kind of error do you have?

    ReplyDelete
  3. Great thanks for the code! You saved my time.
    But I tried to zip non-empty file - without success.
    The decision was to replace
    fread(Buffer, BufferSize, 1, pFile) to:
    fread(Buffer, 1, BufferSize, pFile) or better fread(Buffer, sizeof(unsigned char), BufferSize, pFile)

    2 Vinícius:
    #include needed for fopen(), fread(), fwrite()

    ReplyDelete
  4. Thanks, this helped me enormously.
    A couple of points:
    1. I got a convenient combined package from https://github.com/bgbotond/zipengine including zlib and zipengine and a Visual Studio 2010 solution.
    2. It looks as though some renaming has gone on and in fact hZipFile, m_hZipFile and m_ZipFile are all supposed to be the same identifier.

    ReplyDelete
  5. Thanks, this code really saved my time! :-)

    ReplyDelete
  6. Hello guys, I am trying to use the password protection feature but this doesn't seem to function. The zip file is successfully created with a bin file inside it. I thought that the zip file itself should be Password protected and not the bin file inside it. When I am trying to open the bin file it ask me for a Password, but whatever I give as Input, the file is opened freely.
    1) Is there a way to create a Password protected zip file (and not the files inside it)?
    2) If not, why the Password protected bin file inside the zip files opens with any Password I give as Input? Any clues? Thanks

    ReplyDelete
  7. It seem really strange you can open your zip file using any password, it's the first time I hear something like this. About "global" password the "engine" of zip file protection allow you to set password for only some files inside a single zip and live free to open the others. This is the reasons the password doesn't cover the entire zip. If you want something like this you should move to .rar compression that allow what you need.

    ReplyDelete
  8. At first, thank you for your fast response. Actually, the password protection of the file-files inside the zip is ok for me. The problem is that it opens with any Password given. Can you please guide me to fix this issue? Thanks in advance.

    ReplyDelete
  9. I'm sorry but I really don't know how to fix your problem since is the first time I hear about a zip password protected file that can be opened using any password. The only suggestion I can give is to verify again if you followed all the steps explained in this post...

    ReplyDelete
  10. Hello, I followed the tutorial. I could create a zip file protected by a password. However I can not open this file with popular zip open program such as WinRar, 7Zip, AlZip. Although I input right password, these programs always notice error message "Wrong password". Could you tell me how to fix this issue. Many thanks !

    ReplyDelete
    Replies
    1. Hi, is your password string you set in ascii format instead of some unicode format? You have to be sure to inser a "pure" ascii format, this could be a reason of your problem (but is only an hypothesis since I can not verify directly).

      Delete
    2. Thanks for your answer. But I use password as your sample "mypassword". So I think that insert "pure" ascii password is not problem. Do you have any ideas for my issue ?

      Delete
    3. Also if you use a password composed by ascii value only if the compiler you use is set to magane unicode string the ascii value will be converted in unicode (two bytes per character). I don't know which compiler you are using or under which OS you are developing but using latest compilers unicode is the standard. Try to unsert the password in binary hexadecimal format (for example, the password "xxx" will be char passwd[] = { 'x', 'x', 'x' }; ). However it could be true the opposite, that mean the winrar tool will suppose password is in unicode format and you insert an pure ascii string. A test would be to try reopen the .zip password file using the same sofware you developed for create your zip (that same compiler). This test will give you a first clue if the zip is created correctly. In positive case try to open with your software a zip password protected created by winrar and see if it work.

      Delete
    4. I will try your suggestions. Thanks a lot :D

      Delete
    5. Hi FalsinSoft, could you give me a sample code for unzipping zip files with password. Thank you.

      Delete
    6. Sorry, I don't have a ready made unzipping code. This post is very old and I don't use this library anymore for my projects.

      Delete
    7. Use crc = 0 and the magic appears!!! ; )

      Delete

Post a Comment

Popular posts from this blog

Access GPIO from Linux user space

Android: adb push and read-only file system error

Tree in SQL database: The Nested Set Model