pyhanko.sign.signers module

class pyhanko.sign.signers.PdfSignatureMetadata(field_name: Optional[str] = None, md_algorithm: Optional[str] = None, location: Optional[str] = None, reason: Optional[str] = None, name: Optional[str] = None, certify: bool = False, subfilter: Optional[pyhanko.sign.fields.SigSeedSubFilter] = None, embed_validation_info: bool = False, use_pades_lta: bool = False, timestamp_field_name: Optional[str] = None, validation_context: Optional[certvalidator.context.ValidationContext] = None, docmdp_permissions: pyhanko.sign.fields.MDPPerm = <MDPPerm.FILL_FORMS: 2>)

Bases: object

Specification for a PDF signature.

field_name: str = None

The name of the form field to contain the signature. If there is only one available signature field, the name may be inferred.

md_algorithm: str = None

The name of the digest algorithm to use. It should be supported by hashlib.

If None, this will ordinarily default to the value of DEFAULT_MD, unless a seed value dictionary and/or a prior certification signature happen to be available.

location: str = None

Location of signing.

reason: str = None

Reason for signing (textual).

name: str = None

Name of the signer. This value is usually not necessary to set, since it should appear on the signer’s certificate, but there are cases where it might be useful to specify it here (e.g. in situations where signing is delegated to a trusted third party).

certify: bool = False

Sign with an author (certification) signature, as opposed to an approval signature. A document can contain at most one such signature, and it must be the first one.

subfilter: pyhanko.sign.fields.SigSeedSubFilter = None

Signature subfilter to use.

This should be one of ADOBE_PKCS7_DETACHED or PADES. If not specified, the value may be inferred from the signature field’s seed value dictionary. Failing that, ADOBE_PKCS7_DETACHED is used as the default value.

embed_validation_info: bool = False

Flag indicating whether validation info (OCSP responses and/or CRLs) should be embedded or not. This is necessary to be able to validate signatures long after they have been made. This flag requires validation_context to be set.

The precise manner in which the validation info is embedded depends on the (effective) value of subfilter:

  • With ADOBE_PKCS7_DETACHED, the validation information will be embedded inside the CMS object containing the signature.

  • With PADES, the validation information will be embedded into the document security store (DSS).

use_pades_lta: bool = False

If True, the signer will append an additional document timestamp after writing the signature’s validation information to the document security store (DSS). This flag is only meaningful if subfilter is PADES.

The PAdES B-LTA profile solves the long-term validation problem by adding a timestamp chain to the document after the regular signatures, which is updated with new timestamps at regular intervals. This provides an audit trail that ensures the long-term integrity of the validation information in the DSS, since OCSP responses and CRLs also have a finite lifetime.

See also PdfTimeStamper.update_archival_timestamp_chain().

timestamp_field_name: str = None

Name of the timestamp field created when use_pades_lta is True. If not specified, a unique name will be generated using uuid.

validation_context: certvalidator.context.ValidationContext = None

The validation context to use when validating signatures. If provided, the signer’s certificate and any timestamp certificates will be validated before signing.

This parameter is mandatory when embed_validation_info is True.

docmdp_permissions: pyhanko.sign.fields.MDPPerm = 2

Indicates the document modification policy that will be in force after this signature is created.

Warning

For non-certification signatures, this is only explicitly allowed since PDF 2.0 (ISO 32000-2), so older software may not respect this setting on approval signatures.

class pyhanko.sign.signers.Signer

Bases: object

Abstract signer object that is agnostic as to where the cryptographic operations actually happen.

As of now, pyHanko provides two implementations:

  • SimpleSigner implements the easy case where all the key material can be loaded into memory.

  • PKCS11Signer implements a signer that is capable of interfacing with a PKCS11 device (see also BEIDSigner).

signing_cert: asn1crypto.x509.Certificate

The certificate that will be used to create the signature.

cert_registry: pyhanko.sign.general.CertificateStore

Collection of certificates associated with this signer. Note that this is simply a bookkeeping tool; in particular it doesn’t care about trust.

