[Python] pickle a pyhanko signers object

Discussão em 'Python' iniciado por Stack, Junho 3, 2025.

  1. Stack

    Stack Membro Participativo

    I am writing a small tool for signing pdf files. I want to store the signers.SimpleSigner.load_pkcs12() object (see below) so that I can load it on next start of the program and don't have to type my password every time (and also I do not have to store a password).

    jupyter lab


    In jupyter lap the code below works, even if I save the file (= serialise the pickled signer object), shut down jupyter, start it up and load the file (unserialise the pickled signer object) and then sign a pdf (of course I have to import the libraries again).

    import pickle
    import base64

    def serialize_object_to_b64(obj):
    """Pickle-Objekt in Bytes serialisieren und Base64-codieren."""
    pickled_bytes = pickle.dumps(obj)
    b64_string = base64.b64encode(pickled_bytes).decode('utf-8')
    return b64_string

    def deserialize_object_from_b64(b64_string):
    """Base64-String zurück in Bytes und ent-picklen."""
    pickled_bytes = base64.b64decode(b64_string.encode('utf-8'))
    obj = pickle.loads(pickled_bytes)
    return obj


    from pyhanko.sign import signers
    from pyhanko.pdf_utils.incremental_writer import IncrementalPdfFileWriter
    import asyncio #explained below
    import nest_asyncio #explained below
    nest_asyncio.apply() #explained below

    cert_obj_before_save = signers.SimpleSigner.load_pkcs12(
    pfx_file='test.pfx',
    passphrase=b'#####',
    )

    serial_cert = serialize_object_to_b64(c1ert)
    with open('testfile.txt', 'w') as file:
    file.write(serial_cert)

    [...] here I can stop and close jupyter lab then start it again (load the libraries again)

    with open('testfile.txt', 'r') as file:
    serial_cert_from_file = file.read()
    cert_obj_AFTER_save = deserialize_object_from_b64(serial_cert_from_file)

    with open('test.pdf', 'rb') as inf:
    w = IncrementalPdfFileWriter(inf)

    meta = signers.PdfSignatureMetadata(field_name='Signature3')
    pdf_signer = signers.PdfSigner(meta, signer=cert_obj_AFTER_save)
    with open('document-signed.pdf', 'wb') as outf:
    pdf_signer.sign_pdf(w, output=outf)


    python script with tkinter started from console


    I want a GUI. So during testing I have small python script with tkinter. If I load the pfx file and unlock it (signers.SimpleSigner.load_pkcs12()), I can "use" the signer object to sign pdfs. But if I save and load it with following code, I get an error (error is further down).

    # how I pickle the signer object
    scert = serialize_object_to_b64(my_object)
    with open("my_object_b64.txt", "w") as txt_file:
    txt_file.write(scert)

    # how it is unpickled
    if os.path.exists("my_object_b64.txt"):
    with open("my_object_b64.txt", "r") as txt_file:
    scert = txt_file.read()
    self.my_object = deserialize_object_from_b64(scert)

    # how the pdf is signed
    def sign_pdf(cert_object, file_path, new_path):
    with open(file_path, 'rb') as infile:
    writer = IncrementalPdfFileWriter(infile)
    meta = signers.PdfSignatureMetadata(field_name='Signature3')
    pdf_signer = signers.PdfSigner(meta, signer=cert_object)
    with open(new_path, 'wb') as outfile:
    pdf_signer.sign_pdf(writer, output=outfile)


    In jupyter lab I also have to import asyncio and nest_asyncio to get pyhanko to work. But this is not needed in the python script, I can sign pdfs with a pfx file. When I use a stored and unpickled object I noticed that the error changes if I import asyncio or not.

    Error message with ´import asyncio´


    Exception in Tkinter callback
    Traceback (most recent call last):
    File "C:\Users\x\AppData\Local\Programs\Python\Python311\Lib\tkinter\__init__.py", line 1967, in __call__
    return self.func(*args)
    ^^^^^^^^^^^^^^^^
    File "C:\Users\x\Documents\sign-venv\gui.py", line 329, in handle_drop
    sign_pdf( dropped_file,
    File "C:\Users\x\Documents\sign-venv\gui.py", line 48, in sign_pdf
    pdf_signer = signers.PdfSigner(
    ^^^^^^^^^^^^^^^^^^
    File "C:\Users\x\Documents\sign-venv\Lib\site-packages\pyhanko\sign\signers\pdf_signer.py", line 1082, in __init__
    mech = self.signer.get_signature_mechanism_for_digest(None)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "C:\Users\x\Documents\sign-venv\Lib\site-packages\pyhanko\sign\signers\pdf_cms.py", line 407, in get_signature_mechanism_for_digest
    algo = self.signing_cert.public_key.algorithm
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "C:\Users\x\Documents\sign-venv\Lib\site-packages\asn1crypto\x509.py", line 2538, in public_key
    return self['tbs_certificate']['subject_public_key_info']
    ~~~~^^^^^^^^^^^^^^^^^^^
    File "C:\Users\x\Documents\sign-venv\Lib\site-packages\asn1crypto\core.py", line 3508, in __getitem__
    self._parse_children()
    File "C:\Users\x\Documents\sign-venv\Lib\site-packages\asn1crypto\core.py", line 3988, in _parse_children
    raise e
    File "C:\Users\x\Documents\sign-venv\Lib\site-packages\asn1crypto\core.py", line 3895, in _parse_children
    cls._precomputed_specs[field] or self._determine_spec(field))
    ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^
    TypeError: 'NoneType' object is not subscriptable
    while parsing asn1crypto.x509.Certificate

    Error message without ´import asyncio´


    Exception in Tkinter callback
    Traceback (most recent call last):
    File "C:\Users\x\AppData\Local\Programs\Python\Python311\Lib\tkinter\__init__.py", line 1967, in __call__
    return self.func(*args)
    ^^^^^^^^^^^^^^^^
    File "C:\Users\x\Documents\sign-venv\gui.py", line 325, in handle_drop
    sign_pdf( dropped_file,
    File "C:\Users\x\Documents\sign-venv\gui.py", line 44, in sign_pdf
    pdf_signer = signers.PdfSigner(
    ^^^^^^^^^^^^^^^^^^
    File "C:\Users\x\Documents\sign-venv\Lib\site-packages\pyhanko\sign\signers\pdf_signer.py", line 1082, in __init__
    mech = self.signer.get_signature_mechanism_for_digest(None)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "C:\Users\x\Documents\sign-venv\Lib\site-packages\pyhanko\sign\signers\pdf_cms.py", line 407, in get_signature_mechanism_for_digest
    algo = self.signing_cert.public_key.algorithm
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "C:\Users\x\Documents\sign-venv\Lib\site-packages\asn1crypto\x509.py", line 2538, in public_key
    return self['tbs_certificate']['subject_public_key_info']
    ~~~~^^^^^^^^^^^^^^^^^^^
    File "C:\Users\x\Documents\sign-venv\Lib\site-packages\asn1crypto\core.py", line 3511, in __getitem__
    if key not in self._field_map:
    ^^^^^^^^^^^^^^^^^^^^^^^^^^
    TypeError: argument of type 'NoneType' is not iterable


    I do not understand the difference between jupyter lab and the script.

    Continue reading...

Compartilhe esta Página