'Python throws "zipfile.BadZipFile: Bad CRC-32" ONLY when I pass "D" as password

I'm trying to create a Python script that tests passwords on password protected zip files. The only problem is that whenever I try to pass specifically "D" as the password, I get zipfile.BadZipFile: Bad CRC-32'

To test it, I created p.zip, with the password p, and only one file called p.txt and ran this code:

from zipfile import ZipFile

with ZipFile("p.zip") as zf:
    password = "E"
    try:
        zf.extractall(pwd=bytes(password, "utf-8"))
    except RuntimeError:
        print("wrong password: " + password)

I just got wrong password: E which is what I expected.

However, when I run the EXACT same code except with password = "D" I get zipfile.BadZipFile: Bad CRC-32 for file 'p.txt'

I tried several strings such as p, letmein, password1, DD, DDD and they all work fine. ONLY setting password = "D" gives zipfile.BadZipFile: Bad CRC-32 for file 'p.txt'.

Does anybody know the reason for this or a possible fix?

Here's the full error on console:

Traceback (most recent call last):
  File "C:/Users/argolis/workspace/zip-breaker/zip-breaker/script2.py", line 6, in <module>
    zf.extractall(pwd=bytes(password, "utf-8"))
  File "C:\Users\argolis\AppData\Local\Programs\Python\Python37\lib\zipfile.py", line 1594, in extractall
    self._extract_member(zipinfo, path, pwd)
  File "C:\Users\argolis\AppData\Local\Programs\Python\Python37\lib\zipfile.py", line 1649, in _extract_member
    shutil.copyfileobj(source, target)
  File "C:\Users\argolis\AppData\Local\Programs\Python\Python37\lib\shutil.py", line 79, in copyfileobj
    buf = fsrc.read(length)
  File "C:\Users\argolis\AppData\Local\Programs\Python\Python37\lib\zipfile.py", line 876, in read
    data = self._read1(n)
  File "C:\Users\argolis\AppData\Local\Programs\Python\Python37\lib\zipfile.py", line 966, in _read1
    self._update_crc(data)
  File "C:\Users\argolis\AppData\Local\Programs\Python\Python37\lib\zipfile.py", line 894, in _update_crc
    raise BadZipFile("Bad CRC-32 for file %r" % self.name)
zipfile.BadZipFile: Bad CRC-32 for file 'p.txt'


Solution 1:[1]

This is expected behaviour from the unzip protocol. Sometimes an invalid password will pass the password check and be caught be the CRC check. From man unzip (a Linux doc, but the algorithm is platform independent):

The correct password will always check out against the header, but there is a 1-in-256 chance that an incorrect password will as well. (This is a security feature of the PKWARE zipfile format; it helps prevent brute-force attacks that might otherwise gain a large speed advantage by testing only the header.) In the case that an incorrect password is given but it passes the header test anyway, either an incorrect CRC will be generated for the extracted data or else unzip will fail during the extraction because the ``decrypted'' bytes do not constitute a valid compressed data stream.

There is a Python bug report where this is discussed.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1