Changeset 768

Show
Ignore:
Timestamp:
12/12/06 22:26:54 (2 years ago)
Author:
mfenniak
Message:

support for rev3+ user passwords only

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • pypdf/trunk/pyPdf/pdf.py

    r767 r768  
    515515            '\xa9\xfe\x64\x53\x69\x7a' 
    516516 
    517     def _alg32(self, password, rev, keylen): 
     517    def _alg32(self, password, rev, keylen, metadata_encrypt=True): 
    518518        import md5, struct 
    519519        m = md5.new() 
     
    529529        id1_entry = self.safeGetObject(id_entry[0]) 
    530530        m.update(id1_entry) 
    531         #if rev >= 3
    532         #    if document metadata is not being encrypted, pass \xff\xff\xff\xff into hash 
     531        if rev >= 3 and not metadata_encrypt
     532            m.update("\xff\xff\xff\xff") 
    533533        md5_hash = m.digest() 
    534         #if rev >= 3: 
    535         #    for i in range(50): 
    536         #        m = md5.new() 
    537         #        m.update(md5_hash[:keylen]) 
    538         #        md5_hash = m.digest() 
     534        if rev >= 3: 
     535            for i in range(50): 
     536                md5_hash = md5.new(md5_hash[:keylen]).digest() 
    539537        return md5_hash[:keylen] 
    540538 
    541539    def _alg34(self, password): 
    542         rev = self.safeGetObject(self.safeGetObject(self.trailer['/Encrypt'])['/R']) 
    543         if rev == 2: 
    544             keylen = 5 
    545         key = self._alg32(password, rev, keylen) 
     540        key = self._alg32(password, 2, 5) 
    546541        U = utils.RC4_encrypt(key, self._encryption_padding) 
    547542        return U 
     
    556551        key = md5_hash[:5] 
    557552        return key 
     553 
     554    def _alg35(self, password, rev, keylen, metadata_encrypt): 
     555        import md5 
     556        m = md5.new() 
     557        m.update(self._encryption_padding) 
     558        id_entry = self.safeGetObject(self.trailer['/ID']) 
     559        id1_entry = self.safeGetObject(id_entry[0]) 
     560        m.update(id1_entry) 
     561        md5_hash = m.digest() 
     562        key = self._alg32(password, rev, keylen) 
     563        val = utils.RC4_encrypt(key, md5_hash) 
     564        for i in range(1, 20): 
     565            new_key = '' 
     566            for l in range(len(key)): 
     567                new_key += chr(ord(key[l]) ^ i) 
     568            val = utils.RC4_encrypt(new_key, val) 
     569        return val + ('\x00' * 16) 
    558570 
    559571    ## 
     
    577589    def _authenticateUserPassword(self, password): 
    578590        encrypt = self.safeGetObject(self.trailer['/Encrypt']) 
     591        rev = self.safeGetObject(encrypt['/R']) 
     592        if rev == 2: 
     593            U = self._alg34(password) 
     594        elif rev >= 3: 
     595            U = self._alg35(password, rev, self.safeGetObject(encrypt["/Length"]) / 8, 
     596                    self.safeGetObject(encrypt.get("/EncryptMetadata", False))) 
    579597        real_U = self.safeGetObject(encrypt['/U']) 
    580         U = self._alg34(password) 
    581598        return U == real_U 
    582599