Registry / auth-security / pyhanko

pyhanko

JSON →
library0.36.2pypypi✓ verified 26d ago

PyHanko is a Python library designed for stamping and digitally signing PDF files, offering extensive functionality for handling digital signatures, including support for various PAdES profiles and cryptographic operations. It is actively maintained with frequent minor releases, currently at version 0.34.1, and aims to cover the digital signing features of the PDF standard comprehensively.

pip install 'pyHanko[pkcs11,image-support,opentype,qr]' pyhanko-cli
INSTALL
IMPORT
SIG · PYHANKO
P
pyhanko
auth-securitypythonv0.36.2
Install
5.6s avg
Import
1132ms
Disk
57MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v0.36.2 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.910 runs
installs and imports cleanly · install 0.0s · import 1.172s · 57.8MB
glibc
py 3.103.910 runs
installs and imports cleanly · install 5.6s · import 1.091s · 58MB
57MB installed
● package 57MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

IncrementalPdfFileWriter
from pyhanko.pdf_utils.incremental_writer import IncrementalPdfFileWriter
SimpleSigner
from pyhanko.sign.signers import SimpleSigner
PdfSignatureMetadata
from pyhanko.sign.signers import PdfSignatureMetadata
PdfSigner
from pyhanko.sign.signers import PdfSigner
sign_pdf
from pyhanko.sign.signers import sign_pdf
HTTPTimeStamper
from pyhanko.sign.timestamps import HTTPTimeStamper
pyhanko_certvalidator
import pyhanko_certvalidator
import certvalidator
The certificate validator package was renamed from 'certvalidator' to 'pyhanko_certvalidator' in v0.6.0 to avoid namespace conflicts.

This quickstart demonstrates how to digitally sign a PDF document using `pyhanko` with a simple signer. It covers loading the signing key and certificate, applying a signature to a PDF, and saving the output. For a real application, you would replace the dummy key/cert paths with your actual cryptographic materials.

import io import os from pyhanko.pdf_utils.incremental_writer import IncrementalPdfFileWriter from pyhanko.sign import signers def sign_document_example(input_path, output_path, key_path, cert_path, ca_chain_path=None, key_passphrase=None): # Create dummy key and cert files for runnable example with open('dummy_key.pem', 'w') as f: f.write('-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----') # Placeholder with open('dummy_cert.pem', 'w') as f: f.write('-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----') # Placeholder if ca_chain_path: # Create dummy CA chain if path provided with open('dummy_ca_chain.pem', 'w') as f: f.write('-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----') # Placeholder # In a real scenario, replace 'dummy_key.pem' and 'dummy_cert.pem' # with paths to your actual signer key and certificate. # key_passphrase should be bytes, e.g., b'your_password' # Load the signer key and certificate cms_signer = signers.SimpleSigner.load( key_path or 'dummy_key.pem', cert_path or 'dummy_cert.pem', ca_chain_files=(ca_chain_path or 'dummy_ca_chain.pem',) if ca_chain_path else None, key_passphrase=key_passphrase ) with open(input_path, 'rb') as doc_input: w = IncrementalPdfFileWriter(doc_input) out = signers.sign_pdf( w, signers.PdfSignatureMetadata(field_name='Signature1'), # Use an existing field or 'Signature1' will be created signer=cms_signer, ) with open(output_path, 'wb') as doc_output: doc_output.write(out.read()) print(f"Document signed: {output_path}") # Example usage (requires a dummy PDF and actual key/cert files in a real scenario) # You can create a dummy PDF file like 'input.pdf' for testing. # Replace 'your_key.pem', 'your_cert.pem', 'your_ca_chain.pem' with actual paths. # To run this example, ensure you have a 'input.pdf' file. # And replace the '...'(s) with actual PEM contents from your test certificates if you want to run it end to end. # try: # # Create a minimal dummy PDF for testing if it doesn't exist # if not os.path.exists('input.pdf'): # from PyPDF2 import PdfWriter # writer = PdfWriter() # writer.add_blank_page(width=72, height=72) # with open('input.pdf', 'wb') as f: writer.write(f) # # sign_document_example( # input_path='input.pdf', # output_path='signed_output.pdf', # key_path=os.environ.get('PYHANKO_SIGNER_KEY_PATH', 'dummy_key.pem'), # cert_path=os.environ.get('PYHANKO_SIGNER_CERT_PATH', 'dummy_cert.pem'), # ca_chain_path=os.environ.get('PYHANKO_CA_CHAIN_PATH', 'dummy_ca_chain.pem'), # key_passphrase=os.environ.get('PYHANKO_KEY_PASSPHRASE', '').encode('utf-8') # ) # finally: # # Clean up dummy files # for f in ['dummy_key.pem', 'dummy_cert.pem', 'dummy_ca_chain.pem']: # if os.path.exists(f): os.remove(f)
pyhanko --version
Debug
Known issues
breakingThe `pyhanko-cli` package was separated from the main `pyhanko` library. Direct imports or reliance on the CLI being bundled with `pyhanko` will break.
fix
Install `pyhanko-cli` explicitly: `pip install pyhanko-cli`. If using optional dependencies, include it in the same command: `pip install 'pyHanko[pkcs11]' pyhanko-cli`.
affects: >=0.28.0
breakingThe `certvalidator` dependency, originally an internal fork, was renamed to `pyhanko_certvalidator` to prevent namespace conflicts.
fix
Update import statements from `import certvalidator` to `import pyhanko_certvalidator`.
affects: >=0.6.0
gotchaPyHanko considers 'hybrid reference files' less secure and disables strict parsing for them by default to avoid accidental corruption. Attempting to process them in strict mode will result in errors.
fix
For API users, pass `strict=False` to `IncrementalPdfFileWriter` or `PdfFileReader` objects when handling hybrid files. For CLI users, use the `--no-strict-syntax` switch.
affects: >=0.12.0
deprecatedThe old LTV (Long-Term Validation) functionality provided by `async_validate_pdf_ltv_signature()` has been deprecated.
fix
Consult the latest documentation for updated LTV validation APIs. The documentation notes that LTV validation is still ad-hoc and may not fully adhere to PAdES specifications.
affects: >=0.31.0
gotchaPyHanko does not provide explicit support for signing or stamping PDF/A and PDF/UA files, meaning the output may not comply with these standards.
fix
While `pyhanko` attempts to not unnecessarily break conformance, users should be aware that it does not enforce additional restrictions for PDF/A or PDF/UA. Manual validation or external tooling may be required to ensure compliance.
affects: All versions
gotchaComments and annotations added to a signed PDF are considered 'unsafe' changes by `pyhanko`, regardless of the signer's policy.
fix
Avoid adding comments or annotations to PDFs that have already been signed if strict document integrity is paramount, as `pyhanko`'s validation will flag these as modifications.
affects: All versions
Upgrade
Version history
0.36.2latest on PyPI · released Jul 26, 2026
Audit
Dependencies
pyhanko-clirequiredProvides command-line interface (CLI) functionality; separated from the main library in v0.28.0.
PythonrequiredRequires Python 3.10 or later for compatibility.
pkcs11optionalOptional dependency for PKCS#11 device support.
image-supportoptionalOptional dependency for image handling in stamps.
opentypeoptionalOptional dependency for OpenType/TrueType font support in stamps.
qroptionalOptional dependency for QR code generation in stamps.
async-httpoptionalOptional dependency for asynchronous HTTP operations.
etsioptionalOptional dependency for ETSI (European Telecommunications Standards Institute) related functionality.
Agent activity
16 hits · last 30 days
node
12
OpenAI (training)
1
Resources
pyhanko — pip install pyhanko · libregistry