pyhanko.sign.general module

General tools related to Cryptographic Message Syntax (CMS) signatures, not necessarily to the extent implemented in the PDF specification.

CMS is defined in RFC 5652. To parse CMS messages, pyHanko relies heavily on asn1crypto.

class pyhanko.sign.general.SignatureStatus(intact: bool, valid: bool, trusted: bool, revoked: bool, signing_cert: asn1crypto.x509.Certificate, pkcs7_signature_mechanism: str, md_algorithm: str, validation_path: pyhanko_certvalidator.path.ValidationPath)

Bases: object

Class describing the validity of a (general) CMS signature.

intact: bool

Reports whether the signature is intact, i.e. whether the hash of the message content (which may or may not be embedded inside the CMS object itself) matches the hash value that was signed.

valid: bool

Reports whether the signature is valid, i.e. whether the hash’s signature actually validates.

trusted: bool

Reports whether the signer’s certificate is trusted w.r.t. the currently relevant validation context and key usage requirements.

revoked: bool

Reports whether the signer’s certificate has been revoked or not. If this field is True, then obviously trusted will be False.

signing_cert: asn1crypto.x509.Certificate

Contains the certificate of the signer, as embedded in the CMS object.

pkcs7_signature_mechanism: str

CMS signature mechanism used.

md_algorithm: str

Message digest algorithm used.

validation_path: pyhanko_certvalidator.path.ValidationPath

Validation path providing a valid chain of trust from the signer’s certificate to a trusted root certificate.

key_usage: ClassVar[Set[str]] = {'non_repudiation'}

Class property indicating which key usage extensions are required to be present on the signer’s certificate. The default is non_repudiation only.

extd_key_usage: ClassVar[Optional[Set[str]]] = None

Class property indicating which extended key usage extensions are required to be present on the signer’s certificate.

See KeyUsageConstraints.extd_key_usage.

summary_fields()
summary()

Provide a textual but machine-parsable summary of the validity.

classmethod validate_cert_usage(validator: pyhanko_certvalidator.CertificateValidator, key_usage_settings: Optional[pyhanko.sign.general.KeyUsageConstraints] = None)
pyhanko.sign.general.simple_cms_attribute(attr_type, value)

Convenience method to quickly construct a CMS attribute object with one value.

Parameters
  • attr_type – The attribute type, as a string or OID.

  • value – The value.

Returns

A cms.CMSAttribute object.

pyhanko.sign.general.find_cms_attribute(attrs, name)

Find and return CMS attribute values of a given type.

Parameters
  • attrs – The cms.CMSAttributes object.

  • name – The attribute type as a string (as defined in asn1crypto).

Returns

The values associated with the requested type, if present.

Raises

NonexistentAttributeError – Raised when no such type entry could be found in the cms.CMSAttributes object.

pyhanko.sign.general.find_unique_cms_attribute(attrs, name)

Find and return a unique CMS attribute value of a given type.

Parameters
  • attrs – The cms.CMSAttributes object.

  • name – The attribute type as a string (as defined in asn1crypto).

Returns

The value associated with the requested type, if present.

Raises
pyhanko.sign.general.extract_message_digest(signer_info: asn1crypto.cms.SignerInfo)
pyhanko.sign.general.validate_sig_integrity(signer_info: asn1crypto.cms.SignerInfo, cert: asn1crypto.x509.Certificate, expected_content_type: str, actual_digest: bytes, weak_hash_algorithms=frozenset({'md2', 'md5', 'sha1'})) Tuple[bool, bool]

Validate the integrity of a signature for a particular signerInfo object inside a CMS signed data container.

Warning

This function does not do any trust checks, and is considered “dangerous” API because it is easy to misuse.

Parameters
  • signer_info – A cms.SignerInfo object.

  • cert

    The signer’s certificate.

    Note

    This function will not attempt to extract certificates from the signed data.

  • expected_content_type – The expected value for the content type attribute (as a Python string, see cms.ContentType).

  • actual_digest – The actual digest to be matched to the message digest attribute.

  • weak_hash_algorithms – List, tuple or set of weak hashing algorithms.

