Ejemplo n.º 1
0
    def _make_sig_annotation(self, F=None, Vref=None, T=None, Pref=None):
        annot = po.DictionaryObject()
        annot_ref = self._addObject(annot)
        annot.update({
            po.NameObject("/FT"):
            po.NameObject("/Sig"),
            po.NameObject("/Type"):
            po.NameObject("/Annot"),
            po.NameObject("/Subtype"):
            po.NameObject("/Widget"),
            po.NameObject("/F"):
            F,
            po.NameObject("/T"):
            T,
            po.NameObject("/V"):
            Vref,
            po.NameObject("/P"):
            Pref,

            # For an invisible signature, /Rect should be a size 0 box
            # Defaulting to that
            po.NameObject("/Rect"):
            po.ArrayObject([
                po.FloatObject(0.0),
                po.FloatObject(0.0),
                po.FloatObject(0.0),
                po.FloatObject(0.0),
            ]),
        })
        return annot, annot_ref
Ejemplo n.º 2
0
 def _make_signature(self, Contents=None, Type=None, SubFilter=None):
     sig = po.DictionaryObject()
     sig_ref = self._addObject(sig)
     sig.update({
         po.NameObject("/Type"):
         Type,
         po.NameObject("/Filter"):
         po.NameObject("/Adobe.PPKLite"),
         po.NameObject("/SubFilter"):
         SubFilter,
         po.NameObject("/ByteRange"):
         po.ArrayObject([
             WNumberObject(0),
             WNumberObject(0),
             WNumberObject(0),
             WNumberObject(0),
         ]),
         po.NameObject("/Contents"):
         Contents,
     })
     return sig, sig_ref
Ejemplo n.º 3
0
def makeObject(obj):
    if isinstance(obj, pdf.PdfObject):
        return obj
    if isinstance(obj, int):
        return pdf.NumberObject(obj)
    if isinstance(obj, float):
        return pdf.NumberObject(obj)
    if isinstance(obj, str):
        return pdf.createStringObject(obj)
    if isinstance(obj, (list, tuple)):
        result = pdf.ArrayObject()
        for v in obj:
            v = makeObject(v)
            result.append(v)
        return result
    if isinstance(obj, dict):
        result = PdfDict()
        for k, v in obj.items():
            v = makeObject(v)
            result[k] = v
        return result
    raise ValueError("can`t convert to PdfObject", obj)
