Should Zip PasswordRequired event be called for invalid non-null passwords?

0 votes
asked Nov 1, 2015 by tltabor (210 points)
edited Jan 13, 2016 by Lukas Matyska

ZipArchive's PasswordRequired event appears to be called if the item is encrypted and the archive's password is null, but not if the item is encrypted and the archive's password is non-null and incorrect.

Any thoughts?

Thank you.

EDIT BY REBEX:
The issue was related to ZipItem.Open() method only.
It was fixed in version 2016 R1.

Applies to: Rebex ZIP

2 Answers

0 votes
answered Nov 2, 2015 by Lukas Matyska (40,700 points)

No, ZipArchive.PasswordRequired is raised if no password is specified or data cannot be extracted successfully (incorrect password, CRC32 check failed, corrupted data).

However, the event is raised for one file maximally 5 times by default. This value can be changed by the ZipArchive.Options.MaxPasswordRetryCount property.

Using this, you can easily write code to ask an user to enter the password N-times.

There is no possibility to instruct the ZipArchive class to raise PasswordRequired infinitely. You can either specify MaxPasswordRetryCount to int.MaxValue or write a loop like this:

while (true)
{
    zip.Options.MaxPasswordRetryCount = 0;
    zip.Password = GetPassword();
    try
    {
        zip.ExtractAll(outPath);
        break;
    }
    catch (ZipException ex)
    {
        if (ex.ProblemType == ArchiveProblemType.IncorrectPasswordOrCorruptedData)
            continue;
        throw;
    }
}
commented Nov 3, 2015 by tltabor (210 points)
edited Nov 3, 2015 by tltabor
Sorry, I wasn't clear. I understand PasswordRequired can't be called infinitely.

For an encrypted file, the PasswordRequired event is raised only if the attempted password is null. It should also be raised if the attempted password is non-null but incorrect.

Moreover, if an incorrect password is set in the PasswordRequired handler, an exception is raised rather than PasswordRequired being raised for another attempt (even with MaxPasswordRetryCount > 0).
+1 vote
answered Nov 3, 2015 by Lukas Matyska (40,700 points)

I understand your question, but I still have to say that the event should be raised. Can you please send me your code to support@rebex.net, I will diagnose it?

Here is my proof, that the PasswordRequired is raised even the Password is set to non-null but incorrect password:

Code:

using (ZipArchive zip = new ZipArchive(new MemoryStream()))
{
    // add an encrypted file
    zip.Password = "test3";
    zip.AddFile(new MemoryStream(new byte[1]), "file.txt");

    // set incorrect password
    zip.Password = "test";

    int idx = 0;

    // register handler
    zip.PasswordRequired += (s, e) =>
    {
        e.Password = "test" + idx;
        Console.WriteLine("ZipArchive.Password: {0}, PasswordRequired.Password: {1}", zip.Password, e.Password);
        idx++;
    };

    Console.WriteLine("MaxPasswordRetryCount: " + zip.Options.MaxPasswordRetryCount);

    // extract file
    zip["file.txt"].ExtractToArray();
}

Output:

MaxPasswordRetryCount: 5
ZipArchive.Password: test, PasswordRequired.Password: test0
ZipArchive.Password: test, PasswordRequired.Password: test1
ZipArchive.Password: test, PasswordRequired.Password: test2
ZipArchive.Password: test, PasswordRequired.Password: test3

Alternatively, instead of setting e.Password, you can set zip.Password. Result will be the same:

Code:

// register handler
zip.PasswordRequired += (s, e) =>
{
    zip.Password = "test" + idx;
    Console.WriteLine("ZipArchive.Password: {0}, PasswordRequired.Password: {1}", zip.Password, e.Password);
    idx++;
};

Output:

MaxPasswordRetryCount: 5
ZipArchive.Password: test0, PasswordRequired.Password:
ZipArchive.Password: test1, PasswordRequired.Password:
ZipArchive.Password: test2, PasswordRequired.Password:
ZipArchive.Password: test3, PasswordRequired.Password:
commented Nov 3, 2015 by tltabor (210 points)
This is a really beautiful proof.  Change your ExtractToArray() to Open() and you will replicate my results.
commented Nov 3, 2015 by Lukas Matyska (40,700 points)
Great, I am finally able to reproduce your issue.
I considered it as bug, I will send you fixed version to your email within hour.
commented Jan 13, 2016 by Lukas Matyska (40,700 points)
The bug was fixed in version 2016 R1.
...