Returns

A tuple of two booleans. The first indicates whether the provided digest matches the value in the signed attributes. The second indicates whether the signature of the digest is valid.

class pyhanko.sign.general.CertificateStore

Bases: pyhanko_certvalidator.registry.CertificateCollection, abc.ABC

register(cert: asn1crypto.x509.Certificate) bool

Register a single certificate.

Parameters

cert – Certificate to add.

Returns

True if the certificate was added, False if it already existed in this store.

register_multiple(certs)

Register multiple certificates.

Parameters

certs – Certificates to register.

Returns

True if at least one certificate was added, False if all certificates already existed in this store.

class pyhanko.sign.general.SimpleCertificateStore

Bases: pyhanko_certvalidator.registry.CertificateStore

Simple trustless certificate store.

classmethod from_certs(certs)
register(cert: asn1crypto.x509.Certificate) bool

Register a single certificate.

Parameters

cert – Certificate to add.

Returns

True if the certificate was added, False if it already existed in this store.

retrieve_many_by_key_identifier(key_identifier: bytes)

Retrieves possibly multiple certs via the corresponding key identifiers

Parameters

key_identifier – A byte string of the key identifier

Returns

A list of asn1crypto.x509.Certificate objects

retrieve_by_name(name: asn1crypto.x509.Name)

Retrieves a list certs via their subject name

Parameters

name – An asn1crypto.x509.Name object

Returns

A list of asn1crypto.x509.Certificate objects

retrieve_by_issuer_serial(issuer_serial)

Retrieve a certificate by its issuer_serial value.

Parameters

issuer_serial – The issuer_serial value of the certificate.

Returns

The certificate corresponding to the issuer_serial key passed in.

Returns

None or an asn1crypto.x509.Certificate object

class pyhanko.sign.general.KeyUsageConstraints(key_usage: Optional[Set[str]] = None, key_usage_forbidden: Optional[Set[str]] = None, extd_key_usage: Optional[Set[str]] = None, explicit_extd_key_usage_required: bool = True, match_all_key_usages: bool = False)

Bases: pyhanko.pdf_utils.config_utils.ConfigurableMixin

Convenience class to pass around key usage requirements and validate them. Intended to be flexible enough to handle both PKIX and ISO 32000 certificate seed value constraint semantics.

Changed in version 0.6.0: Bring extended key usage semantics in line with RFC 5280 (PKIX).

key_usage: Set[str] = None

All or some (depending on match_all_key_usage) of these key usage extensions must be present in the signer’s certificate. If not set or empty, all key usages are considered acceptable.

key_usage_forbidden: Set[str] = None

These key usage extensions must not be present in the signer’s certificate.

Note

This behaviour is undefined in RFC 5280 (PKIX), but included for compatibility with certificate seed value settings in ISO 32000.

extd_key_usage: Set[str] = None

List of acceptable key purposes that can appear in an extended key usage extension in the signer’s certificate, if such an extension is at all present. If not set, all extended key usages are considered acceptable.

If no extended key usage extension is present, or the anyExtendedKeyUsage key purpose ID is present the resulting behaviour depends on explicit_extd_key_usage_required.

Setting this option to the empty set (as opposed to None) effectively bans all (presumably unrecognised) extended key usages.

Warning

Note the difference in behaviour with key_usage for empty sets of valid usages.

Warning

Contrary to what some CAs seem to believe, the criticality of the extended key usage extension is irrelevant here. Even a non-critical EKU extension must be enforced according to RFC 5280 § 4.2.1.12.

In practice, many certificate authorities issue non-repudiation certs that can also be used for TLS authentication by only including the TLS client authentication key purpose ID in the EKU extension. Interpreted strictly, RFC 5280 bans such certificates from being used to sign documents, and pyHanko will enforce these semantics if extd_key_usage is not None.

explicit_extd_key_usage_required: bool = True

New in version 0.6.0.