Ejemplo n.º 4
0
    def sign(self, datau, udct, key, cert, othercerts, algomd, hsm,
             timestampurl):
        startdata = len(datau)

        fi = io.BytesIO(datau)

        # read end decrypt
        prev = pdf.PdfFileReader(fi)
        if prev.isEncrypted:
            rc = prev.decrypt(udct["password"])
        else:
            rc = 0

        # digest method must remain unchanged from prevoius signatures
        obj = prev.trailer
        for k in ("/Root", "/Perms", "/DocMDP", "/Reference"):
            if k in obj:
                obj = obj[k]
                if isinstance(obj, po.ArrayObject):
                    obj = obj[0]
                obj = obj.getObject()
            else:
                obj = None
                break
        if obj is not None:
            algomd = obj["/DigestMethod"][1:].lower()

        # produce smaller signatures, but must be signed twice
        aligned = udct.get("aligned", 0)
        if aligned:
            zeros = b"00" * aligned
        else:
            md = getattr(hashlib, algomd)().digest()
            contents = signer.sign(None, key, cert, othercerts, algomd, True,
                                   md, hsm, False, timestampurl)
            zeros = contents.hex().encode("utf-8")

        self.makepdf(prev, udct, algomd, zeros)

        # if document was encrypted, encrypt this version too
        if prev.isEncrypted:
            self.encrypt(prev, udct["password"], rc)
        else:
            self._encrypt_key = None

        # ID[0] is used in password protection, must be unchanged
        ID = prev.trailer.get("/ID", None)
        if ID is None:
            ID = hashlib.md5(repr(time.time()).encode()).digest()
        else:
            ID = ID[0]
            if isinstance(ID, str):
                ID = ID.encode()
        self._ID = po.ArrayObject([
            po.ByteStringObject(ID),
            po.ByteStringObject(
                hashlib.md5(repr(random.random()).encode()).digest()),
        ])

        fo = io.BytesIO()
        self.write(fo, prev, startdata)
        datas = fo.getvalue()

        br = [0, 0, 0, 0]
        bfrom = (b"[ " + b" ".join([WNumberObject.Format] * 4) +
                 b" ]") % tuple(br)

        pdfbr1 = datas.find(zeros)
        pdfbr2 = pdfbr1 + len(zeros)
        br = [
            0,
            startdata + pdfbr1 - 1,
            startdata + pdfbr2 + 1,
            len(datas) - pdfbr2 - 1,
        ]
        bto = b"[%d %d %d %d]" % tuple(br)
        bto += b" " * (len(bfrom) - len(bto))
        assert len(bfrom) == len(bto)
        datas = datas.replace(bfrom, bto, 1)

        md = getattr(hashlib, algomd)()
        md.update(datau)
        b1 = datas[:br[1] - startdata]
        b2 = datas[br[2] - startdata:]
        md.update(b1)
        md.update(b2)
        md = md.digest()

        contents = signer.sign(None, key, cert, othercerts, algomd, True, md,
                               hsm, False, timestampurl)
        contents = contents.hex().encode("utf-8")
        if aligned:
            nb = len(zeros) - len(contents)
            contents += b"0" * nb
        assert len(zeros) == len(contents)

        datas = datas.replace(zeros, contents, 1)

        return datas
