10

Recently I was testing whether I could make 7-Zip archives more bruteforce-resistant. Both someone on Wikipedia and @kelalaka on this website make the following claim:

The 7z format supports encryption with the AES algorithm with a 256-bit key. The key is generated from a user-supplied passphrase using an algorithm based on the SHA-256 hash function. The SHA-256 is executed 218 (262144) times, which causes a significant delay on slow PCs before compression or extraction starts. This technique is called key stretching and is used to make a brute-force search for the passphrase more difficult. Current GPU-based, and custom hardware attacks limit the effectiveness of this particular method of key stretching, so it is still important to choose a strong password. The 7z format provides the option to encrypt the filenames of a 7z archive.

7zip uses 2^19-times iterated SHA256 to derive the AES-256 key from passwords.

The problem is that I cannot verify this claim. I grepped for various keywords and the closest I got was the following piece of code:

[20:19:36]  d33tah@d33tah-pc:/tmp/p7zip-16.02+dfsg(0) > grep -A10 'static void DeriveKey2' CPP/7zip/Crypto/ZipStrong.cpp
static void DeriveKey2(const Byte *digest, Byte c, Byte *dest)
{
  Byte buf[64];
  memset(buf, c, 64);
  for (unsigned i = 0; i < NSha1::kDigestSize; i++)
    buf[i] ^= digest[i];
  NSha1::CContext sha;
  sha.Init();
  sha.Update(buf, 64);
  sha.Final(dest);
}

However, it's not SHA-1, but xor. Am I looking at the wrong place in the source code? Here's a GitHub repository I found for convenience (grepping was done on the result of apt-get source p7zip-full).

Wai Ha Lee
  • 113
  • 1
  • 7
d33tah
  • 6,524
  • 8
  • 38
  • 60
  • 2
    You might need to look in `7zAes.cpp`. `ZipStrong.cpp` might only be used for `zip` archives, not `7z` archives. – user Mar 21 '22 at 19:47
  • 3
    It's worth noting that this type of key stretching is no longer recommended because it is not memory-hard. 7zip would be better off if they switched to Argon2. – forest Mar 21 '22 at 22:25

1 Answers1

15

The relevant code for 7z key derivation is in 7zAES.cpp function CKeyInfo::CalcKey and it matches the description about SHA-256 and number of rounds.

Steffen Ullrich
  • 184,332
  • 29
  • 363
  • 424
  • I actually appears to be calculating the SHA-256 of a byte stream composed of n repetitions of the concatenation of: salt, password, incrementing 64-bit little-endian counter. The output of the SHA-256 is not fed back into to SHA-256 (which is what a casual reader of the OP's quoted text might infer). – abligh Mar 23 '22 at 06:53