diff options
-rw-r--r-- | Lib/test/test_zipfile.py | 21 | ||||
-rw-r--r-- | Lib/zipfile.py | 13 |
2 files changed, 32 insertions, 2 deletions
diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py index 40003aa..adc0dc1 100644 --- a/Lib/test/test_zipfile.py +++ b/Lib/test/test_zipfile.py @@ -698,31 +698,52 @@ class DecryptionTests(unittest.TestCase): '\x1a\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x01\x00 \x00\xb6\x81' '\x00\x00\x00\x00test.txtPK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x006\x00' '\x00\x00L\x00\x00\x00\x00\x00' ) + data2 = ( + 'PK\x03\x04\x14\x00\t\x00\x08\x00\xcf}38xu\xaa\xb2\x14\x00\x00\x00\x00\x02' + '\x00\x00\x04\x00\x15\x00zeroUT\t\x00\x03\xd6\x8b\x92G\xda\x8b\x92GUx\x04' + '\x00\xe8\x03\xe8\x03\xc7<M\xb5a\xceX\xa3Y&\x8b{oE\xd7\x9d\x8c\x98\x02\xc0' + 'PK\x07\x08xu\xaa\xb2\x14\x00\x00\x00\x00\x02\x00\x00PK\x01\x02\x17\x03' + '\x14\x00\t\x00\x08\x00\xcf}38xu\xaa\xb2\x14\x00\x00\x00\x00\x02\x00\x00' + '\x04\x00\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00\x00\x00\x00ze' + 'roUT\x05\x00\x03\xd6\x8b\x92GUx\x00\x00PK\x05\x06\x00\x00\x00\x00\x01' + '\x00\x01\x00?\x00\x00\x00[\x00\x00\x00\x00\x00' ) plain = 'zipfile.py encryption test' + plain2 = '\x00'*512 def setUp(self): fp = open(TESTFN, "wb") fp.write(self.data) fp.close() self.zip = zipfile.ZipFile(TESTFN, "r") + fp = open(TESTFN2, "wb") + fp.write(self.data2) + fp.close() + self.zip2 = zipfile.ZipFile(TESTFN2, "r") def tearDown(self): self.zip.close() os.unlink(TESTFN) + self.zip2.close() + os.unlink(TESTFN2) def testNoPassword(self): # Reading the encrypted file without password # must generate a RunTime exception self.assertRaises(RuntimeError, self.zip.read, "test.txt") + self.assertRaises(RuntimeError, self.zip2.read, "zero") def testBadPassword(self): self.zip.setpassword("perl") self.assertRaises(RuntimeError, self.zip.read, "test.txt") + self.zip2.setpassword("perl") + self.assertRaises(RuntimeError, self.zip2.read, "zero") def testGoodPassword(self): self.zip.setpassword("python") self.assertEquals(self.zip.read("test.txt"), self.plain) + self.zip2.setpassword("12345") + self.assertEquals(self.zip2.read("zero"), self.plain2) class TestsWithRandomBinaryFiles(unittest.TestCase): diff --git a/Lib/zipfile.py b/Lib/zipfile.py index eb00b34..6feabbf 100644 --- a/Lib/zipfile.py +++ b/Lib/zipfile.py @@ -186,6 +186,7 @@ class ZipInfo (object): 'CRC', 'compress_size', 'file_size', + '_raw_time', ) def __init__(self, filename="NoName", date_time=(1980,1,1,0,0,0)): @@ -683,6 +684,7 @@ class ZipFile: x.CRC, x.compress_size, x.file_size) = centdir[1:12] x.volume, x.internal_attr, x.external_attr = centdir[15:18] # Convert date/time code to (year, month, day, hour, min, sec) + x._raw_time = t x.date_time = ( (d>>9)+1980, (d>>5)&0xF, d&0x1F, t>>11, (t>>5)&0x3F, (t&0x1F) * 2 ) @@ -790,11 +792,18 @@ class ZipFile: # The first 12 bytes in the cypher stream is an encryption header # used to strengthen the algorithm. The first 11 bytes are # completely random, while the 12th contains the MSB of the CRC, + # or the MSB of the file time depending on the header type # and is used to check the correctness of the password. bytes = zef_file.read(12) h = map(zd, bytes[0:12]) - if ord(h[11]) != ((zinfo.CRC>>24)&255): - raise RuntimeError, "Bad password for file %s" % name + if zinfo.flag_bits & 0x8: + # compare against the file type from extended local headers + check_byte = (zinfo._raw_time >> 8) & 0xff + else: + # compare against the CRC otherwise + check_byte = (zinfo.CRC >> 24) & 0xff + if ord(h[11]) != check_byte: + raise RuntimeError("Bad password for file", name) # build and return a ZipExtFile if zd is None: |