0

In the (PK)ZIP specification at https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT, specifically in the Strong Encryption Specification (SES) section, there is a line on deriving a key from a password:

MasterSessionKey = DeriveKey(SHA1(Password)) 

What's DeriveKey?

(In WinZip's AES documentation at https://www.winzip.com/en/support/aes-encryption/, they use PBKDF2 with 1000 iterations. I don't see any similar explanation in APPNOTE)

Michal Charemza
  • 25,940
  • 14
  • 98
  • 165

2 Answers2

1

PKWARE implemented a strong encryption in version 5, but did not provide the algorithm of encoding/decoding (Method For Strongly Encrypted .ZIP Files - Patent US 2020/0250329 A1). In this algorithm AES encryption was implemented as part of it. You can define this by strong encryption (bit 6) = yes in General Purpose Flag.

After that WinZip could not use this algo, so it invented another one. You can define this by strong encryption (bit 6) = no in General Purpose Flag and AesExtraFieldRecord with signature 0x990.

As you can see there're two ways to encrypt a zip file. All open source software use the second one. The first one is available only by PKWARE SecureZIP

You can find example of this alogirthm in (7zip) Strong.cpp:35. In java it should look like this:

public static byte[] getMasterKey(String password) {
    byte[] data = password.getBytes(StandardCharsets.UTF_8);
    byte[] sha1 = DigestUtils.sha1(data);
    return DeriveKey(sha1);
}

private static byte[] DeriveKey(byte[] digest) {
    byte[] buf = new byte[kDigestSize * 2];  // kDigestSize = 20
    DeriveKey2(digest, (byte)0x36, buf, 0);
    DeriveKey2(digest, (byte)0x5C, buf, kDigestSize);
    return Arrays.copyOfRange(buf, 0, 32);
}

private static void DeriveKey2(byte[] digest, byte c, byte[] dest, int offs) {
    byte[] buf = new byte[64];
    Arrays.fill(buf, c);

    for (int i = 0; i < kDigestSize; i++)
        buf[i] ^= digest[i];

    byte[] sha1 = DigestUtils.sha1(buf);
    System.arraycopy(sha1, 0, dest, offs, sha1.length);
}

Demo:

String password = "JohnDoe";
byte[] masterKey = getMasterKey(password);
Oleg Cherednik
  • 17,377
  • 4
  • 21
  • 35
  • I have similar post https://stackoverflow.com/q/58393996/3461397 and there there're the answer from PKWARE guy. – Oleg Cherednik Nov 06 '22 at 07:12
  • Thanks for this - although to clarify, is the code here an example of PKWARE's algorithm or WinZip's? – Michal Charemza Nov 06 '22 at 08:13
  • Ah... [nosing around the code](https://github.com/keithjjones/7z/blob/174a5af5960d2bbebc7deb3b7bc622f5f62b9a3e/CPP/7zip/Archive/Zip/ZipHandler.cpp#L555), I think it's PKWARE's(?). I'm wondering though, are there potential patent/licensing issues here? – Michal Charemza Nov 06 '22 at 09:40
  • 1
    I think yes. At least for encoding, because PKWARE SecureZip is not free. But there is SecureZipReader - it is free. I think in case you implement StringEncryption Reading in your application, it could be norm. I am think about support reading in my zip4jvm - https://github.com/oleg-cherednik/zip4jvm as well. – Oleg Cherednik Nov 06 '22 at 17:26
  • I have requested an information from Pkware. The said that there is not limits to implemente any part of zip format specification until you not use Pkwares's applications. – Oleg Cherednik Dec 13 '22 at 07:51
0

The next paragraph 'defines' it

7.2.5.3 The function names and parameter requirements will depend on the choice of the cryptographic toolkit selected. Almost any toolkit supporting the reference implementations for each algorithm can be used. The RSA BSAFE(r), OpenSSL, and Microsoft CryptoAPI libraries are all known to work well.

I guess it's up to you to decide which of the encryption algorithms you want to use and go from there

bixarrio
  • 373
  • 1
  • 10