signature_mechanism: asn1crypto.algos.SignedDigestAlgorithm

The (cryptographic) signature mechanism to use.

sign_raw(data: bytes, digest_algorithm: str, dry_run=False) → bytes

Compute the raw cryptographic signature of the data provided, hashed using the digest algorithm provided.

Parameters
  • data – Data to sign.

  • digest_algorithm

    Digest algorithm to use.

    Warning

    If signature_mechanism also specifies a digest, they should match.

  • dry_run – Do not actually create a signature, but merely output placeholder bytes that would suffice to contain an actual signature.

Returns

Signature bytes.

property subject_name
Returns

The subject’s common name as a string, extracted from signing_cert.

static format_revinfo(ocsp_responses: Optional[list] = None, crls: Optional[list] = None)

Format Adobe-style revocation information for inclusion into a CMS object.

Parameters
  • ocsp_responses – A list of OCSP responses to include.

  • crls – A list of CRLs to include.

Returns

A CMS attribute containing the relevant data.

signed_attrs(data_digest: bytes, timestamp: Optional[datetime.datetime] = None, revocation_info=None, use_pades=False)

Format the signed attributes for a CMS signature.

Parameters
  • data_digest – Raw digest of the data to be signed.

  • timestamp – Current timestamp (ignored when use_pades is True).

  • revocation_info – Revocation information to embed; this should be the output of a call to Signer.format_revinfo() (ignored when use_pades is True).

  • use_pades – Respect PAdES requirements.

Returns

An asn1crypto.cms.CMSAttributes object.

signer_info(digest_algorithm: str, signed_attrs, signature)

Format the SignerInfo entry for a CMS signature.

Parameters
  • digest_algorithm – Digest algorithm to use.

  • signed_attrs – Signed attributes (see signed_attrs()).

  • signature – The raw signature to embed (see sign_raw()).

Returns

An asn1crypto.cms.SignerInfo object.

sign(data_digest: bytes, digest_algorithm: str, timestamp: Optional[datetime.datetime] = None, dry_run=False, revocation_info=None, use_pades=False, timestamper=None) → asn1crypto.cms.ContentInfo

Produce a detached CMS signature from a raw data digest.

Parameters
  • data_digest – Digest of the actual content being signed.

  • digest_algorithm – Digest algorithm to use. This should be the same digest method as the one used to hash the (external) content.

  • timestamp – Current timestamp (ignored when use_pades is True).

  • dry_run

    If True, the actual signing step will be replaced with a placeholder.

    In a PDF signing context, this is necessary to estimate the size of the signature container before computing the actual digest of the document.

  • revocation_info – Revocation information to embed; this should be the output of a call to Signer.format_revinfo() (ignored when use_pades is True).

  • use_pades – Respect PAdES requirements.

  • timestamper

    TimeStamper used to obtain a trusted timestamp token that can be embedded into the signature container.

    Note

    If dry_run is true, the timestamper’s dummy_response() method will be called to obtain a placeholder token. Note that with a standard HTTPTimeStamper, this might still hit the timestamping server (in order to produce a realistic size estimate), but the dummy response will be cached.

Returns

An ContentInfo object.

class pyhanko.sign.signers.SimpleSigner(signing_cert: asn1crypto.x509.Certificate, signing_key: asn1crypto.keys.PrivateKeyInfo, cert_registry: pyhanko.sign.general.CertificateStore, signature_mechanism: Optional[asn1crypto.algos.SignedDigestAlgorithm] = None)

Bases: pyhanko.sign.signers.Signer

Simple signer implementation where the key material is available in local memory.

signing_key: asn1crypto.keys.PrivateKeyInfo

Private key associated with the certificate in signing_cert.

sign_raw(data: bytes, digest_algorithm: str, dry_run=False) → bytes

Compute the raw cryptographic signature of the data provided, hashed using the digest algorithm provided.