Ejemplo n.º 5
0
    def makepdf(self, prev, udct, algomd, zeros):
        catalog = prev.trailer["/Root"]
        size = prev.trailer["/Size"]
        pages = catalog["/Pages"].getObject()
        page0ref = pages["/Kids"][udct.get("sigpage", 0)]

        while len(self._objects) < size - 1:
            self._objects.append(None)

        obj13 = po.DictionaryObject()
        obj13ref = self._addObject(obj13)
        obj12 = po.DictionaryObject()
        obj12ref = self._addObject(obj12)

        obj12.update({
            po.NameObject("/Type"):
            po.NameObject("/Sig"),
            po.NameObject("/Filter"):
            po.NameObject("/Adobe.PPKLite"),
            po.NameObject("/SubFilter"):
            po.NameObject("/adbe.pkcs7.detached"),
            po.NameObject("/Name"):
            po.createStringObject(udct["contact"]),
            po.NameObject("/Location"):
            po.createStringObject(udct["location"]),
            po.NameObject("/Reason"):
            po.createStringObject(udct["reason"]),
            po.NameObject("/M"):
            po.createStringObject(udct["signingdate"]),
            po.NameObject("/Contents"):
            UnencryptedBytes(zeros),
            po.NameObject("/ByteRange"):
            po.ArrayObject([
                WNumberObject(0),
                WNumberObject(0),
                WNumberObject(0),
                WNumberObject(0),
            ]),
        })
        obj13.update({
            po.NameObject("/FT"):
            po.NameObject("/Sig"),
            po.NameObject("/Type"):
            po.NameObject("/Annot"),
            po.NameObject("/Subtype"):
            po.NameObject("/Widget"),
            po.NameObject("/F"):
            po.NumberObject(udct.get("sigflagsft", 132)),
            po.NameObject("/T"):
            EncodedString(udct.get("sigfield", "Signature1")),
            po.NameObject("/V"):
            obj12ref,
            po.NameObject("/P"):
            page0ref,
            po.NameObject("/Rect"):
            po.ArrayObject([
                po.FloatObject(0.0),
                po.FloatObject(0.0),
                po.FloatObject(0.0),
                po.FloatObject(0.0),
            ]),
        })

        box = udct.get("signaturebox", None)
        if box is not None:
            from endesive.pdf.PyPDF2_annotate.annotations.text import FreeText
            from endesive.pdf.PyPDF2_annotate.annotations.image import Image
            from endesive.pdf.PyPDF2_annotate.config.appearance import Appearance
            from endesive.pdf.PyPDF2_annotate.config.location import Location
            from endesive.pdf.PyPDF2_annotate.util.geometry import identity

            annotationtext = udct.get("signature", None)
            x1, y1, x2, y2 = box
            if annotationtext is not None:
                annotation = FreeText(
                    Location(x1=x1, y1=y1, x2=x2, y2=y2, page=0),
                    Appearance(
                        fill=[0, 0, 0],
                        stroke_width=1,
                        wrap_text=True,
                        font_size=12,
                        content=annotationtext,
                    ),
                )
                names = ("BS", "C", "Contents", "DA")
                if not udct.get("sigbutton", False):
                    obj13[po.NameObject("/Subtype")] = po.NameObject(
                        "/FreeText")
            else:
                ap = Appearance()
                ap.image = udct["signature_img"]
                annotation = Image(
                    Location(x1=x1, y1=y1, x2=x2, y2=y2, page=0), ap)
                if not udct.get("sigbutton", False):
                    names = (
                        #
                        "Subtype", )
                else:
                    names = ()

            pdfa = annotation.as_pdf_object(identity(), page=page0ref)
            objapn = self._extend(pdfa["/AP"]["/N"])
            objapnref = self._addObject(objapn)

            for name in names + (
                    "Rect",
                    # "Subtype",
            ):
                key = po.NameObject("/" + name)
                v = pdfa[key]
                obj13[key] = v

            objap = po.DictionaryObject()
            objap[po.NameObject("/N")] = objapnref
            obj13.update({
                po.NameObject("/AP"):
                objap,
                po.NameObject("/SM"):
                po.createStringObject("TabletPOSinline"),
            })

            page0 = page0ref.getObject()
            annots = po.ArrayObject([obj13ref])
            if "/Annots" in page0:
                page0annots = page0["/Annots"]
                if isinstance(page0annots, po.IndirectObject):
                    annots.insert(0, page0annots)
                elif isinstance(page0annots, po.ArrayObject):
                    annots = page0annots
                    annots.append(obj13ref)
            page0.update({po.NameObject("/Annots"): annots})
            self._objects[page0ref.idnum - 1] = page0

        if "/Perms" not in catalog:
            obj10 = po.DictionaryObject()
            obj10ref = self._addObject(obj10)
            obj11 = po.DictionaryObject()
            obj11ref = self._addObject(obj11)
            obj14 = po.DictionaryObject()
            obj14ref = self._addObject(obj14)
            obj14.update({po.NameObject("/DocMDP"): obj12ref})
            obj10.update({
                po.NameObject("/Type"):
                po.NameObject("/TransformParams"),
                po.NameObject("/P"):
                po.NumberObject(2),
                po.NameObject("/V"):
                po.NameObject("/1.2"),
            })
            obj11.update({
                po.NameObject("/Type"):
                po.NameObject("/SigRef"),
                po.NameObject("/TransformMethod"):
                po.NameObject("/DocMDP"),
                po.NameObject("/DigestMethod"):
                po.NameObject("/" + algomd.upper()),
                po.NameObject("/TransformParams"):
                obj10ref,
            })
            obj12[po.NameObject("/Reference")] = po.ArrayObject([obj11ref])
            catalog[po.NameObject("/Perms")] = obj14ref

        if "/AcroForm" in catalog:
            form = catalog["/AcroForm"].getObject()
            if "/Fields" in form:
                fields = form["/Fields"]
            else:
                fields = po.ArrayObject()
            fields.append(obj13ref)
            form.update({
                po.NameObject("/Fields"):
                fields,
                po.NameObject("/SigFlags"):
                po.NumberObject(udct.get("sigflags", 3)),
            })
            formref = catalog.raw_get("/AcroForm")
            if isinstance(formref, po.IndirectObject):
                self._objects[formref.idnum - 1] = form
                form = formref
        else:
            form = po.DictionaryObject()
            form.update({
                po.NameObject("/Fields"):
                po.ArrayObject([obj13ref]),
                po.NameObject("/SigFlags"):
                po.NumberObject(udct.get("sigflags", 3)),
            })
        catalog[po.NameObject("/AcroForm")] = form

        if "/Metadata" in catalog:
            catalog[po.NameObject("/Metadata")] = catalog.raw_get("/Metadata")

        x_root = prev.trailer.raw_get("/Root")
        self._objects[x_root.idnum - 1] = catalog
        self.x_root = po.IndirectObject(x_root.idnum, 0, self)
        self.x_info = prev.trailer.raw_get("/Info")
