Ejemplo n.º 1
0
 def _decrypt(self, password):
     encrypt = self.trailer['/Encrypt'].getObject()
     if encrypt['/Filter'] != '/Standard':
         raise NotImplementedError(
             "only Standard PDF encryption handler is available")
     if not (encrypt['/V'] in (1, 2)):
         raise NotImplementedError(
             "only algorithm code 1 and 2 are supported")
     user_password, key = self._authenticateUserPassword(password)
     if user_password:
         self._decryption_key = key
         return 1
     else:
         rev = encrypt['/R'].getObject()
         if rev == 2:
             keylen = 5
         else:
             keylen = encrypt['/Length'].getObject() // 8
         key = _alg33_1(password, rev, keylen)
         real_O = encrypt["/O"].getObject()
         if rev == 2:
             userpass = utils.RC4_encrypt(key, real_O)
         else:
             val = real_O
             for i in range(19, -1, -1):
                 new_key = b_('')
                 for l in range(len(key)):
                     new_key += b_(chr(utils.ord_(key[l]) ^ i))
                 val = utils.RC4_encrypt(new_key, val)
             userpass = val
         owner_password, key = self._authenticateUserPassword(userpass)
         if owner_password:
             self._decryption_key = key
             return 2
     return 0
Ejemplo n.º 2
0
 def _decrypt(self, password):
     encrypt = self.trailer['/Encrypt'].getObject()
     if encrypt['/Filter'] != '/Standard':
         raise NotImplementedError(
             "only Standard PDF encryption handler is available")
     if not (encrypt['/V'] in (1, 2)):
         raise NotImplementedError(
             "only algorithm code 1 and 2 are supported")
     user_password, key = self._authenticateUserPassword(password)
     if user_password:
         self._decryption_key = key
         return 1
     else:
         rev = encrypt['/R'].getObject()
         if rev == 2:
             keylen = 5
         else:
             keylen = encrypt['/Length'].getObject() // 8
         key = _alg33_1(password, rev, keylen)
         real_O = encrypt["/O"].getObject()
         if rev == 2:
             userpass = utils.RC4_encrypt(key, real_O)
         else:
             val = real_O
             for i in range(19, -1, -1):
                 new_key = b_('')
                 for l in range(len(key)):
                     new_key += b_(chr(utils.ord_(key[l]) ^ i))
                 val = utils.RC4_encrypt(new_key, val)
             userpass = val
         owner_password, key = self._authenticateUserPassword(userpass)
         if owner_password:
             self._decryption_key = key
             return 2
     return 0
Ejemplo n.º 3
0
def decode_pdfdocencoding(byte_array):
    retval = u_('')
    for b in byte_array:
        c = _pdfDocEncoding[ord_(b)]
        if c == u_('\u0000'):
            raise UnicodeDecodeError("pdfdocencoding", utils.barray(b), -1, -1,
                    "does not exist in translation table")
        retval += c
    return retval
Ejemplo n.º 4
0
def decode_pdfdocencoding(byte_array):
    retval = u_('')
    for b in byte_array:
        c = _pdfDocEncoding[ord_(b)]
        if c == u_('\u0000'):
            raise UnicodeDecodeError("pdfdocencoding", utils.barray(b), -1, -1,
                                     "does not exist in translation table")
        retval += c
    return retval
Ejemplo n.º 5
0
 def writeToStream(self, stream, encryption_key):
     # Try to write the string out as a PDFDocEncoding encoded string.  It's
     # nicer to look at in the PDF file.  Sadly, we take a performance hit
     # here for trying...
     try:
         bytearr = encode_pdfdocencoding(self)
     except UnicodeEncodeError:
         bytearr = codecs.BOM_UTF16_BE + self.encode("utf-16be")
     if encryption_key:
         bytearr = RC4_encrypt(encryption_key, bytearr)
         obj = ByteStringObject(bytearr)
         obj.writeToStream(stream, None)
     else:
         stream.write(b_("("))
         for c in bytearr:
             if not chr_(c).isalnum() and c != b_(' '):
                 stream.write(b_("\\%03o" % ord_(c)))
             else:
                 stream.write(b_(chr_(c)))
         stream.write(b_(")"))
