Skip to content

zipfile cannot read AES encrypted files #53416

Closed

Description

@aymill
mannequin
BPO 9170
Nosy @birkenfeld, @amauryfa, @pitrou
Dependencies
  • bpo-8998: add crypto routines to stdlib
  • Files
  • example.zip: Example zip encrypted with WinZip 11.1 using AES 256. Password is "cat".
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = <Date 2013-10-14.17:40:22.054>
    created_at = <Date 2010-07-05.17:42:22.542>
    labels = ['type-feature', 'library']
    title = 'zipfile cannot read AES encrypted files'
    updated_at = <Date 2013-10-14.17:40:22.053>
    user = 'https://bugs.python.org/aymill'

    bugs.python.org fields:

    activity = <Date 2013-10-14.17:40:22.053>
    actor = 'georg.brandl'
    assignee = 'none'
    closed = True
    closed_date = <Date 2013-10-14.17:40:22.054>
    closer = 'georg.brandl'
    components = ['Library (Lib)']
    creation = <Date 2010-07-05.17:42:22.542>
    creator = 'aymill'
    dependencies = ['8998']
    files = ['17872']
    hgrepos = []
    issue_num = 9170
    keywords = []
    message_count = 4.0
    messages = ['109342', '109385', '109650', '199933']
    nosy_count = 4.0
    nosy_names = ['georg.brandl', 'amaury.forgeotdarc', 'pitrou', 'aymill']
    pr_nums = []
    priority = 'normal'
    resolution = 'wont fix'
    stage = 'needs patch'
    status = 'closed'
    superseder = None
    type = 'enhancement'
    url = 'https://bugs.python.org/issue9170'
    versions = ['Python 3.2']

    Activity

    1. aymill commented on Jul 5, 2010

      aymillmannequin
      MannequinAuthor

      On a WinZip AES-256 encrypted zip, zipfile.extractall raises a RuntimeError for "Bad password for file" when given the correct password. Command line example below:

      Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41) 
      [GCC 4.3.3] on linux2
      Type "help", "copyright", "credits" or "license" for more information.
      >>> from zipfile import ZipFile
      >>> zip = ZipFile("example.zip", "r")
      >>> zip.extractall(".", pwd="cat")
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
        File "/usr/lib/python2.6/zipfile.py", line 935, in extractall
          self.extract(zipinfo, path, pwd)
        File "/usr/lib/python2.6/zipfile.py", line 923, in extract
          return self._extract_member(member, path, pwd)
        File "/usr/lib/python2.6/zipfile.py", line 963, in _extract_member
          source = self.open(member, pwd=pwd)
        File "/usr/lib/python2.6/zipfile.py", line 898, in open
          raise RuntimeError("Bad password for file", name)
      RuntimeError: ('Bad password for file', <zipfile.ZipInfo object at 0xb739e26c>)
      >>>
    2. added
      type-bugAn unexpected behavior, bug, or error
      stdlibStandard Library Python modules in the Lib/ directory
      on Jul 5, 2010
    3. amauryfa commented on Jul 6, 2010

      @amauryfa
      Contributor

      zipfile only supports the "Traditional PKWARE Encryption" method.
      Support for other encryption methods would be useful.

    4. changed the title [-]zipfile.extractall raises runtime error on correct password[/-] [+]zipfile cannot read AES encrypted files[/+] on Jul 6, 2010
    5. added
      type-featureA feature request or enhancement
      and removed
      type-bugAn unexpected behavior, bug, or error
      on Jul 6, 2010
    6. pitrou commented on Jul 9, 2010

      @pitrou
      Member

      Do note that providing a patch first requires that encryption/decryption facilities be made available in the stdlib.
      (right now we only offer hashing, and "high-level" socket wrapping)

    7. birkenfeld commented on Oct 14, 2013

      @birkenfeld
      Member

      bpo-8998 has been closed (among others due to legal concerns), so this need not be kept open.

    8. transferred this issue fromon Apr 10, 2022
    9. adiroiban commented on Jul 17, 2025

      @adiroiban

      Even if stdlib will never support WinZIP AES encrpyption, it would be useful to allow for downstream project to implement it.


      There is pyzipper based on a fork but the code is not very different to what we have in stdlib.

      Do you think that we can have something like this in stdlib to allow extending

      A very simple proof of concept downstream code is here that can only read AES ZIP files https://gist.github.com/adiroiban/18dcb49ee3ed755c003c74a4eb85d3a4


      It is using this patch for stdblib

      --- lib/python3.12/zipfile/__init__.py        2025-07-17 11:19:59.376677338 +0100
      +++ src/dev_tools/zipfile_init.py       2025-07-17 11:21:50.797894299 +0100
      @@ -1286,6 +1286,9 @@
       
           """
       
      +    _ZipInfo = ZipInfo
      +    _ZipExtFile = ZipExtFile
      +
           fp = None                   # Set here since __del__ checks it
           _windows_illegal_name_trans_table = None
       
      @@ -1456,7 +1459,7 @@
                       # Historical ZIP filename encoding
                       filename = filename.decode(self.metadata_encoding or 'cp437')
                   # Create ZipInfo instance to store file information
      -            x = ZipInfo(filename)
      +            x = self._ZipInfo(filename)
                   x.extra = fp.read(centdir[_CD_EXTRA_FIELD_LENGTH])
                   x.comment = fp.read(centdir[_CD_COMMENT_LENGTH])
                   x.header_offset = centdir[_CD_LOCAL_HEADER_OFFSET]
      @@ -1592,11 +1595,11 @@
                       "Attempt to use ZIP archive that was already closed")
       
               # Make sure we have an info object
      -        if isinstance(name, ZipInfo):
      +        if isinstance(name, self._ZipInfo):
                   # 'name' is already an info object
                   zinfo = name
               elif mode == 'w':
      -            zinfo = ZipInfo(name)
      +            zinfo = self._ZipInfo(name)
                   zinfo.compress_type = self.compression
                   zinfo._compresslevel = self.compresslevel
               else:
      @@ -1664,7 +1667,7 @@
                   else:
                       pwd = None
       
      -            return ZipExtFile(zef_file, mode, zinfo, pwd, True)
      +            return self._ZipExtFile(zef_file, mode, zinfo, pwd, True)
               except:
                   zef_file.close()
                   raise
      @@ -1762,7 +1765,7 @@
               """Extract the ZipInfo object 'member' to a physical
                  file on the path targetpath.
               """
      -        if not isinstance(member, ZipInfo):
      +        if not isinstance(member, self._ZipInfo):
                   member = self.getinfo(member)
       
               # build the destination pathname, replacing
      @@ -1838,7 +1841,7 @@
                       "Can't write to ZIP archive while an open writing handle exists"
                   )
       
      -        zinfo = ZipInfo.from_file(filename, arcname,
      +        zinfo = self._ZipInfo.from_file(filename, arcname,
                                         strict_timestamps=self._strict_timestamps)
       
               if zinfo.is_dir():
      @@ -1868,8 +1871,8 @@
               the name of the file in the archive."""
               if isinstance(data, str):
                   data = data.encode("utf-8")
      -        if not isinstance(zinfo_or_arcname, ZipInfo):
      -            zinfo = ZipInfo(filename=zinfo_or_arcname,
      +        if not isinstance(zinfo_or_arcname, self._ZipInfo):
      +            zinfo = self._ZipInfo(filename=zinfo_or_arcname,
                                   date_time=time.localtime(time.time())[:6])
                   zinfo.compress_type = self.compression
                   zinfo._compresslevel = self.compresslevel
      @@ -1910,7 +1913,7 @@
                   directory_name = zinfo_or_directory_name
                   if not directory_name.endswith("/"):
                       directory_name += "/"
      -            zinfo = ZipInfo(directory_name)
      +            zinfo = self._ZipInfo(directory_name)
                   zinfo.compress_size = 0
                   zinfo.CRC = 0
                   zinfo.external_attr = ((0o40000 | mode) & 0xFFFF) << 16

      Would you consider such a patch ?

      Thanks

    10. brianschubert commented on Jul 17, 2025

      @brianschubert
      Contributor

      @adiroiban for better visibility, I'd suggest opening a discussion on https://discuss.python.org/c/ideas/6 and/or opening a new issue for this specific feature

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Metadata

    Metadata

    Assignees

    No one assigned

      Labels

      stdlibStandard Library Python modules in the Lib/ directorytype-featureA feature request or enhancement

      Projects

      No projects

        Milestone

        No milestone

        Relationships

        None yet

        Development

        No branches or pull requests

        Issue actions