Ejemplo n.º 6
0
    def main(self, fname, password):
        with open(fname, "rb") as fi:
            datau = fi.read()
        startdata = len(datau)

        fi = io.BytesIO(datau)

        prev = pdf.PdfFileReader(fi)
        if prev.isEncrypted:
            rc = prev.decrypt(password)
        else:
            rc = 0

        algomd = "sha1"
        aligned = False

        obj = prev.trailer
        for k in ("/Root", "/Perms", "/DocMDP", "/Reference"):
            if k in obj:
                obj = obj[k]
                if isinstance(obj, po.ArrayObject):
                    obj = obj[0]
                obj = obj.getObject()
            else:
                obj = None
                break
        if obj is not None:
            algomd = obj["/DigestMethod"][1:].lower()

        if aligned:
            zeros = b"0" * 37888
        else:
            md = getattr(hashlib, algomd)().digest()
            contents = self.sign(md, algomd)
            zeros = contents.hex().encode("utf-8")

        self.makepdf(prev, algomd, zeros)

        if prev.isEncrypted:
            self.encrypt(prev, password, rc)
        else:
            self._encrypt_key = None
        ID = prev.trailer.get("/ID", None)
        if ID is None:
            ID = po.ByteStringObject(
                hashlib.md5(repr(time.time()).encode()).digest())
        else:
            ID = ID[0]
        self._ID = po.ArrayObject([
            ID,
            po.ByteStringObject(
                hashlib.md5(repr(random.random()).encode()).digest()),
        ])

        fo = io.BytesIO()
        self.write(fo, prev, startdata)
        datas = fo.getvalue()

        br = [0, 0, 0, 0]
        bfrom = (b"[ " + b" ".join([WNumberObject.Format] * 4) +
                 b" ]") % tuple(br)

        pdfbr1 = datas.find(zeros)
        pdfbr2 = pdfbr1 + len(zeros)
        br = [
            0,
            startdata + pdfbr1 - 1,
            startdata + pdfbr2 + 1,
            len(datas) - pdfbr2 - 1,
        ]
        bto = b"[%d %d %d %d]" % tuple(br)
        bto += b" " * (len(bfrom) - len(bto))
        assert len(bfrom) == len(bto)
        datas = datas.replace(bfrom, bto, 1)

        md = getattr(hashlib, algomd)()
        md.update(datau)
        b1 = datas[:br[1] - startdata]
        b2 = datas[br[2] - startdata:]
        md.update(b1)
        md.update(b2)
        md = md.digest()

        contents = self.sign(md, algomd)
        contents = contents.hex().encode("utf-8")
        if aligned:
            nb = len(zeros) - len(contents)
            contents += b"0" * nb
        datas = datas.replace(zeros, contents, 1)

        fname = fname.replace(".pdf", "-signed-pypdf.pdf")
        with open(fname, "wb") as fp:
            fp.write(datau)
            fp.write(datas)
Ejemplo n.º 7
0
def PdfArray(l):
    result = pdf.ArrayObject([])
    for v in l:
        v = makeObject(v)
        result.append(v)
    return result