Ejemplo n.º 6
0
 def writeToStream(self, stream, encryption_key):
     # Try to write the string out as a PDFDocEncoding encoded string.  It's
     # nicer to look at in the PDF file.  Sadly, we take a performance hit
     # here for trying...
     try:
         bytearr = encode_pdfdocencoding(self)
     except UnicodeEncodeError:
         bytearr = codecs.BOM_UTF16_BE + self.encode("utf-16be")
     if encryption_key:
         bytearr = RC4_encrypt(encryption_key, bytearr)
         obj = ByteStringObject(bytearr)
         obj.writeToStream(stream, None)
     else:
         stream.write(b_("("))
         for c in bytearr:
             if not chr_(c).isalnum() and c != b_(' '):
                 stream.write(b_("\\%03o" % ord_(c)))
             else:
                 stream.write(b_(chr_(c)))
         stream.write(b_(")"))
Ejemplo n.º 7
0
    def decode(data, decodeParms):
        data = decompress(data)
        predictor = 1
        if decodeParms:
            try:
                predictor = decodeParms.get("/Predictor", 1)
            except AttributeError:
                pass    # usually an array with a null object was read

        # predictor 1 == no predictor
        if predictor != 1:
            columns = decodeParms["/Columns"]
            # PNG prediction:
            if predictor >= 10 and predictor <= 15:
                output = StringIO()
                # PNG prediction can vary from row to row
                rowlength = columns + 1
                assert len(data) % rowlength == 0
                prev_rowdata = (0,) * rowlength
                for row in range(len(data) // rowlength):
                    rowdata = [ord_(x) for x in data[(row*rowlength):((row+1)*rowlength)]]
                    filterByte = rowdata[0]
                    if filterByte == 0:
                        pass
                    elif filterByte == 1:
                        for i in range(2, rowlength):
                            rowdata[i] = (rowdata[i] + rowdata[i-1]) % 256
                    elif filterByte == 2:
                        for i in range(1, rowlength):
                            rowdata[i] = (rowdata[i] + prev_rowdata[i]) % 256
                    else:
                        # unsupported PNG filter
                        raise PdfReadError("Unsupported PNG filter %r" % filterByte)
                    prev_rowdata = rowdata
                    output.write(''.join([chr(x) for x in rowdata[1:]]))
                data = output.getvalue()
            else:
                # unsupported predictor
                raise PdfReadError("Unsupported flatedecode predictor %r" % predictor)
        return data
Ejemplo n.º 8
0
def _alg35(password, rev, keylen,
           owner_entry, p_entry, id1_entry, metadata_encrypt):
    # 1. Create an encryption key based on the user password string, as
    # described in Algorithm 3.2.
    key = _alg32(password, rev, keylen, owner_entry, p_entry, id1_entry)
    # 2. Initialize the MD5 hash function and pass the 32-byte padding string
    # shown in step 1 of Algorithm 3.2 as input to this function.
    m = md5()
    m.update(_encryption_padding)
    # 3. Pass the first element of the file's file identifier array (the value
    # of the ID entry in the document's trailer dictionary; see Table 3.13 on
    # page 73) to the hash function and finish the hash.  (See implementation
    # note 25 in Appendix H.)
    m.update(id1_entry.original_bytes)
    md5_hash = m.digest()
    # 4. Encrypt the 16-byte result of the hash, using an RC4 encryption
    # function with the encryption key from step 1.
    val = utils.RC4_encrypt(key, md5_hash)
    # 5. Do the following 19 times: Take the output from the previous
    # invocation of the RC4 function and pass it as input to a new invocation
    # of the function; use an encryption key generated by taking each byte of
    # the original encryption key (obtained in step 2) and performing an XOR
    # operation between that byte and the single-byte value of the iteration
    # counter (from 1 to 19).
    for i in range(1, 20):
        new_key = b_('')
        for l in range(len(key)):
            new_key += b_(chr(utils.ord_(key[l]) ^ i))
        val = utils.RC4_encrypt(new_key, val)
    # 6. Append 16 bytes of arbitrary padding to the output from the final
    # invocation of the RC4 function and store the 32-byte result as the value
    # of the U entry in the encryption dictionary.
    # (implementator note: I don't know what "arbitrary padding" is supposed to
    # mean, so I have used null bytes.  This seems to match a few other
    # people's implementations)
    return val + (b_('\x00') * 16), key