Parameters
  • data – Data to sign.

  • digest_algorithm

    Digest algorithm to use.

    Warning

    If signature_mechanism also specifies a digest, they should match.

  • dry_run – Do not actually create a signature, but merely output placeholder bytes that would suffice to contain an actual signature.

Returns

Signature bytes.

classmethod load_pkcs12(pfx_file, ca_chain_files=None, passphrase=None, signature_mechanism=None)

Load certificates and key material from a PCKS#12 archive (usually .pfx or .p12 files).

Parameters
  • pfx_file – Path to the PKCS#12 archive.

  • ca_chain_files – Path to (PEM/DER) files containing other relevant certificates not included in the PKCS#12 file.

  • passphrase – Passphrase to decrypt the PKCS#12 archive, if required.

  • signature_mechanism – Override the signature mechanism to use.

Returns

A SimpleSigner object initialised with key material loaded from the PKCS#12 file provided.

classmethod load(key_file, cert_file, ca_chain_files=None, key_passphrase=None, other_certs=None, signature_mechanism=None)

Load certificates and key material from PEM/DER files.

Parameters
  • key_file – File containing the signer’s private key.

  • cert_file – File containing the signer’s certificate.

  • ca_chain_files – File containing other relevant certificates.

  • key_passphrase – Passphrase to decrypt the private key (if required).

  • other_certs – Other relevant certificates, specified as a list of asn1crypto.x509.Certificate objects.

  • signature_mechanism – Override the signature mechanism to use.

Returns

A SimpleSigner object initialised with key material loaded from the files provided.

class pyhanko.sign.signers.PdfTimeStamper(timestamper: pyhanko.sign.timestamps.TimeStamper)

Bases: object

Class to encapsulate the process of appending document timestamps to PDF files.

generate_timestamp_field_name() → str

Generate a unique name for a document timestamp field using uuid.

Returns

The field name, as a (Python) string.

timestamp_pdf(pdf_out: pyhanko.pdf_utils.incremental_writer.IncrementalPdfFileWriter, md_algorithm, validation_context, bytes_reserved=None, validation_paths=None, in_place=False, timestamper: Optional[pyhanko.sign.timestamps.TimeStamper] = None)

Timestamp the contents of pdf_out. Note that pdf_out should not be written to after this operation.

Parameters
  • pdf_out – An IncrementalPdfFileWriter.

  • md_algorithm – The hash algorithm to use when computing message digests.

  • validation_context – The certvalidator.ValidationContext against which the TSA response should be validated. This validation context will also be used to update the DSS.

  • bytes_reserved – Bytes to reserve for the CMS object in the PDF file. If not specified, make an estimate based on a dummy signature.

  • validation_paths – If the validation path(s) for the TSA’s certificate are already known, you can pass them using this parameter to avoid having to run the validation logic again.

  • in_place – Sign the input in-place. If False, write output to a BytesIO object.

  • timestamper – Override the default TimeStamper associated with this PdfTimeStamper.

Returns

The output stream containing the signed output.

update_archival_timestamp_chain(reader: pyhanko.pdf_utils.reader.PdfFileReader, validation_context, in_place=True)

Validate the last timestamp in the timestamp chain on a PDF file, and write an updated version to an output stream.

Parameters
  • reader – A PdfReader encapsulating the input file.

  • validation_contextcertvalidator.ValidationContext object to validate the last timestamp.

  • in_place – Sign the input in-place. If False, write output to a BytesIO object.

Returns

The output stream containing the signed output.

class pyhanko.sign.signers.PdfSigner(signature_meta: pyhanko.sign.signers.PdfSignatureMetadata, signer: pyhanko.sign.signers.Signer, *, timestamper: Optional[pyhanko.sign.timestamps.TimeStamper] = None, stamp_style: Optional[pyhanko.stamp.TextStampStyle] = None, new_field_spec: Optional[pyhanko.sign.fields.SigFieldSpec] = None)

Bases: pyhanko.sign.signers.PdfTimeStamper

Class to handle PDF signatures in general.