Ejemplo n.º 8
0
    def makepdf(self, prev, udct, algomd, zeros, cert, **params):
        catalog = prev.trailer["/Root"]
        size = prev.trailer["/Size"]
        pages = catalog["/Pages"].getObject()
        page0ref = prev.getPage(udct.get("sigpage", 0)).indirectRef

        self._objects = []
        while len(self._objects) < size - 1:
            self._objects.append(None)


##        if params['mode'] == 'timestamp':
##            # deal with extensions
##            if '/Extensions' not in catalog:
##                extensions = po.DictionaryObject()
##            else:
##                extensions = catalog['/Extensions']
##
##            if '/ESIC' not in extensions:
##                extensions.update({
##                    po.NameObject("/ESIC"): po.DictionaryObject({
##                        po.NameObject('/BaseVersion'): po.NameObject('/1.7'),
##                        po.NameObject('/ExtensionLevel'): po.NumberObject(1),
##                        })
##                    })
##            else:
##                esic = extensions['/ESIC']
##                major, minor = esic['/BaseVersion'].lstrip('/').split('.')
##                if int(major) < 1 or int(minor) < 7:
##                    esic.update({
##                        po.NameObject('/BaseVersion'): po.NameObject('/1.7'),
##                        po.NameObject('/ExtensionLevel'): po.NumberObject(1),
##                        })
##            catalog.update({
##                po.NameObject('/Extensions'): extensions
##                })