Require an extended key usage extension with the right key usages to be present if extd_key_usage is non-empty.

If this flag is True, at least one key purpose in extd_key_usage must appear in the certificate’s extended key usage, and anyExtendedKeyUsage will be ignored.

match_all_key_usages: bool = False

New in version 0.6.0.

If True, all key usages indicated in key_usage must be present in the certificate. If False, one match suffices.

If key_usage is empty or None, this option has no effect.

validate(cert: asn1crypto.x509.Certificate)
classmethod process_entries(config_dict)

Hook method that can modify the configuration dictionary to overwrite or tweak some of their values (e.g. to convert string parameters into more complex Python objects)

Subclasses that override this method should call super().process_entries(), and leave keys that they do not recognise untouched.

Parameters

config_dict – A dictionary containing configuration values.

Raises

ConfigurationError – when there is a problem processing a relevant entry.

exception pyhanko.sign.general.SigningError

Bases: ValueError

Error encountered while signing a file.

exception pyhanko.sign.general.UnacceptableSignerError

Bases: pyhanko.sign.general.SigningError

Error raised when a signer was judged unacceptable.

exception pyhanko.sign.general.WeakHashAlgorithmError

Bases: pyhanko.sign.general.SignatureValidationError

exception pyhanko.sign.general.NonexistentAttributeError

Bases: KeyError

exception pyhanko.sign.general.MultivaluedAttributeError

Bases: ValueError

exception pyhanko.sign.general.SignatureValidationError

Bases: ValueError

Error validating a signature.

pyhanko.sign.general.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.general.load_cert_from_pemder(cert_file)

A convenience function to load a single PEM/DER-encoded certificate from a file.

Parameters

cert_file – A file name.

Returns

An asn1crypto.x509.Certificate object.

pyhanko.sign.general.load_private_key_from_pemder(key_file, passphrase: Optional[bytes]) asn1crypto.keys.PrivateKeyInfo

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

Parameters
  • key_file – File to read the key from.

  • passphrase – Key passphrase.

Returns

A private key encoded as an unencrypted PKCS#8 PrivateKeyInfo object.

pyhanko.sign.general.get_pyca_cryptography_hash(algorithm, prehashed=False)
pyhanko.sign.general.optimal_pss_params(cert: asn1crypto.x509.Certificate, digest_algorithm: str) asn1crypto.algos.RSASSAPSSParams

Figure out the optimal RSASSA-PSS parameters for a given certificate. The subject’s public key must be an RSA key.

Parameters
  • cert – An RSA X.509 certificate.

  • digest_algorithm – The digest algorithm to use.

Returns

RSASSA-PSS parameters.

pyhanko.sign.general.as_signing_certificate(cert: asn1crypto.x509.Certificate) asn1crypto.tsp.SigningCertificate

Format an ASN.1 SigningCertificate object, where the certificate is identified by its SHA-1 digest.

Parameters

cert – An X.509 certificate.

Returns

A tsp.SigningCertificate object referring to the original certificate.

pyhanko.sign.general.as_signing_certificate_v2(cert: asn1crypto.x509.Certificate, hash_algo='sha256') asn1crypto.tsp.SigningCertificateV2

Format an ASN.1 SigningCertificateV2 value, where the certificate is identified by the hash algorithm specified.

Parameters
  • cert – An X.509 certificate.

  • hash_algo – Hash algorithm to use to digest the certificate. Default is SHA-256.

Returns

A tsp.SigningCertificateV2 object referring to the original certificate.

pyhanko.sign.general.match_issuer_serial(expected_issuer_serial: Union[asn1crypto.cms.IssuerAndSerialNumber, asn1crypto.tsp.IssuerSerial], cert: asn1crypto.x509.Certificate) bool

Match the issuer and serial number of an X.509 certificate against some expected identifier.

Parameters
  • expected_issuer_serial – A certificate identifier, either cms.IssuerAndSerialNumber or tsp.IssuerSerial.

  • cert – An x509.Certificate.

Returns

True if there’s a match, False otherwise.