Parameters
  • signature_meta – The specification of the signature to add.

  • signerSigner object to use to produce the signature object.

  • timestamperTimeStamper object to use to produce any time stamp tokens that might be required.

  • stamp_style – Stamp style specification to determine the visible style of the signature, typically an object of type TextStampStyle or QRStampStyle. Defaults to DEFAULT_SIGNING_STAMP_STYLE.

  • new_field_spec – If a new field is to be created, this parameter allows the caller to specify the field’s properties in the form of a SigFieldSpec. This parameter is only meaningful if existing_fields_only is False.

generate_timestamp_field_name() → str

Look up the timestamp field name in the PdfSignatureMetadata object associated with this PdfSigner. If not specified, generate a unique field name using uuid.

Returns

The field name, as a (Python) string.

sign_pdf(pdf_out: pyhanko.pdf_utils.incremental_writer.IncrementalPdfFileWriter, existing_fields_only=False, bytes_reserved=None, in_place=False, appearance_text_params=None)

Sign a PDF file using the provided output writer.

Parameters
  • pdf_out – An IncrementalPdfFileWriter containing the data to sign.

  • existing_fields_only – If True, never create a new empty signature field to contain the signature. If False, a new field may be created if no field matching field_name exists.

  • bytes_reserved – Bytes to reserve for the CMS object in the PDF file. If not specified, make an estimate based on a dummy signature.

  • in_place – Sign the input in-place. If False, write output to a BytesIO object.

  • appearance_text_params – Dictionary with text parameters that will be passed to the signature appearance constructor (if applicable).

Returns

The output stream containing the signed data.

pyhanko.sign.signers.sign_pdf(pdf_out: pyhanko.pdf_utils.incremental_writer.IncrementalPdfFileWriter, signature_meta: pyhanko.sign.signers.PdfSignatureMetadata, signer: pyhanko.sign.signers.Signer, timestamper: Optional[pyhanko.sign.timestamps.TimeStamper] = None, new_field_spec: Optional[pyhanko.sign.fields.SigFieldSpec] = None, existing_fields_only=False, bytes_reserved=None, in_place=False)

Thin convenience wrapper around PdfSigner.sign_pdf().

Parameters
  • pdf_out – An IncrementalPdfFileWriter.

  • bytes_reserved – Bytes to reserve for the CMS object in the PDF file. If not specified, make an estimate based on a dummy signature.

  • signature_meta – The specification of the signature to add.

  • signerSigner object to use to produce the signature object.

  • timestamperTimeStamper object to use to produce any time stamp tokens that might be required.

  • in_place – Sign the input in-place. If False, write output to a BytesIO object.

  • existing_fields_only – If True, never create a new empty signature field to contain the signature. If False, a new field may be created if no field matching field_name exists.

  • new_field_spec – If a new field is to be created, this parameter allows the caller to specify the field’s properties in the form of a SigFieldSpec. This parameter is only meaningful if existing_fields_only is False.

Returns

The output stream containing the signed output.

pyhanko.sign.signers.load_certs_from_pemder(cert_files)

A convenience function to load PEM/DER-encoded certificates from files.

Parameters

cert_files – An iterable of file names.

Returns

A generator producing asn1crypto.x509.Certificate objects.

pyhanko.sign.signers.DEFAULT_MD = 'sha256'

Default message digest algorithm used when computing digests for use in signatures.

pyhanko.sign.signers.DEFAULT_SIGNING_STAMP_STYLE = TextStampStyle(text_box_style=TextBoxStyle(font=<pyhanko.pdf_utils.font.SimpleFontEngine object>, font_size=10, leading=None, text_sep=10, border_width=0, vertical_center=True), border_width=3, stamp_text='Digitally signed by %(signer)s.\nTimestamp: %(ts)s.', timestamp_format='%Y-%m-%d %H:%M:%S %Z', background=<pyhanko.pdf_utils.content.RawContent object>, background_opacity=0.6)

Default stamp style used for visible signatures.