# obj12 is the digital signature
        obj12, obj12ref = self._make_signature(
            Type=po.NameObject("/Sig"),
            SubFilter=po.NameObject("/adbe.pkcs7.detached"),
            Contents=UnencryptedBytes(zeros),
        )

        if params['mode'] == 'timestamp':
            # obj12 is a timestamp this time
            obj12.update({
                po.NameObject("/Type"):
                po.NameObject("/DocTimeStamp"),
                po.NameObject("/SubFilter"):
                po.NameObject("/ETSI.RFC3161"),
                po.NameObject("/V"):
                po.NumberObject(0),
            })
        else:
            obj12.update({
                po.NameObject("/Name"):
                po.createStringObject(udct["contact"]),
                po.NameObject("/Location"):
                po.createStringObject(udct["location"]),
                po.NameObject("/Reason"):
                po.createStringObject(udct["reason"]),
            })
            if params.get('use_signingdate'):
                obj12.update({
                    po.NameObject("/M"):
                    po.createStringObject(udct["signingdate"]),
                })

        # obj13 is a combined AcroForm Sig field with Widget annotation
        new_13 = True
        #obj13 = po.DictionaryObject()
        if udct.get('signform', False):
            # Attaching signature to existing field in AcroForm
            if "/AcroForm" in catalog:
                form = catalog["/AcroForm"].getObject()
                if "/Fields" in form:
                    fields = form["/Fields"].getObject()
                    obj13ref = [
                        f for f in fields if f.getObject()['/T'] == udct.get(
                            'sigfield', 'Signature1')
                    ][0]
                    obj13 = obj13ref.getObject()
                    self._objects[obj13ref.idnum - 1] = obj13
                    new_13 = False

        # box is coordinates of the annotation to fill
        box = udct.get("signaturebox", None)

        if new_13:
            obj13, obj13ref = self._make_sig_annotation(
                F=po.NumberObject(udct.get("sigflagsft", 132)),
                T=EncodedString(udct.get("sigfield", "Signature1")),
                Vref=obj12ref,
                Pref=page0ref,
            )
        else:
            # original obj13 is a merged SigField/SigAnnot
            # Setting /V on the AcroForm field sets the signature
            # for the field
            obj13.update({
                po.NameObject("/V"): obj12ref,
            })
            # fill the existing signature field annotation,
            # ignore any other location
            if "/Rect" in obj13:
                box = [float(f) for f in obj13["/Rect"]]

        # add an annotation if there is a field to fill
        if box is not None:
            from endesive.pdf.PyPDF2_annotate.annotations.signature import Signature
            from endesive.pdf.PyPDF2_annotate.config.appearance import Appearance
            from endesive.pdf.PyPDF2_annotate.config.location import Location
            from endesive.pdf.PyPDF2_annotate.util.geometry import identity

            x1, y1, x2, y2 = box
            annotation = Signature(
                Location(x1=x1, y1=y1, x2=x2, y2=y2, page=0),
                Appearance(),
            )
            if 'signature' in udct:
                # Plain text signature with the default font
                # text to render is contained in udct['signature']
                # font parameters are in udct['signature']['text']
                annotationtext = udct["signature"]
                wrap_text = udct.get('text', {}).get('wraptext', True)
                font_size = udct.get('text', {}).get('fontsize', 12)
                text_align = udct.get('text', {}).get('textalign', 'left')
                line_spacing = udct.get('text', {}).get('linespacing', 1.2)

                annotation.add_default_font()
                annotation.set_signature_appearance(
                    ['fill_colour', 0, 0, 0], ['font', 'default', font_size], [
                        'text_box', annotationtext, 'default', 0, 0, x2 - x1,
                        y2 - y1, font_size, wrap_text, text_align, 'middle',
                        line_spacing
                    ])
            elif 'signature_img' in udct:
                # Simple image signature, stretches to fit the box
                # image to render is contained in udct['signature_image']
                annotation.add_image(udct["signature_img"], "Image")
                annotation.set_signature_appearance([
                    'image',
                    "Image",
                    0,
                    0,
                    x2 - x1,
                    y2 - y1,
                    udct.get('signature_img_distort', True),
                    udct.get('signature_img_centred', False),
                ])
            elif 'signature_appearance' in udct:
                # Adobe-inspired signature with text and images
                # Parameters are contained in udct['signature_appearance']
                # If a field is included in the display list, that field
                # will be contained in the annotation.
                #
                # Text and border are the colour specified by outline,
                # and border is the the inset distance from the outer
                # edge of the annotation.  The R G B values range between
                # 0 and 1.
                #
                # Icon is an image to display above the background and
                # border at the left-hand side of the anntoation.  If
                # there is no text, it is centred.
                #
                # The text block is left-aligned to the right of the icon
                # image.  If there is no image, the text is left-aliged
                # with the left-hand border of the annotation
                #
                # display fields:
                #   CN, DN, date, contact, reason, location
                #
                # Dict format:
                #   appearance = dict(
                #       background = Image with alpha / None,
                #       icon = Image with alpha / None,
                #       labels = bool,
                #       display = list,
                #       software = str,
                #       outline = [R, G, B],
                #       border = int,
                #       )
                sig = {}
                for f in ('background', 'icon', 'labels', 'border', 'outline'):
                    if f in udct['signature_appearance']:
                        sig[f] = udct['signature_appearance'][f]

                toggles = udct['signature_appearance'].get('display', [])
                for f in ('contact', 'reason', 'location', 'contact',
                          'signingdate'):
                    if f in toggles:
                        sig[f] = udct.get(f, '{} unknown'.format(f))
                if 'date' in toggles:
                    sig['date'] = udct['signingdate']
                if 'CN' in toggles:
                    from cryptography.x509 import ObjectIdentifier
                    sig['CN'] = cert.subject.get_attributes_for_oid(
                        ObjectIdentifier('2.5.4.3'))[0].value
                if 'DN' in toggles:
                    sig['DN'] = cert.subject.rfc4514_string()
                annotation.simple_signature(sig)
            else:
                # Manual signature annotation creation
                #
                # Make your own appearance with an arbitrary number of
                # images and fonts
                if 'manual_images' in udct:
                    for name, img in udct['manual_images'].items():
                        annotation.add_image(img, name=name)
                if 'manual_fonts' in udct:
                    for name, path in udct['manual_fonts'].items():
                        annotation.add_ttf_font(path, name=name)
                annotation.add_default_font()
                annotation.set_signature_appearance(*udct['signature_manual'])

            pdfa = annotation.as_pdf_object(identity(), page=page0ref)
            objapn = self._extend(pdfa["/AP"]["/N"])
            objapnref = self._addObject(objapn)

            objap = po.DictionaryObject()
            objap[po.NameObject("/N")] = objapnref
            obj13.update({
                po.NameObject("/Rect"):
                po.ArrayObject([
                    po.FloatObject(x1),
                    po.FloatObject(y1),
                    po.FloatObject(x2),
                    po.FloatObject(y2),
                ]),
                po.NameObject("/AP"):
                objap,
                #po.NameObject("/SM"): po.createStringObject("TabletPOSinline"),
            })

            page0 = page0ref.getObject()
            if new_13:
                annots = po.ArrayObject([obj13ref])
                if "/Annots" in page0:
                    page0annots = page0["/Annots"]
                    if isinstance(page0annots, po.IndirectObject):
                        annots.insert(0, page0annots)
                    elif isinstance(page0annots, po.ArrayObject):
                        annots = page0annots
                        annots.append(obj13ref)
            else:
                annots = page0["/Annots"]
            page0.update({po.NameObject("/Annots"): annots})
            self._objects[page0ref.idnum - 1] = page0

        if udct.get("sigandcertify", False) and "/Perms" not in catalog:
            obj10 = po.DictionaryObject()
            obj10ref = self._addObject(obj10)
            obj11 = po.DictionaryObject()
            obj11ref = self._addObject(obj11)
            obj14 = po.DictionaryObject()
            obj14ref = self._addObject(obj14)
            obj14.update({po.NameObject("/DocMDP"): obj12ref})
            obj10.update({
                po.NameObject("/Type"):
                po.NameObject("/TransformParams"),
                po.NameObject("/P"):
                po.NumberObject(udct.get("sigflags", 3)),
                po.NameObject("/V"):
                po.NameObject("/1.2"),
            })
            obj11.update({
                po.NameObject("/Type"):
                po.NameObject("/SigRef"),
                po.NameObject("/TransformMethod"):
                po.NameObject("/DocMDP"),
                po.NameObject("/DigestMethod"):
                po.NameObject("/" + algomd.upper()),
                po.NameObject("/TransformParams"):
                obj10ref,
            })
            obj12[po.NameObject("/Reference")] = po.ArrayObject([obj11ref])
            catalog[po.NameObject("/Perms")] = obj14ref

        if "/AcroForm" in catalog:
            form = catalog["/AcroForm"].getObject()
            if "/Fields" in form:
                fields = form["/Fields"]
                old_field_names = [f.getObject()['/T'] for f in fields]
            else:
                fields = po.ArrayObject()
                old_field_names = []
            if udct.get('auto_sigfield',
                        False) and obj13['/T'] in old_field_names:
                name_base = udct.get('sigfield', 'Signature1')
                checklist = [
                    f[len(name_base):] for f in old_field_names
                    if f.startswith(name_base)
                ]
                for i in range(1, len(checklist) + 1):
                    suffix = '_{}'.format(i)
                    if suffix in checklist:
                        next

                    new_name = '{}{}'.format(name_base, suffix)
                    obj13.update(
                        {po.NameObject("/T"): EncodedString(new_name)})
                    break

            old_flags = int(form.get("/SigFlags", 0))
            new_flags = int(form.get("/SigFlags", 0)) | udct.get("sigflags", 3)
            if new_13:
                fields.append(obj13ref)
                form.update({
                    po.NameObject("/Fields"):
                    fields,
                    po.NameObject("/SigFlags"):
                    po.NumberObject(new_flags),
                })
            elif new_flags > old_flags:
                form.update({
                    po.NameObject("/SigFlags"):
                    po.NumberObject(new_flags),
                })
            formref = catalog.raw_get("/AcroForm")
            if isinstance(formref, po.IndirectObject):
                self._objects[formref.idnum - 1] = form
                form = formref
        else:
            form = po.DictionaryObject()
            form.update({
                po.NameObject("/Fields"):
                po.ArrayObject([obj13ref]),
                po.NameObject("/SigFlags"):
                po.NumberObject(udct.get("sigflags", 3)),
            })
        catalog[po.NameObject("/AcroForm")] = form

        if "/Metadata" in catalog:
            catalog[po.NameObject("/Metadata")] = catalog.raw_get("/Metadata")

        x_root = prev.trailer.raw_get("/Root")
        self._objects[x_root.idnum - 1] = catalog
        self.x_root = po.IndirectObject(x_root.idnum, 0, self)
        self.x_info = prev.trailer.get("/Info")
