File Lib/zipfile.py changed (mode: 100644) (index 8a19ca246b..6fdf2c398d) |
... |
... |
class ZipInfo (object): |
509 |
509 |
return self.filename[-1] == '/' |
return self.filename[-1] == '/' |
510 |
510 |
|
|
511 |
511 |
|
|
512 |
|
class _ZipDecrypter: |
|
513 |
|
"""Class to handle decryption of files stored within a ZIP archive. |
|
|
512 |
|
# ZIP encryption uses the CRC32 one-byte primitive for scrambling some |
|
513 |
|
# internal keys. We noticed that a direct implementation is faster than |
|
514 |
|
# relying on binascii.crc32(). |
|
515 |
|
|
|
516 |
|
_crctable = None |
|
517 |
|
def _gen_crc(crc): |
|
518 |
|
for j in range(8): |
|
519 |
|
if crc & 1: |
|
520 |
|
crc = (crc >> 1) ^ 0xEDB88320 |
|
521 |
|
else: |
|
522 |
|
crc >>= 1 |
|
523 |
|
return crc |
|
524 |
|
|
|
525 |
|
# ZIP supports a password-based form of encryption. Even though known |
|
526 |
|
# plaintext attacks have been found against it, it is still useful |
|
527 |
|
# to be able to get data out of such a file. |
|
528 |
|
# |
|
529 |
|
# Usage: |
|
530 |
|
# zd = _ZipDecrypter(mypwd) |
|
531 |
|
# plain_bytes = zd(cypher_bytes) |
|
532 |
|
|
|
533 |
|
def _ZipDecrypter(pwd): |
|
534 |
|
key0 = 305419896 |
|
535 |
|
key1 = 591751049 |
|
536 |
|
key2 = 878082192 |
|
537 |
|
|
|
538 |
|
global _crctable |
|
539 |
|
if _crctable is None: |
|
540 |
|
_crctable = list(map(_gen_crc, range(256))) |
|
541 |
|
crctable = _crctable |
|
542 |
|
|
|
543 |
|
def crc32(ch, crc): |
|
544 |
|
"""Compute the CRC32 primitive on one byte.""" |
|
545 |
|
return (crc >> 8) ^ crctable[(crc ^ ch) & 0xFF] |
514 |
546 |
|
|
515 |
|
ZIP supports a password-based form of encryption. Even though known |
|
516 |
|
plaintext attacks have been found against it, it is still useful |
|
517 |
|
to be able to get data out of such a file. |
|
|
547 |
|
def update_keys(c): |
|
548 |
|
nonlocal key0, key1, key2 |
|
549 |
|
key0 = crc32(c, key0) |
|
550 |
|
key1 = (key1 + (key0 & 0xFF)) & 0xFFFFFFFF |
|
551 |
|
key1 = (key1 * 134775813 + 1) & 0xFFFFFFFF |
|
552 |
|
key2 = crc32(key1 >> 24, key2) |
518 |
553 |
|
|
519 |
|
Usage: |
|
520 |
|
zd = _ZipDecrypter(mypwd) |
|
521 |
|
plain_char = zd(cypher_char) |
|
522 |
|
plain_text = map(zd, cypher_text) |
|
523 |
|
""" |
|
|
554 |
|
for p in pwd: |
|
555 |
|
update_keys(p) |
524 |
556 |
|
|
525 |
|
def _GenerateCRCTable(): |
|
526 |
|
"""Generate a CRC-32 table. |
|
|
557 |
|
def decrypter(data): |
|
558 |
|
"""Decrypt a bytes object.""" |
|
559 |
|
result = bytearray() |
|
560 |
|
append = result.append |
|
561 |
|
for c in data: |
|
562 |
|
k = key2 | 2 |
|
563 |
|
c ^= ((k * (k^1)) >> 8) & 0xFF |
|
564 |
|
update_keys(c) |
|
565 |
|
append(c) |
|
566 |
|
return bytes(result) |
527 |
567 |
|
|
528 |
|
ZIP encryption uses the CRC32 one-byte primitive for scrambling some |
|
529 |
|
internal keys. We noticed that a direct implementation is faster than |
|
530 |
|
relying on binascii.crc32(). |
|
531 |
|
""" |
|
532 |
|
poly = 0xedb88320 |
|
533 |
|
table = [0] * 256 |
|
534 |
|
for i in range(256): |
|
535 |
|
crc = i |
|
536 |
|
for j in range(8): |
|
537 |
|
if crc & 1: |
|
538 |
|
crc = ((crc >> 1) & 0x7FFFFFFF) ^ poly |
|
539 |
|
else: |
|
540 |
|
crc = ((crc >> 1) & 0x7FFFFFFF) |
|
541 |
|
table[i] = crc |
|
542 |
|
return table |
|
543 |
|
crctable = None |
|
544 |
|
|
|
545 |
|
def _crc32(self, ch, crc): |
|
546 |
|
"""Compute the CRC32 primitive on one byte.""" |
|
547 |
|
return ((crc >> 8) & 0xffffff) ^ self.crctable[(crc ^ ch) & 0xff] |
|
548 |
|
|
|
549 |
|
def __init__(self, pwd): |
|
550 |
|
if _ZipDecrypter.crctable is None: |
|
551 |
|
_ZipDecrypter.crctable = _ZipDecrypter._GenerateCRCTable() |
|
552 |
|
self.key0 = 305419896 |
|
553 |
|
self.key1 = 591751049 |
|
554 |
|
self.key2 = 878082192 |
|
555 |
|
for p in pwd: |
|
556 |
|
self._UpdateKeys(p) |
|
557 |
|
|
|
558 |
|
def _UpdateKeys(self, c): |
|
559 |
|
self.key0 = self._crc32(c, self.key0) |
|
560 |
|
self.key1 = (self.key1 + (self.key0 & 255)) & 4294967295 |
|
561 |
|
self.key1 = (self.key1 * 134775813 + 1) & 4294967295 |
|
562 |
|
self.key2 = self._crc32((self.key1 >> 24) & 255, self.key2) |
|
563 |
|
|
|
564 |
|
def __call__(self, c): |
|
565 |
|
"""Decrypt a single character.""" |
|
566 |
|
assert isinstance(c, int) |
|
567 |
|
k = self.key2 | 2 |
|
568 |
|
c = c ^ (((k * (k^1)) >> 8) & 255) |
|
569 |
|
self._UpdateKeys(c) |
|
570 |
|
return c |
|
|
568 |
|
return decrypter |
571 |
569 |
|
|
572 |
570 |
|
|
573 |
571 |
class LZMACompressor: |
class LZMACompressor: |
|
... |
... |
class ZipExtFile(io.BufferedIOBase): |
953 |
951 |
raise EOFError |
raise EOFError |
954 |
952 |
|
|
955 |
953 |
if self._decrypter is not None: |
if self._decrypter is not None: |
956 |
|
data = bytes(map(self._decrypter, data)) |
|
|
954 |
|
data = self._decrypter(data) |
957 |
955 |
return data |
return data |
958 |
956 |
|
|
959 |
957 |
def close(self): |
def close(self): |
|
... |
... |
class ZipFile: |
1411 |
1409 |
# or the MSB of the file time depending on the header type |
# or the MSB of the file time depending on the header type |
1412 |
1410 |
# and is used to check the correctness of the password. |
# and is used to check the correctness of the password. |
1413 |
1411 |
header = zef_file.read(12) |
header = zef_file.read(12) |
1414 |
|
h = list(map(zd, header[0:12])) |
|
|
1412 |
|
h = zd(header[0:12]) |
1415 |
1413 |
if zinfo.flag_bits & 0x8: |
if zinfo.flag_bits & 0x8: |
1416 |
1414 |
# compare against the file type from extended local headers |
# compare against the file type from extended local headers |
1417 |
1415 |
check_byte = (zinfo._raw_time >> 8) & 0xff |
check_byte = (zinfo._raw_time >> 8) & 0xff |