Add a signature field to a PDF

What I’m trying to do:
I have generated a PDF document using Anvil’s very good anvil.pdf.render_form method.
Now I need to add to the PDF the capabilty to be digitally signed.
To do this, I need to add a PDF-Form with a Digital Signature field.

What I’ve tried and what’s not working:
I tried looking at already installed packages that looked promising like PyPDF2 and fpdf2 but couldn’t sort it out.

Has anyone already done that and can he/she point me to the right tool (pip installable package?) to use?

Thank you

Just to share how I solved it, I installed PyHanko in my app’s virtual environment.

1 Like

Thank you for sharing. Is it possible to link a minimal clone of your solution?

Hi @nickantonaccio
sure! Here it is.

https://anvil.works/build#clone:AQ64KFRHRMKWDFUB=B7WXSWQTHXJOZX6W45VRZXHQ

It’s just a small server funcion.

from pyhanko.sign.fields import SigFieldSpec, append_signature_field
from pyhanko.pdf_utils.incremental_writer import IncrementalPdfFileWriter
import anvil.media

# PARAM 1: uploaded_file: anvil media with input pdf file
# PARAM 2: name: 'signatures'
#          type: list of dictionaries
#          valore: list of dictionaries representing signature fields to add:
#                  [
#                    {
#                      "sig_name": <string> signature field name, 
#                       "position": { 
#                          "page": <int> page to add the field to. Negative numbers are applied from the end,
#                          "x1": <int>, "y1": <int>, "x2": <int>, "y2": <int> signature field box in cartesian coordinates (i.e. (0,0) is lower left)
#                       }
#                    }
#                  ]
#         EXMAPLE: [{"sig_name":"signature_1","position":{"page":1,"x1":100,"y1":100,"x2":200,"y2":200}},{"sig_name":"signature_2","position":{"page":2,"x1":150,"y1":200,"x2":250,"y2":300}}]
# OUTPUT: anvil.media of the pdf file with the signatures

def add_sig_fields(uploaded_file, signatures):
  # write temp file and call pyhanko
  if uploaded_file.name[-4:] == ".pdf":
    output_filename = f"/tmp/{uploaded_file.name[:-4]}.pdf"
  else:
    output_filename = f"/tmp/{uploaded_file.name}.pdf"
  with open(output_filename, 'wb+') as doc:
    doc.write(uploaded_file.get_bytes())    
    w = IncrementalPdfFileWriter(doc)
    for signature in signatures:
      append_signature_field(
        w, 
        SigFieldSpec(
          sig_field_name = signature['sig_name'],
          on_page = signature['position']['page'],
          box = (signature['position']['x1'],signature['position']['y1'],signature['position']['x2'],signature['position']['y2'])
        )
      )
      w.write_in_place()
  output_media = anvil.media.from_file(output_filename, "application/pdf")
  return output_media

3 Likes

Thank you! Now exploring the ‘how to ensure signed pdf documents are legally binding’ Google rabbit hole…