Ejemplo n.º 9
0
    def makepdf(self, prev, zeros):
        catalog = prev.trailer["/Root"]
        pages = catalog["/Pages"].getObject()
        page0 = pages["/Kids"][0]
        pages = catalog.raw_get("/Pages")

        self.x_info = prev.trailer.raw_get("/Info")
        self.x_root = prev.trailer.raw_get("/Root")

        while len(self._objects) < self.x_root.idnum:
            self._objects.append(None)
        # 14
        obj = po.DictionaryObject()
        obj.update({
            po.NameObject("/Type"): po.NameObject("/TransformParams"),
            po.NameObject("/P"): po.NumberObject(2),
            po.NameObject("/V"): po.NameObject("/1.2"),
        })
        obj14 = self._addObject(obj)
        # 13
        obj = po.DictionaryObject()
        obj.update({
            po.NameObject("/Type"): po.NameObject("/SigRef"),
            po.NameObject("/TransformMethod"): po.NameObject("/DocMDP"),
            po.NameObject("/DigestMethod"): po.NameObject("/SHA256"),
            po.NameObject("/TransformParams"): obj14,
        })
        obj13 = self._addObject(obj)
        # 12
        obj = po.DictionaryObject()
        obj.update({
            po.NameObject("/Type"):
            po.NameObject("/Sig"),
            po.NameObject("/Filter"):
            po.NameObject("/Adobe.PPKLite"),
            po.NameObject("/SubFilter"):
            po.NameObject("/adbe.pkcs7.detached"),
            po.NameObject("/Name"):
            S("Grzegorz Makarewicz"),
            po.NameObject("/Location"):
            S("Szczecin"),
            po.NameObject("/Reason"):
            S("Dokument podpisany cyfrowo"),
            po.NameObject("/M"):
            S("D:20200314100055+00'00'"),
            po.NameObject("/Reference"):
            po.ArrayObject([obj13]),
            po.NameObject("/Contents"):
            B(zeros),
            po.NameObject("/ByteRange"):
            po.ArrayObject([
                WNumberObject(0),
                WNumberObject(0),
                WNumberObject(0),
                WNumberObject(0),
            ]),
        })
        obj12 = self._addObject(obj)
        # 10
        obj = po.DictionaryObject()
        obj.update({po.NameObject("/DocMDP"): obj12})
        obj10 = self._addObject(obj)
        # 11
        obj = po.DictionaryObject()
        obj.update({
            po.NameObject("/FT"):
            po.NameObject("/Sig"),
            po.NameObject("/Type"):
            po.NameObject("/Annot"),
            po.NameObject("/Subtype"):
            po.NameObject("/Widget"),
            po.NameObject("/F"):
            po.NumberObject(132),
            po.NameObject("/T"):
            S("Signature1"),
            po.NameObject("/V"):
            obj12,
            po.NameObject("/P"):
            page0,
            po.NameObject("/Rect"):
            po.ArrayObject([
                po.NumberObject(0),
                po.NumberObject(0),
                po.NumberObject(0),
                po.NumberObject(0),
            ]),
        })
        obj11 = self._addObject(obj)
        # 9
        form = po.DictionaryObject()
        form.update({
            po.NameObject("/Fields"): po.ArrayObject([obj11]),
            po.NameObject("/SigFlags"): po.NumberObject(3),
        })
        obj = catalog
        obj.update({
            po.NameObject("/Perms"): obj10,
            po.NameObject("/AcroForm"): form
        })
        self._objects[self.x_root.idnum - 1] = obj
        self.x_root = po.IndirectObject(self.x_root.idnum, 0, self)