NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #1771 most downloaded on PyPI
Validates X.509 certificates and paths; forked from wbond/certvalidator
Last release 24 days ago
10 Sep 2026
Release timing varies
gaps range from 9 days to 5 months
Nearly every release is documented
notes for 56 of 56 stable releases
4 versions withdrawn
withdrawn after publishing
6 years old
60 releases · first in 2020
One column per quarter.
The release artifacts have been published to PyPI .
The release artifacts have been published to PyPI.
The release notes for the 0.32.1 release are available on the Release History page
Release date: 2026-09-10
Fix host name normalisation in name constraints.
Release date: 2026-09-10
Fix host name normalisation in name constraints.
The release artifacts have been published to PyPI .
The release artifacts have been published to PyPI.
The release notes for the 0.32.0 release are available on the Release History page
Release date: 2025-11-22
Support Python 3.14
Relax uharfbuzz upper bound to <0.51.0 .
Warning
PyHanko currently does not test against free-threaded Python builds. Feel free to raise issues related to free-threaded Python in the discussion forum or on the issue tracker if you’re sure the problem is pyHanko-related, but there are currently no concrete plans to actively pursue support for this.
Support reading PKCS#12 data from memory.
Make PKCS#11 sign_kwargs easier to customise in subclasses.
Support basic text field filling.
Put in place scaffolding for content stream parsing.
The release artifacts have been published to PyPI .
The release artifacts have been published to PyPI.
The release notes for the 0.31.4 release are available on the Release History page
Release date: 2026-07-26
No functional changes, this release adopts the new attestation strategy .
Release date: 2026-07-26
No functional changes, this release adopts the new attestation strategy.
The release artifacts have been published to PyPI .
The release artifacts have been published to PyPI.
The release notes for the 0.31.3 release are available on the Release History page
Release date: 2026-07-25
No changes. Re-run to address a CI configuration issue.
Release date: 2026-07-25
No changes. Re-run to address a CI configuration issue.
- Mass-apply linting fixes to comply with new ruff default ruleset.
Release date: 2026-07-25
Mass-apply linting fixes to comply with new ruff default ruleset.
Relax upper bound for aiohttp to <3.15 .
Release date: 2026-07-25
Mass-apply linting fixes to comply with new ruff default ruleset.
Relax upper bound for aiohttp to <3.15.
The release artifacts have been published to PyPI.
The release artifacts have been published to PyPI.
The release notes for the 0.31.1 release are available on the Release History page
Release date: 2026-05-06
Bump cryptography to 48.0.0 .
ML-DSA support.
The release artifacts have been published to PyPI. Documentation is available on ReadTheDocs.
The release artifacts have been published to PyPI. Documentation is available on ReadTheDocs.
The release notes for the 0.31.0 release are available on the Release History page
Release date: 2025-09-12
Some pieces of the configuration API were refactored or pushed fully into the CLI layer.
The old LTV validation functionality provided by async_validate_pdf_ltv_signature() has now been deprecated and may be removed in a future release.
Release date: 2025-09-12
Some pieces of the configuration API were refactored or pushed fully into the CLI layer.
The old LTV validation functionality provided by ~pyhanko.sign.validation.ltv.async_validate_pdf_ltv_signature has now been deprecated and may be removed in a future release.
The release artifacts have been published to PyPI.
The release artifacts have been published to PyPI.
The release notes for the 0.30.2 release are available on the Release History page
Release date: 2026-03-27
Fix issue #648 , causing OCSP responses to fail to be processed if the responder certificate’s subject key identifier is not generated in the standard way.
Release date: 2026-03-27
Fix issue #648, causing OCSP responses to fail to be processed if the responder certificate's subject key identifier is not generated in the standard way.
The release artifacts have been published to PyPI.
The release artifacts have been published to PyPI.
The release notes for the 0.30.1 release are available on the Release History page
Release date: 2026-03-08
Address a packaging error with tests directory in sdists.
Release date: 2026-03-08
Address a packaging error with tests directory in sdists.
The release artifacts have been published to PyPI.
The release artifacts have been published to PyPI.
The release notes for the 0.30.0 release are available on the Release History page
The release artifacts have been published to PyPI. Documentation is available on ReadTheDocs.
The release notes for the 0.30.0 release are available on the Release History page
Release date: 2025-08-23
Bump python-pkcs11 to 0.9.x .
Introduce signxml>=4.2.0 into [etsi] dependency group.
Allow custom text and stamp border colours.
Allow slotting in a custom validation implementation (e.g. to support validating signatures that require cryptographic primitives that aren’t supported in-tree). This applies to certificate validation as well. See SignatureValidator .
Add support for validating against ETSI TS 119 612 trusted lists (as used in the EU’s eIDAS programme) and deriving qualification judgments from such lists for signatures and timestamps. This is an incubating feature; in particular it is not yet exposed in the CLI.
The release artifacts have been published to PyPI.
The release artifacts have been published to PyPI.
The release notes for the 0.29.1 release are available on the Release History page
The release artifacts have been published to PyPI. Documentation is available on ReadTheDocs.
The release notes for the 0.29.1 release are available on the Release History page
Release date: 2025-06-20
Bump python-pkcs11 to 0.8.0 .
Relax aiohttp upper bound to allow 3.12.x and make sure we test against the most recent version.
Correct buggy behaviour when reauthenticating with a security handler.
Fix registration of multiple extensions in encrypted files.
Tolerate key usage violations when the signer is a trust anchor.
Remove unnecessary 3.8 compatibility code.
Make it easier to customise PKCS#11 queries
The release artifacts have been published to PyPI.
The release artifacts have been published to PyPI.
The release notes for the 0.29.0 release are available on the Release History page
Note: As indicated in the release notes, the CLI was split off from the core library into a separate PyPI artifact. This release also comes with several other significant dependency changes.
The release artifacts have been published to PyPI. Documentation is available on ReadTheDocs.
The release notes for the 0.29.0 release are available on the Release History page
Release date: 2025-05-27
The pyhanko.keys and pyhanko.stamp modules were turned into packages, exposing the same API in their respective init.py , so this change is source-compatible.
The version and version_info attributes are no longer exposed at the root package level, but have been moved into pyhanko.version (which was also turned into a subpackage).
The CLI code still installs as pyhanko.cli in the package hierarchy.
There are no code-level changes for CLI plugins other than the requirement to add a dependency on pyhanko-cli . In principle, this allows “old” plugins to keep working without needing a re-release as long as pyhanko-cli is installed together with pyhanko .
Make the dependency on qrcode optional (in the new [qr] dependency group)
Replace defusedxml with a dependency on lxml , configured appropriately. This was done in anticipation of some future feature work that will require a dependency on lxml either way.
The release artifacts have been published to PyPI.
The release artifacts have been published to PyPI.
The release notes for the 0.28.0 release are available on the Release History page
The release artifacts have been published to PyPI. Documentation is available on ReadTheDocs.
The release notes for the 0.28.0 release are available on the Release History page
Release date: 2025-05-24
Drop support for Python 3.8
Retool repository structure as uv multi-project workspace.
Include pyhanko-certvalidator as subproject.
Remove dev-only & testing dependencies from package metadata.
Fix error in SHA-3 detection when determining whether to include the ISO/TS 32001 extension metadata.
The release artifacts have been published to PyPI.
The release artifacts have been published to PyPI.
The release notes for the 0.27.0 release have been included in the changelog file
The release artifacts have been published to PyPI. Documentation is available on ReadTheDocs.
The release notes for the 0.27.0 release are available on the Release History page
Release date: 2025-05-12
Relax uharfbuzz upper bound to <0.51.0 .
Constrain click to <8.2.0 while we address breaking changes.
Bump test dependencies.
Allow choosing whether to apply stamps in the page’s default coordinate system, or in the frame of reference that is active at the end of the page’s content stream. The former is now the default.
Fix handling of “plugin unavailable” error.
Clear /NeedAppearances when putting in a signature.
- Fixed bug where an HTTP(S) CRL URI appearing next to an LDAP one as part of the same DP entry would not always be picked up.
Release date: 2025-03-15
Fixed bug where an HTTP(S) CRL URI appearing next to an LDAP one as part of the same DP entry would not always be picked up.
Dramatically improved processing speed for large CRLs.
Release date: 2025-03-15
Fixed bug where an HTTP(S) CRL URI appearing next to an LDAP one as part of the same DP entry would not always be picked up.
Dramatically improved processing speed for large CRLs.
Release date: 2025-03-12 - No functional changes.
Release date: 2025-03-12
No functional changes.
- List qcStatements as a known extension
Release date: 2025-03-12
Drop Python 3.7
List qcStatements as a known extension
Release date: 2025-03-12
Drop Python 3.7
List qcStatements as a known extension
- Future-proofing against an upcoming asn1crypto that is already being shipped in some distro packages.
Release date: 2024-11-17
Future-proofing against an upcoming asn1crypto that is already being shipped in some distro packages.
Address some timing issues in tests.
Release date: 2024-11-17
Future-proofing against an upcoming asn1crypto that is already being shipped in some distro packages.
Address some timing issues in tests.
- Bump aiohttp requirement to >=3.8,<3.11 .
Release date: 2024-11-12
Bump aiohttp requirement to >=3.8,<3.11 .
Declare support for Python 3.12 and 3.13
Release date: 2024-11-12
Bump aiohttp requirement to >=3.8,<3.11.
Declare support for Python 3.12 and 3.13
- Bump aiohttp requirement to >=3.8,<3.10 .
Release date: 2023-12-13
Bump aiohttp requirement to >=3.8,<3.10 .
Address two certificate fetching issues.
Tolerate CMS certificate-only message in response without Content-Type .
Deal with implicit reliance on order of certs when processing such messages.
Release date: 2023-12-13
Bump aiohttp requirement to >=3.8,<3.10.
Address two certificate fetching issues.
Tolerate CMS certificate-only message in response without Content-Type.
Deal with implicit reliance on order of certs when processing such messages.
- Bump some dependency versions.
Release date: 2023-11-18
Bump some dependency versions.
- Handle nonspecific OCSP validation errors cleanly during validation.
Release date: 2023-11-18
Handle nonspecific OCSP validation errors cleanly during validation.
Release date: 2023-11-18
Handle nonspecific OCSP validation errors cleanly during validation.
The release artifacts have been published to PyPI. Documentation is available on ReadTheDocs.
The release artifacts have been published to PyPI. Documentation is available on ReadTheDocs.
The release notes for the 0.26.0 release are available on the Release History page
Release date: 2025-03-08
Some outdated algos for encrypting the security handler seed in a public-key encrypted PDF were dropped to get rid of oscrypto as a direct dependency of pyhanko . It is still pulled in via pyhanko-certvalidator , but it is no longer used for any cryptographic operations (which is significant, because of compatibility issues on systems that no longer ship OpenSSL 1.1.1)
Relax uharfbuzz upper bound to <0.47.0 .
Make defusedxml a regular dependency, remove [xmp] dependency group.
Remove [extra-pubkey-algs] dependency group (see breaking change list)
Expose signature_mechanism parameter in PKCS#11 API.
The release artifacts have been published to PyPI. Documentation is available on ReadTheDocs.
The release artifacts have been published to PyPI. Documentation is available on ReadTheDocs.
The release notes for the 0.25.0 release are available on the Release History page
Release date: 2024-05-06
Implement ISO/TS 32003 and ISO/TS 32004, to support AES-GCM streams and MAC authentication in encrypted PDF 2.0 documents, respectively. MACs are turned on by default when creating documents with PDF 2.0-style encryption.
- Ignore content types altogether when fetching certificates and the response payload is PEM.
Release date: 2023-09-17
Ignore content types altogether when fetching certificates and the response payload is PEM.
Release date: 2023-09-17
Ignore content types altogether when fetching certificates and the response payload is PEM.
The release artifacts have been published to PyPI. Documentation is available on ReadTheDocs.
The release artifacts have been published to PyPI. Documentation is available on ReadTheDocs.
The release notes for the 0.24.0 release are available on the Release History page
Release date: 2024-04-27
Setting & retrieving permission flags for encrypted files now comes with an ergonomic API that is much less error-prone. You no longer have to manually convert your permission bits to their signed integer representation. See pyhanko.pdf_utils.crypt.permissions .
Upgraded xsdata (optional) to 24.4 .
Several issues with copying objects from encrypted documents (in particular, encrypted documents with signatures) have been fixed.
Tolerate unpadded empty ciphertext.
Improve error messages on malformed keys.
The release artifacts have been published to PyPI. Documentation is available on ReadTheDocs.
The release artifacts have been published to PyPI. Documentation is available on ReadTheDocs.
The release notes for the 0.23.0 release are available on the Release History page
Release date: 2024-03-10
The BeID signer implementation and CLI command was moved into a separate package; see pyhanko-beid-plugin . While this integration was so far preserved in the core tree for historical reasons, pyHanko has matured beyond this kind of vendor/country-specific code. Note that CLI invocations will continue to work unchanged as long as pyhanko-beid-plugin is installed alongside pyHanko, thanks to Python’s package entry point mechanism.
The release artifacts have been published to PyPI. Documentation is available on ReadTheDocs.
The release artifacts have been published to PyPI. Documentation is available on ReadTheDocs.
The release notes for the 0.22.0 release are available on the Release History page
Release date: 2024-03-07
Relax upper bounds on xsdata and uharfbuzz .
cryptography` to ``42.0.1
Get rid of pytest-runner
Relax processing of PKCS#11 options, setting better defaults so users have to write less config to select their key/certificate. (see PR #296 )
Add timestamp command to CLI to add a document timestamp without performing any PAdES validation.
Gracefully handle lack of /Type entry in signature objects vailidation.
- Fix a typing issue caused by a typo in the requests cert fetcher.
Release date: 2023-04-17
Fix a typing issue caused by a typo in the requests cert fetcher.
Removed a piece of misbehaving and duplicative logic in the revocation freshness checker.
Release date: 2023-04-17
Fix a typing issue caused by a typo in the requests cert fetcher.
Removed a piece of misbehaving and duplicative logic in the revocation freshness checker.
- Fix DisallowedAlgorithmError parameters.
Release date: 2023-04-02
Fix DisallowedAlgorithmError parameters.
Preserve timestamp info in expiration-related errors.
Disable algo enforcement in prima facie past validation checks.
Correct a misunderstanding in the interaction between the AdES code and the old “retroactive revinfo” setting.
Release date: 2023-04-02
Fix DisallowedAlgorithmError parameters.
Preserve timestamp info in expiration-related errors.
Disable algo enforcement in prima facie past validation checks.
Correct a misunderstanding in the interaction between the AdES code and the old "retroactive revinfo" setting.
The release artifacts have been published to PyPI. Documentation is available on ReadTheDocs.
The release artifacts have been published to PyPI. Documentation is available on ReadTheDocs.
The release notes for the 0.21.0 release are available on the Release History page
Release date: 2023-11-26
Bumped the minimal supported Python version to 3.8 (dropping 3.7).
Bumped the lower bound on qrcode to 7.3.1 .
Bumped pyhanko-certvalidator to 0.26.x .
Bumped the lower bound on click to 8.1.3 .
Bumped the lower bound on requests to 2.31.0 .
Bumped the lower bound on pyyaml to 6.0 .
Bumped the lower bound on cryptography to 41.0.5 .
Bumped aiohttp to 3.9.x .
Bumped certomancer-csc-dummy test dependency to 0.2.3 .
Introduced new dependency group etsi with xsdata for features implementing functionality from AdES and related ETSI standards.
Add support for /ContactInfo , /Prop_AuthTime and /Prop_AuthType .
Experimental support for AdES validation reports (requires new etsi optional deps)
New API function for simulating PAdES-LTA validation at a time in the future; see simulate_future_ades_lta_validation() .
Add support for asserting the nonrevoked status of a certificate chain.
Add --resave flag to addfields subcommand.
Fixed an oversight in the serialisation of the /ByteRange entry in a signature that prevented large documents from being signed correctly.
Various adjustments to the (still experimental) AdES validation API.
Various local documentation fixes.
PDF signatures that do not omit the eContent field in their encapsulated content info are now rejected as invalid.
Include PyPDF2 licence file in package metadata.
Cleaned up loading logic in PdfFileReader . The most important impact of this change is that structural errors in the encryption dictionary will now cause exceptions to be thrown when decryption is attempted, not in the init function.
The release artifacts have been published to PyPI. Documentation is available on ReadTheDocs.
The release artifacts have been published to PyPI. Documentation is available on ReadTheDocs.
The release notes for the 0.20.1 release are available on the Release History page
Release date: 2023-09-17
Upgrade pyhanko-certvalidator to 0.24.x
Tolerate missing D: in date strings (see PR #296 ).
Various minor documentation improvements.
Release workflow dependency bumps and minor improvements.
Release date: 2023-09-17
Upgrade pyhanko-certvalidator to 0.24.x
Tolerate missing D: in date strings (see PR #296).
Various minor documentation improvements.
Release workflow dependency bumps and minor improvements.
The release artifacts have been published to PyPI. Documentation is available on ReadTheDocs.
The release artifacts have been published to PyPI. Documentation is available on ReadTheDocs.
The release notes for the 0.20.0 release are available on the Release History page
Release date: 2023-07-28
Relax upper bound on uharfbuzz to <0.38.0 (allows more users to benefit from prebuilt wheels)
Bump python-barcode from 0.14.0 to 0.15.1 .
Bump pytest-asyncio from 0.21.0 to 0.21.1 .
Relax pytest-cov bound to allow 4.1.x
Various minor documentation improvements.
Improved unit test coverage, especially for error handling.
- Fix double encoding when generating OCSP nonces
Release date: 2022-12-20
Fix double encoding when generating OCSP nonces
Release date: 2022-12-20
Fix double encoding when generating OCSP nonces
- Make certificate fetcher more tolerant (see #2)
Release date: 2022-12-11
Make certificate fetcher more tolerant (see #2)
Release date: 2022-12-11
Make certificate fetcher more tolerant (see #2)
Release date: 2022-10-27 - Update asn1crypto to 1.5.1 - Declare Python 3.11 support
Release date: 2022-10-27
Update asn1crypto to 1.5.1
Declare Python 3.11 support
Release date: 2022-10-27
Update asn1crypto to 1.5.1
Declare Python 3.11 support
- Maintenance update to bump asn1crypto to 1.5.0 and get rid of a number of compatibility shims for fixes that were upstreamed to asn1crypto .
Release date: 2022-03-08
Maintenance update to bump asn1crypto to 1.5.0 and get rid of a number of compatibility shims for fixes that were upstreamed to asn1crypto .
Release date: 2022-03-08
Maintenance update to bump asn1crypto to 1.5.0 and get rid of a number of compatibility shims for fixes that were upstreamed to asn1crypto.
- Fix improper error handling when dealing with expired or not-yet-valid attribute certificates.
Release date: 2022-02-10
Fix improper error handling when dealing with expired or not-yet-valid attribute certificates.
Release date: 2022-02-10
Fix improper error handling when dealing with expired or not-yet-valid attribute certificates.
- Correct and improve behaviour of certificate fetcher when the server does not supply a Content-Type header.
Release date: 2022-02-03
Correct and improve behaviour of certificate fetcher when the server does not supply a Content-Type header.
Release date: 2022-02-03
Correct and improve behaviour of certificate fetcher when the server does not supply a Content-Type header.
- Patch asn1crypto to work around tagging issue in AC issuer field
Release date: 2021-12-22
Patch asn1crypto to work around tagging issue in AC issuer field
Release date: 2021-12-22
Patch asn1crypto to work around tagging issue in AC issuer field
- Properly enforce algo matching in AC validation
Release date: 2021-12-22
Properly enforce algo matching in AC validation
Release date: 2021-12-22
Properly enforce algo matching in AC validation
The release artifacts have been published to PyPI. Documentation is available on ReadTheDocs.
The release artifacts have been published to PyPI. Documentation is available on ReadTheDocs.
The release notes for the 0.19.0 release are available on the Release History page
Release date: 2023-06-18
Bump pyhanko-certvalidator to 0.23.0
certomancer updated to 0.11.0 , certomancer-csc-dummy to 0.2.2
Minor reorganisation of the EnvelopeKeyDecrypter . The change moves the cert property from an attribute to an abstract property, and adds a method to allow us to handle protocols based on key agreement in addition to key transport. Implementations need not implement both.
Move ignore_key_usage into to new RecipientEncryptionPolicy class.
Support RSAES-OAEP for file encryption with the public-key security handler. This is not widely supported by PDF viewers in the wild.
Support some ECDH-based key exchange methods for file encryption with the public-key security handler. Concretely, pyHanko now supports the dhSinglePass-stdDH-sha*kdf family from RFC 5753, which is also implemented in Acrobat (for NIST curves). X25519 and X448 are also included.
Better UX for argument errors relating to visible signature creation.
Allow processing OCSP responses without nextUpdate .
Run non-cryptographic CLI commands in nonstrict mode.
Treat nulls the same as missing entries in dictionaries, as required by the standard.
Fix several default stamp style selection issues in CLI
The release artifacts have been published to PyPI. Documentation is available on ReadTheDocs.
The release artifacts have been published to PyPI. Documentation is available on ReadTheDocs.
The release notes for the 0.18.1 release are available on the Release History page
Release date: 2023-04-29
Remove dependency on pytz with fallback to backports.zoneinfo
Bump tzlocal version to 4.3 .
Do not rely on deprecated timezone API anymore in the tests. See PR #257 .
Release date: 2023-04-29
Remove dependency on pytz with fallback to backports.zoneinfo
Bump tzlocal version to 4.3.
Do not rely on deprecated timezone API anymore in the tests. See PR #257.
The release will be published to PyPI. Documentation is available on ReadTheDocs.
The release will be published to PyPI. Documentation is available on ReadTheDocs.
Important remark: This is the first pyHanko release to make use of GitHub Actions to publish and sign release artifacts. The CI signing workflow uses Sigstore to bind the published artifacts to pyHanko's "GitHub identity", as it were. For the time being, releases will continue to be manually signed with GPG in addition. My PGP key fingerprint is 9C41 44F3 5E74 2C88 A5D2 563C 15F4 2BEF A159 BA54, the same as for previous releases.
Should you want to validate the .sigstore signature bundles, download all the artifacts into a single folder, install sigstore from pip and run the following command:
sigstore verify github \
--cert-identity https://github.com/MatthiasValvekens/pyHanko/.github/workflows/release.yml@refs/tags/v0.18.0 \
pyHanko*.tar.gz pyHanko*.whl
Note: This release also marks pyHanko’s move to beta status. That doesn’t mean that it’s feature-complete in every respect, but it does mean that we’ve now entered a stabilisation phase in anticipation of the 1.0.0 release, so until then the focus will be on fixing bugs and clearing up issues in the documentation (in particular regarding the API contract). After the 1.0.0 release, pyHanko will simply follow SemVer.
The release notes for the 0.18.0 release are available here.
Release date: 2023-04-26
This is largely a maintenance release in the sense that it adds relatively little in the way of core features, but it nevertheless comes with some major reorganisation and work to address technical debt.
This release also marks pyHanko’s move to beta status. That doesn’t mean that it’s feature-complete in every respect, but it does mean that we’ve now entered a stabilisation phase in anticipation of the 1.0.0 release, so until then the focus will be on fixing bugs and clearing up issues in the documentation (in particular regarding the API contract). After the 1.0.0 release, pyHanko will simply follow SemVer.
Some changes have been made to the Signer class. For all practical purposes, these are mostly relevant for custom Signer implementations. Regular users should see fairly little impact.
The arguments to init have been made keyword-only.
Several attributes have been turned into read-only properties:
signing_cert
cert_registry
attribute_certs
signature_mechanism
This change was made to better reflect the way the properties were used internally, and made it easier to set expectations for the API: it doesn’t make sense to allow arbitrary modifications to these properties for all Signer implementations. The parameters to init have been extended to allow setting defaults more cleanly. Implementation-wise, the properties are backed by an underscored internal variable (e.g. _signing_cert for signing_cert ). Subclasses can of course still elect to make some of these read-only properties writable by declaring setters.
get_signature_mechanism was renamed to get_signature_mechanism_for_digest() to make it more clear that it does more than just fetch the underlying value of signature_mechanism .
Concretely, this means that init logic of the form
class MySigner ( Signer ): def init ( self , signing_cert : x509 . Certificate , cert_registry : CertificateStore , * args , ** kwargs ): self . signing_cert = signing_cert self . cert_registry = cert_registry self . signature_mechanism = signature_mechanism super () . init ()
needs to be rewritten as
class MySigner ( Signer ): def init ( self , signing_cert : x509 . Certificate , cert_registry : CertificateStore , * args , ** kwargs ): self . _signing_cert = signing_cert self . _cert_registry = cert_registry self . _signature_mechanism = signature_mechanism super () . init ()
or, alternatively, as
class MySigner ( Signer ): def init ( self , signing_cert : x509 . Certificate , cert_registry : CertificateStore , * args , ** kwargs ): super () . init ( signing_cert = signing_cert , cert_registry = cert_registry , signature_mechanism = signature_mechanism )
Other than these, there have been some miscellaneous changes.
The CLI no longer allows signing files encrypted using public-key encryption targeted towards the signer’s certificate, because that feature didn’t make much sense in key management terms, was rarely used, and hard to integrate with the new plugin system.
APIs with status_cls parameters have made certain args keyword-only for strict type checking purposes.
Move add_content_to_page to add_to_page() to deal with a (conceptual) circular dependency between modules.
CertificateStore is no longer reexported by pyhanko.sign.general .
The BEIDSigner no longer allows convenient access to the authentication certificate.
Packaging-wise, underscores have been replaced with hyphens in optional dependency groups.
In pyhanko_certvalidator , InvalidCertificateError is no longer a subclass of PathValidationError .
Finally, some internal refactoring took place as well:
The cli.py module was refactored into a new subpackage ( pyhanko.cli ) and is now also tested systematically.
CLI config classes have been refactored, some configuration was moved to the new pyhanko.config package.
Time tolerance config now passes around timedelta objects instead of second values.
The qualify() function in the difference analysis has been split into qualify() and qualify_transforming() .
Certificate and key loading was moved to a new pyhanko.keys module, but pyhanko.sign.general still reexports the relevant functions for backwards compatibility. Concretely, the affected functions are
pyhanko.keys.load_cert_from_pemder() ,
pyhanko.keys.load_certs_from_pemder() ,
pyhanko.keys.load_certs_from_pemder_data() ,
pyhanko.keys.load_private_key_from_pemder() ,
pyhanko.keys.load_private_key_from_pemder_data() .
Onboarded mypy and flag pyHanko as a typed library by adding py.typed .
Package metadata and tooling settings have now been centralised to pyproject.toml . Other configuration files like setup.py , requirements.txt and most tool-specific config have been eliminated.
The docstring-based documentation for pyhanko_certvalidator was added to the API reference.
Some non-autogenerated API reference documentation pages were consolidated to reduce the sprawl.
Heavily reworked the CI/CD pipeline. PyHanko releases are now published via GitHub Actions and signed with Sigstore. GPG signatures will continue to be provided for the time being.
Bump pyhanko-certvalidator to 0.22.0 .
Relax the upper bound on uharfbuzz for better Python 3.11 support
The AdES LTA validator now tolerates documents that don’t have a DSS (assuming that all the required information is otherwise present).
Ensure that the trusted attribute on SignatureStatus is not set if the validation path is not actually available.
Correct the typing on validation_path .
Fix several result presentation bugs in the AdES code.
Fix overeager sharing of POEManager objects in AdES code.
Correct algo policy handling in AdES-with-time validation.
Ensure that container_ref is also populated on past versions of the trailer dictionary.
The CLI now features plugins ! All current addsig subcommands have been reimplemented to use the plugin interface. Other plugins will be auto-detected through package entry points.
Refine algorithm policy handling; put in place a subclass of AlgorithmUsagePolicy specifically for CMS validation; see CMSAlgorithmUsagePolicy .
Try to remember paths when validation fails.
Make certificates from local CMS context available during path building for past certificate validation (subject to PoE checks).
Move docmdp_ok up in the hierarchy to ModificationInfo .
Release date: 2023-04-26
This is largely a maintenance release in the sense that it adds relatively little in the way of core features, but it nevertheless comes with some major reorganisation and work to address technical debt.
This release also marks pyHanko's move to beta status. That doesn't mean that it's feature-complete in every respect, but it does mean that we've now entered a stabilisation phase in anticipation of the 1.0.0 release, so until then the focus will be on fixing bugs and clearing up issues in the documentation (in particular regarding the API contract). After the 1.0.0 release, pyHanko will simply follow SemVer.
Some changes have been made to the ~pyhanko.sign.signers.pdf_cms.Signer class. For all practical purposes, these are mostly relevant for custom ~pyhanko.sign.signers.pdf_cms.Signer implementations. Regular users should see fairly little impact.
The arguments to __init__ have been made keyword-only.
Several attributes have been turned into read-only properties:
~pyhanko.sign.signers.pdf_cms.Signer.signing_cert
~pyhanko.sign.signers.pdf_cms.Signer.cert_registry
~pyhanko.sign.signers.pdf_cms.Signer.attribute_certs
~pyhanko.sign.signers.pdf_cms.Signer.signature_mechanism
This change was made to better reflect the way the properties were used internally, and made it easier to set expectations for the API: it doesn't make sense to allow arbitrary modifications to these properties for all ~pyhanko.sign.signers.pdf_cms.Signer implementations. The parameters to __init__ have been extended to allow setting defaults more cleanly. Implementation-wise, the properties are backed by an underscored internal variable (e.g. _signing_cert for signing_cert). Subclasses can of course still elect to make some of these read-only properties writable by declaring setters.
get_signature_mechanism was renamed to ~pyhanko.sign.signers.pdf_cms.Signer.get_signature_mechanism_for_digest to make it more clear that it does more than just fetch the underlying value of ~pyhanko.sign.signers.pdf_cms.Signer.signature_mechanism.
Concretely, this means that init logic of the form
class MySigner(Signer):
def __init__(
self,
signing_cert: x509.Certificate,
cert_registry: CertificateStore,
*args, **kwargs
):
self.signing_cert = signing_cert
self.cert_registry = cert_registry
self.signature_mechanism = signature_mechanism
super().__init__()
needs to be rewritten as
class MySigner(Signer):
def __init__(
self,
signing_cert: x509.Certificate,
cert_registry: CertificateStore,
*args, **kwargs
):
self._signing_cert = signing_cert
self._cert_registry = cert_registry
self._signature_mechanism = signature_mechanism
super().__init__()
or, alternatively, as
class MySigner(Signer):
def __init__(
self,
signing_cert: x509.Certificate,
cert_registry: CertificateStore,
*args, **kwargs
):
super().__init__(
signing_cert=signing_cert,
cert_registry=cert_registry,
signature_mechanism=signature_mechanism
)
Other than these, there have been some miscellaneous changes.
The CLI no longer allows signing files encrypted using public-key encryption targeted towards the signer's certificate, because that feature didn't make much sense in key management terms, was rarely used, and hard to integrate with the new plugin system.
APIs with status_cls parameters have made certain args keyword-only for strict type checking purposes.
Move add_content_to_page to ~pyhanko.pdf_utils.content.PdfContent.add_to_page to deal with a (conceptual) circular dependency between modules.
~pyhanko_certvalidator.registry.CertificateStore is no longer reexported by pyhanko.sign.general.
The BEIDSigner no longer allows convenient access to the authentication certificate.
Packaging-wise, underscores have been replaced with hyphens in optional dependency groups.
In pyhanko_certvalidator, ~pyhanko_certvalidator.errors.InvalidCertificateError is no longer a subclass of ~pyhanko_certvalidator.errors.PathValidationError.
Finally, some internal refactoring took place as well:
The cli.py module was refactored into a new subpackage (pyhanko.cli) and is now also tested systematically.
CLI config classes have been refactored, some configuration was moved to the new pyhanko.config package.
Time tolerance config now passes around timedelta objects instead of second values.
The ~pyhanko.sign.diff_analysis.commons.qualify function in the difference analysis has been split into ~pyhanko.sign.diff_analysis.commons.qualify and ~pyhanko.sign.diff_analysis.commons.qualify_transforming.
Certificate and key loading was moved to a new pyhanko.keys module, but pyhanko.sign.general still reexports the relevant functions for backwards compatibility. Concretely, the affected functions are
pyhanko.keys.load_cert_from_pemder,
pyhanko.keys.load_certs_from_pemder,
pyhanko.keys.load_certs_from_pemder_data,
pyhanko.keys.load_private_key_from_pemder,
pyhanko.keys.load_private_key_from_pemder_data.
Onboarded mypy and flag pyHanko as a typed library by adding py.typed.
Package metadata and tooling settings have now been centralised to pyproject.toml. Other configuration files like setup.py, requirements.txt and most tool-specific config have been eliminated.
The docstring-based documentation for pyhanko_certvalidator was added to the API reference.
Some non-autogenerated API reference documentation pages were consolidated to reduce the sprawl.
Heavily reworked the CI/CD pipeline. PyHanko releases are now published via GitHub Actions and signed with Sigstore. GPG signatures will continue to be provided for the time being.
Bump pyhanko-certvalidator to 0.22.0.
Relax the upper bound on uharfbuzz for better Python 3.11 support
The AdES LTA validator now tolerates documents that don't have a DSS (assuming that all the required information is otherwise present).
Ensure that the ~pyhanko.sign.validation.status.SignatureStatus.trusted attribute on ~pyhanko.sign.validation.status.SignatureStatus is not set if the validation path is not actually available.
Correct the typing on ~pyhanko.sign.validation.status.SignatureStatus.validation_path.
Fix several result presentation bugs in the AdES code.
Fix overeager sharing of ~pyhanko_certvalidator.ltv.poe.POEManager objects in AdES code.
Correct algo policy handling in AdES-with-time validation.
Ensure that container_ref is also populated on past versions of the trailer dictionary.
The CLI now features plugins! All current addsig subcommands have been reimplemented to use the plugin interface. Other plugins will be auto-detected through package entry points.
Refine algorithm policy handling; put in place a subclass of ~pyhanko_certvalidator.policy_decl.AlgorithmUsagePolicy specifically for CMS validation; see ~pyhanko.sign.validation.utils.CMSAlgorithmUsagePolicy.
Try to remember paths when validation fails.
Make certificates from local CMS context available during path building for past certificate validation (subject to PoE checks).
Move ~pyhanko.sign.validation.status.ModificationInfo.docmdp_ok up in the hierarchy to ~pyhanko.sign.validation.status.ModificationInfo.
- Fix mistaken assumption when a certificate’s MIME type is announced as application/x-x509-ca-cert .
Release date: 2021-11-13
Fix mistaken assumption when a certificate’s MIME type is announced as application/x-x509-ca-cert .
Update aiohttp to 3.8.0
Release date: 2021-11-13
Fix mistaken assumption when a certificate's MIME type is announced as application/x-x509-ca-cert.
Update aiohttp to 3.8.0
- Fix a deadlocking bug caused by improper exception handling in the fetcher code.
Release date: 2021-10-28
Fix a deadlocking bug caused by improper exception handling in the fetcher code.
Exceptions are now communicated to fetch jobs waiting for results.
Release date: 2021-10-28
Fix a deadlocking bug caused by improper exception handling in the fetcher code.
Exceptions are now communicated to fetch jobs waiting for results.
The release has been uploaded to PyPI. Documentation is available on ReadTheDocs.
The release has been uploaded to PyPI. Documentation is available on ReadTheDocs.
Note: The public API is not completely stable yet, so future releases may still include API changes. This is particularly likely for the validation code and the pdf_utils package; please refer to the documentation for further details.
The release notes for the 0.17.2 release are available here.
Release date: 2023-03-10
This is a follow-up on yesterday’s bugfix release, addressing a number of similar issues.
Address another potential infinite loop in the comment processing logic.
Fix some (rather esoteric) correctness issues w.r.t. PDF whitespace.
The release has been uploaded to PyPI. Documentation is available on ReadTheDocs.
The release has been uploaded to PyPI. Documentation is available on ReadTheDocs.
Note: The public API is not completely stable yet, so future releases may still include API changes. This is particularly likely for the validation code and the pdf_utils package; please refer to the documentation for further details.
The release notes for the 0.17.1 release are available here.
Release date: 2023-03-09
This is a maintenance release without significant functionality changes. It contains a bugfix, addresses some documentation issues and applies the Black formatter to the codebase.
Address a potential infinite loop in the PDF parsing logic. See PR #237 .
The release has been uploaded to PyPI. Documentation is available on ReadTheDocs.
The release has been uploaded to PyPI. Documentation is available on ReadTheDocs.
Note: The public API is not completely stable yet, so future releases may still include API changes. This is particularly likely for the validation code and the pdf_utils package; please refer to the documentation for further details.
The release notes for the 0.17.0 release are available here.
Release date: 2023-01-31
This is a bit of an odd release. It comes with relatively few functional changes or enhancements to existing features, but it has nevertheless been in the works for quite a long time.
In early 2022, I decided that the time was right to equip pyHanko with its own AdES validation engine, implementing the machinery specified by ETSI EN 319 102-1. I knew ahead of time that this would not be an easy task:
PyHanko’s own validation code was put together in a fairly ad-hoc manner starting from the provisions in the CMS specification, so some refactoring would be necessary.
pyhanko-certvalidator also was never designed to be anything more than an RFC 5280 validation engine, and retrofitting the fine-tuning required by the AdES spec definitely wasn’t easy.
Initially, I estimated that this effort would take a few months tops. Yet here we are, approximately one year down the road: pyhanko.sign.validation.ades .
Truth be told, the implementation isn’t yet ready for prime time, but it is in a state where it’s at least useful for experimentation purposes, and can be iterated on. Also, given the volume of subtle changes and far-reaching refactoring in the internals of both the pyhanko and pyhanko-certvalidator packages, continually rebasing the feature/ades-validation feature branch turned into a chore quite quickly.
So, if you’re keen to start playing around with AdES validation: please do so, and let me know what you think. If standards-based validation is not something you care about, feel free to disregard everything I wrote above, it almost certainly won’t affect any of your code.
My plan is to incrementally build upon and polish the code in pyhanko.sign.validation.ades , and eventually deprecate the current ad-hoc LTV validation logic in pyhanko.sign.validation.ltv.async_validate_pdf_ltv_signature() . That’s still a ways off from now, though.
pyhanko-certvalidator updated to 0.20.0
There are various changes in the validation internals that are not backwards compatible, but all of those concern internal APIs.
There are some noteworthy changes to the pyhanko-certvalidator API. Those are documented in the change log . Most of these do not affect basic usage.
Experimental AdES validation engine pyhanko.sign.validation.ades .
In the status API, make a more meaningful distinction between valid and intact , and document that distinction.
The release has been uploaded to PyPI. Documentation is available on ReadTheDocs.
The release has been uploaded to PyPI. Documentation is available on ReadTheDocs.
Note: The public API is not completely stable yet, so future releases may still include API changes. This is particularly likely for the validation code and the pdf_utils package; please refer to the documentation for further details.
The release notes for the 0.16.0 release are available here.
Release date: 2022-12-21
pyhanko-certvalidator updated to 0.19.8
This release includes breaking changes to the difference analysis engine. Unless you’re implementing your own difference analysis policies, this change should break your API usage.
Add support for Prop_Build metadata in signatures. See PR #192
Improvements to the difference analysis engine that allow more nuance to be expressed in the rule system.
Tolerate an indirect Extensions and MarkInfo dictionary in difference analysis. See PR #177 .
Gracefully handle unreadable/undecodable producer strings.
- Short-circuit anyPolicy when reporting policies
Release date: 2021-07-25
Short-circuit anyPolicy when reporting policies
Export PKIXValidationParams
Limit CRL client to HTTP-based URLs
Release date: 2021-07-25
Short-circuit anyPolicy when reporting policies
Export PKIXValidationParams
Limit CRL client to HTTP-based URLs
- Properly handle missing Content-Type header in server response when fetching CA certificates referenced in a CRL.
Release date: 2021-05-22
Properly handle missing Content-Type header in server response when fetching CA certificates referenced in a CRL.
Release date: 2021-05-22
Properly handle missing Content-Type header in server response when fetching CA certificates referenced in a CRL.
The release has been uploaded to PyPI. Documentation is available on ReadTheDocs.
The release has been uploaded to PyPI. Documentation is available on ReadTheDocs.
Note: The public API is not completely stable yet, so future releases may still include API changes. This is particularly likely for the validation code and the pdf_utils package; please refer to the documentation for further details.
The release notes for the 0.15.1 release are available here.
Release date: 2022-10-27
This release adds Python 3.11 to the list of supported Python versions.
pyhanko-certvalidator updated to 0.19.6
certomancer updated to 0.9.1
Be more tolerant towards deviations from DER restrictions in signed attributes when validating signatures.
The release has been uploaded to PyPI. Documentation is available on ReadTheDocs.
The release has been uploaded to PyPI. Documentation is available on ReadTheDocs.
Note: The public API is not completely stable yet, so future releases may still include API changes. This is particularly likely for the validation code and the pdf_utils package; please refer to the documentation for further details.
The release notes for the 0.15.0 release are available here.
Release date: 2022-10-11
Other than a few bug fixes, the highlight of this release is the addition of support for two very recently published PDF extension standards, ISO/TS 32001 and ISO/TS 32002.
Fix metadata handling in encrypted documents see issue #160 .
Make sure XMP stream dictionaries contain the required typing entries.
Respect visible_sig_settings on field autocreation.
Fix a division by zero corner case in the stamp layout code; see issue #170 .
Add support for the new PDF extensions defined by ISO/TS 32001 and ISO/TS 32002; see PR #169 .
SHA-3 support
EdDSA support for both the PKCS#11 signer and the in-memory signer
Auto-register developer extensions in the file
Make it easier to extract keys from bytes objects.
Add support for validating EdDSA signatures (as defined in ISO/TS 32002)
- No code changes, rerelease because distribution package was polluted due to improper build cache cleanup.
Release date: 2021-04-03
No code changes, rerelease because distribution package was polluted due to improper build cache cleanup.
Release date: 2021-04-03
No code changes, rerelease because distribution package was polluted due to improper build cache cleanup.
The release has been uploaded to PyPI. Documentation is available on ReadTheDocs.
The release has been uploaded to PyPI. Documentation is available on ReadTheDocs.
Note: The public API is not completely stable yet, so future releases may still include API changes. This is particularly likely for the validation code and the pdf_utils package; please refer to the documentation for further details.
The release notes for the 0.14.0 release are available here.
Release date: 2022-09-17
This release contains a mixture of minor and major changes. Of particular note is the addition of automated metadata management support, including XMP metadata. This change affects almost every PDF write operation in the background. While pyHanko has very good test coverage, some instability and regressions may ensue. Bug reports are obviously welcome.
The breaking changes in this release are all relatively minor. Chances are that your code isn’t affected at all, other than perhaps by the change to PreparedByteRangeDigest .
md_algorithm attribute removed from PreparedByteRangeDigest since it wasn’t necessary for further processing.
Low-level change in raw_get for PDF container object types ( ArrayObject and DictionaryObject ): the decrypt parameter is no longer a boolean, but a tri-state enum value of type EncryptedObjAccess .
Developer extension management API moved into pyhanko.pdf_utils.extensions .
get_courier() convenience function moved into pyhanko.pdf_utils.font.basic and now takes a mandatory writer argument.
The token_label attribute was removed from PKCS11SignatureConfig , but will still be parsed (with a deprecation warning).
The prompt_pin attribute in PKCS11SignatureConfig was changed from a bool to an enum. See PKCS11PinEntryMode .
pytest-aiohttp updated to 1.0.4
certomancer updated to 0.9.0
certomancer-csc-dummy updated to 0.2.1
Relax bounds on uharfbuzz to allow everything up to the current version (i.e. 0.30.0 ) as well.
New optional dependency group xmp , which for now only contains defusedxml
Allow certificates with no CN in the certificate subject.
The extension dictionary handling logic can now deal with encrypted documents without actually decrypting the document contents.
Fix processing error when passing empty strings to uharfbuzz ; see issue #132 .
Use proper PDF text string serialisation routine in simple font handler, to ensure everything is escaped correctly.
Ensure that output_version is set to at least the input version in incrementally updated files.
Drop the requirement for signing_cert to be set from the start of the signing process in an interrupted signing workflow. This has come up on several occasions in the past, since it’s necessary in remote signing scenarios where the certificate is generated or provided on-demand when submitting the document digest to the signing service. See pull #141 for details.
Add convenience API to set the /TU entry on a signature field; see readable_field_name .
Allow greater control over the initialisation of document timestamp fields.
New class hierarchy for (un)signed attribute provisioning; see SignedAttributeProviderSpec and UnsignedAttributeProviderSpec .
Allow greater control over annotation flags for visible signatures. This is implemented using VisibleSigSettings . See discussion #150 .
Factor out and improve PKCS#11 token finding; see TokenCriteria and issue #149 .
Factor out and improve PKCS#11 mechanism selection, allowing more raw modes.
Change pin entry settings for PKCS#11 to be more granular, in order to also allow PROTECTED_AUTH ; see issue #133 .
Allow the PKCS#11 PIN to be sourced from an environment variable when pyHanko is invoked through the CLI and no PIN is provided in the configuration. PyHanko will now first check the PYHANKO_PKCS11_PIN variable before prompting for a PIN. This also works when prompting for PIN entry is disabled altogether.
Note
The PKCS#11 code is now also tested in CI, using SoftHSMv2 .
Allow validation time overrides in the CLI. Passing in the special value claimed tells pyHanko to take the stated signing time in the file at face value. See issue #130 .
Also return permissions on owner access to allow for easier inspection.
Better version enforcement for security handlers.
Allow metrics to be specified for simple fonts.
Provide metrics for default Courier font.
Experimental option that allows graphics to be embedded in the central area of the QR code; see qr_inner_content .
Basic XMP metadata support with optional xmp dependency group.
Automated metadata management (document info dictionary, XMP metadata).
Refactor some low-level digesting and CMS validation code.
Make the CLI print a warning when the key passphrase is left empty.
Tweak configuration management utilities to better cope with fallback logic for deprecated configuration parameters.
Move all cross-reference writing logic into pyhanko.pdf_utils.xref .
Improve error classes and error reporting in the CLI so that errors in non-verbose mode still provide a little more info.
Release date: 2022-09-17
This release contains a mixture of minor and major changes. Of particular note is the addition of automated metadata management support, including XMP metadata. This change affects almost every PDF write operation in the background. While pyHanko has very good test coverage, some instability and regressions may ensue. Bug reports are obviously welcome.
The breaking changes in this release are all relatively minor. Chances are that your code isn't affected at all, other than perhaps by the change to ~pyhanko.sign.signers.pdf_byterange.PreparedByteRangeDigest.
md_algorithm attribute removed from ~pyhanko.sign.signers.pdf_byterange.PreparedByteRangeDigest since it wasn't necessary for further processing.
Low-level change in raw_get for PDF container object types (~pyhanko.pdf_utils.generic.ArrayObject and ~pyhanko.pdf_utils.generic.DictionaryObject): the decrypt parameter is no longer a boolean, but a tri-state enum value of type ~pyhanko.pdf_utils.generic.EncryptedObjAccess.
Developer extension management API moved into pyhanko.pdf_utils.extensions.
~pyhanko.pdf_utils.font.basic.get_courier convenience function moved into pyhanko.pdf_utils.font.basic and now takes a mandatory writer argument.
The token_label attribute was removed from ~pyhanko.cli.config.PKCS11SignatureConfig, but will still be parsed (with a deprecation warning).
The ~pyhanko.cli.config.PKCS11SignatureConfig.prompt_pin attribute in ~pyhanko.cli.config.PKCS11SignatureConfig was changed from a bool to an enum. See ~pyhanko.cli.config.PKCS11PinEntryMode.
pytest-aiohttp updated to 1.0.4
certomancer updated to 0.9.0
certomancer-csc-dummy updated to 0.2.1
Relax bounds on uharfbuzz to allow everything up to the current version (i.e. 0.30.0) as well.
New optional dependency group xmp, which for now only contains defusedxml
Allow certificates with no CN in the certificate subject.
The extension dictionary handling logic can now deal with encrypted documents without actually decrypting the document contents.
Fix processing error when passing empty strings to uharfbuzz; see issue #132.
Use proper PDF text string serialisation routine in simple font handler, to ensure everything is escaped correctly.
Ensure that output_version is set to at least the input version in incrementally updated files.
Drop the requirement for ~pyhanko.sign.signers.pdf_cms.Signer.signing_cert to be set from the start of the signing process in an interrupted signing workflow. This has come up on several occasions in the past, since it's necessary in remote signing scenarios where the certificate is generated or provided on-demand when submitting the document digest to the signing service. See pull #141 for details.
Add convenience API to set the /TU entry on a signature field; see ~pyhanko.sign.fields.SigFieldSpec.readable_field_name.
Allow greater control over the initialisation of document timestamp fields.
New class hierarchy for (un)signed attribute provisioning; see ~pyhanko.sign.attributes.SignedAttributeProviderSpec and ~pyhanko.sign.attributes.UnsignedAttributeProviderSpec.
Allow greater control over annotation flags for visible signatures. This is implemented using ~pyhanko.sign.fields.VisibleSigSettings. See discussion #150.
Factor out and improve PKCS#11 token finding; see ~pyhanko.cli.config.TokenCriteria and issue #149.
Factor out and improve PKCS#11 mechanism selection, allowing more raw modes.
Change pin entry settings for PKCS#11 to be more granular, in order to also allow PROTECTED_AUTH; see issue #133.
Allow the PKCS#11 PIN to be sourced from an environment variable when pyHanko is invoked through the CLI and no PIN is provided in the configuration. PyHanko will now first check the PYHANKO_PKCS11_PIN variable before prompting for a PIN. This also works when prompting for PIN entry is disabled altogether.
Note
The PKCS#11 code is now also tested in CI, using SoftHSMv2.
Allow validation time overrides in the CLI. Passing in the special value claimed tells pyHanko to take the stated signing time in the file at face value. See issue #130.
Also return permissions on owner access to allow for easier inspection.
Better version enforcement for security handlers.
Allow metrics to be specified for simple fonts.
Provide metrics for default Courier font.
Experimental option that allows graphics to be embedded in the central area of the QR code; see ~pyhanko.stamp.QRStampStyle.qr_inner_content.
Basic XMP metadata support with optional xmp dependency group.
Automated metadata management (document info dictionary, XMP metadata).
Refactor some low-level digesting and CMS validation code.
Make the CLI print a warning when the key passphrase is left empty.
Tweak configuration management utilities to better cope with fallback logic for deprecated configuration parameters.
Move all cross-reference writing logic into pyhanko.pdf_utils.xref.
Improve error classes and error reporting in the CLI so that errors in non-verbose mode still provide a little more info.
The release has been uploaded to PyPI. Documentation is available on ReadTheDocs.
The release has been uploaded to PyPI. Documentation is available on ReadTheDocs.
Note: The public API is not completely stable yet, so future releases may still include API changes. This is particularly likely for the validation code and the pdf_utils package; please refer to the documentation for further details.
The release notes for the 0.13.1 release are available here.
Release date: 2022-05-01
This is a patch release to update fontTools and uharfbuzz to address a conflict between the latest fontTools and older uharfbuzz versions.
fontTools updated to 4.33.3
uharfbuzz updated to 0.25.0
The release has been uploaded to PyPI. Documentation is available on ReadTheDocs.
The release has been uploaded to PyPI. Documentation is available on ReadTheDocs.
Note: The public API is not completely stable yet, so future releases may still include API changes. This is particularly likely for the validation code and the pdf_utils package; please refer to the documentation for further details.
The release notes for the 0.13.0 release are available here.
Release date: 2022-04-25
Like the previous two releases, this is largely a maintenance release.
asn1crypto updated to 1.5.1
pyhanko-certvalidator updated to 0.19.5
certomancer updated to 0.8.2
Depend on certomancer-csc-dummy for tests; get rid of python-pae test dependency.
Various parsing robustness improvements.
Be consistent with security handler version bounds.
Improve coverage of encryption code.
Ensure owner password gets prioritised in the legacy security handler.
Replaced some ValueError usages with PdfError
Improvements to error handling in strict mode.
Make CLI stack traces less noisy by default.
Refactor internal crypt module into package.
Add support for serialising credentials.
Cleaner credential inheritance for incremental writers.
Allow post-signing actions on encrypted files with serialised credentials.
Improve --use-pades-lta ergonomics in CLI.
Add --no-pass parameter to pemder CLI.
Preparatory scaffolding for AdES status reporting.
Provide some tolerance against malformed ACs.
Increase robustness against invalid DNs.
The release has been uploaded to PyPI. Documentation is available on ReadTheDocs.
The release has been uploaded to PyPI. Documentation is available on ReadTheDocs.
Note: The public API is not completely stable yet, so future releases may still include API changes. This is particularly likely for the validation code and the pdf_utils package; please refer to the documentation for further details.
The release notes for the 0.12.1 release are available here.
Release date: 2022-02-26
uharfbuzz updated to 0.19.0
pyhanko-certvalidator updated to 0.19.4
certomancer updated to 0.8.1
Fix typing issue in DSS reading logic (see issue #81 )
Release date: 2022-02-26
uharfbuzz updated to 0.19.0
pyhanko-certvalidator updated to 0.19.4
certomancer updated to 0.8.1
Fix typing issue in DSS reading logic (see issue #81)
The release has been uploaded to PyPI. Documentation is available on ReadTheDocs.
The release has been uploaded to PyPI. Documentation is available on ReadTheDocs.
Note: The public API is not completely stable yet, so future releases may still include API changes. This is particularly likely for the validation code and the pdf_utils package; please refer to the documentation for further details.
The release notes for the 0.12.0 release are available here.
Release date: 2022-01-26
This is largely a maintenance release, and contains no new high-level features or public API changes. As such, upgrading is strongly recommended.
The most significant change is the (rather minimalistic) support for hybrid reference files. Since working with hybrid reference files means dealing with potential ambiguity (which is dangerous when dealing with signatures), creation and validation of signatures in hybrid reference documents is only enabled in nonstrict mode. Hybrid reference files are relatively rare these days, but the internals need to be able to cope with them either way, in order to be able to update such files safely.
Significant refactor of cross-reference parsing internals. This doesn’t affect any public API entrypoints, but read the reference documentation for pyhanko.pdf_utils.xref if you happen to have code that directly relies on that internal logic.
Minimal support for hybrid reference files.
Add strict flag to IncrementalPdfFileWriter .
Expose --no-strict-syntax CLI flag in the addsig subcommand.
Ensure that signature appearance bounding boxes are rounded to a reasonable precision. Failure to do so caused issues with some viewers.
To be consistent with the purpose of the strictness flag, non-essential xref consistency checking is now only enabled when running in strict mode (which is the default).
The hybrid reference support indirectly fixes some potential silent file corruption issues that could arise when working on particularly ill-behaved hybrid reference files.
Your coding agent can read these notes before it upgrades. Set up the MCP server →