X509: Certificates and Verification
To be able to verify structures, Signify has a library to allow validating certificates. The Certificate is an object that abstracts a x509 certificate and has the ability to be verified. The verification requires the creation of a validation chain, that lead back to a trusted certificate authority.
You can use this module as follows:
trust_store = FileSystemCertificateStore(location=pathlib.Path("certificates/authenticode/"), trusted=True)
context = VerificationContext(trust_store)
with open("certificate.pem", "rb") as f, open("certificate2.pem", "rb") as g:
to_verify1 = Certificate.from_pem(f.read())
to_verify2 = Certificate.from_pem(g.read())
to_verify1.verify(context) # prints True
to_verify2.verify(context) # raises VerificationError
Certificate
- class signify.x509.Certificate(asn1: Certificate | CertificateChoices)
Representation of a certificate. It is built from an ASN.1 structure.
- property extensions: dict[str, Any]
This is a list of extension objects.
- classmethod from_der(content: bytes) Certificate
Load the Certificate object from DER-encoded data
- classmethod from_pem(content: bytes) Certificate
Reads a Certificate from a PEM formatted file.
- classmethod from_pems(content: bytes) Iterator[Certificate]
Reads a Certificate from a PEM formatted file.
- property issuer: CertificateName
The
CertificateNamefor the issuer.
- potential_chains(context: VerificationContext) Iterator[list[Certificate]]
Alias for
VerificationContext.potential_chains()
- property serial_number: int
The full integer serial number of the certificate
- property signature_algorithm: str
These values are considered part of the certificate, but not fully parsed.
- property signature_value: bytes
These values are considered part of the certificate, but not fully parsed.
- property subject: CertificateName
The
CertificateNamefor the subject.
- property subject_public_algorithm: AlgorithmIdentifier
These values are considered part of the certificate, but not fully parsed.
- property subject_public_key: bytes
These values are considered part of the certificate, but not fully parsed.
- property to_der: bytes
Returns the DER-encoded data from this certificate.
- property valid_from: datetime
The datetime objects between which the certificate is valid.
- property valid_to: datetime
The datetime objects between which the certificate is valid.
- verify(context: VerificationContext) Iterable[Certificate]
Alias for
VerificationContext.verify()
- verify_signature(signature: bytes, data: bytes, algorithm: HashFunction, allow_legacy: bool = False) None
Verifies whether the signature bytes match the data using the hashing algorithm. Supports RSA and EC keys. Note that not all hashing algorithms are supported.
- Parameters:
signature – The signature to verify
data – The data that must be verified
algorithm – The hashing algorithm to use
allow_legacy –
If
True, allows legacy signature verification. This method is intended for the case where thesignaturedoes not contain an ASN.1 structure, but a raw hash value instead. It is attempted automatically when verification of the RSA signature fails.This case is described in more detail on https://mta.openssl.org/pipermail/openssl-users/2015-September/002053.html
- property version: str
This is the version of the certificate
- class signify.x509.CertificateName(asn1: Name | GeneralName)
- property dn: str
Returns an (almost) rfc2253 compatible string given a RDNSequence
- get_components(component_type: None = None) Iterator[tuple[str, str]]
- get_components(component_type: str) Iterator[str]
Get individual components of this CertificateName
- Parameters:
component_type – if provided, yields only values of this type, if not provided, yields tuples of
(type, value)
- property rdns: Iterable[tuple[str, str]]
A list of all components of the object.
Certificate Store
- class signify.x509.CertificateStore(*args: Certificate | Iterable[Certificate], trusted: bool = False, ctl: CertificateTrustList | dict[str, list[str] | None] | None = None)
A list of
Certificateobjects.- __init__(*args: Certificate | Iterable[Certificate], trusted: bool = False, ctl: CertificateTrustList | dict[str, list[str] | None] | None = None)
- Parameters:
trusted – If true, all certificates that are appended to this structure are set to trusted.
ctl – The certificate trust list to use (if any), or a mapping of SHA-1 hashes to acceptable EKU’s.
- find_certificate(**kwargs: Any) Certificate
Finds the certificate as specified by the keyword arguments. See
find_certificates()for all possible arguments. If there is not exactly 1 certificate matching the parameters, i.e. there are zero or there are multiple, an error is raised.- Raises:
KeyError –
- find_certificates(*, subject: CertificateName | None = None, serial_number: int | None = None, issuer: CertificateName | None = None, sha256_fingerprint: str | None = None) Iterable[Certificate]
Finds all certificates given by the specified properties. A property can be omitted by specifying
None. Calling this function without arguments is the same as iterating over this store- Parameters:
subject – Certificate subject to look for, as
CertificateNameserial_number (int) – Serial number to look for.
issuer – Certificate issuer to look for, as
CertificateNamesha256_fingerprint (str) – The SHA-256 fingerprint to look for
- is_trusted(certificate: Certificate) bool
- Returns whether the provided certificate is trusted by this certificate
store.
Warning
This check does not verify that the certificate is valid according to the Trust List, if set. It merely checks that the provided certificate is in a trusted certificate store. You still need to verify the chain for its full trust.
- verify_trust(chain: list[Certificate], context: VerificationContext | None = None) bool
Verifies that the chain is trusted given the context.
- class signify.x509.FileSystemCertificateStore(location: Path, *args: Any, **kwargs: Any)
A list of
Certificateobjects loaded from the file system.- __init__(location: Path, *args: Any, **kwargs: Any)
- Parameters:
location – The file system location for the certificates.
trusted – If true, all certificates that are appended to this structure are set to trusted.
Verification
- class signify.x509.VerificationContext(*stores: CertificateStore, timestamp: datetime | None = None, key_usages: Iterable[str] | None = None, optional_ku: Literal['critical'] | bool = True, extended_key_usages: Iterable[str] | None = None, optional_eku: Literal['critical'] | bool = True, allow_legacy: bool = True, revocation_mode: Literal['soft-fail', 'hard-fail', 'require'] = 'soft-fail', allow_fetching: bool = False, fetch_timeout: int = 30, crls: Iterable[CertificateList] | None = None, ocsps: Iterable[OCSPResponse] | None = None)
- __init__(*stores: CertificateStore, timestamp: datetime | None = None, key_usages: Iterable[str] | None = None, optional_ku: Literal['critical'] | bool = True, extended_key_usages: Iterable[str] | None = None, optional_eku: Literal['critical'] | bool = True, allow_legacy: bool = True, revocation_mode: Literal['soft-fail', 'hard-fail', 'require'] = 'soft-fail', allow_fetching: bool = False, fetch_timeout: int = 30, crls: Iterable[CertificateList] | None = None, ocsps: Iterable[OCSPResponse] | None = None)
A context holding properties about the verification of a signature or certificate.
- Parameters:
stores – A list of
CertificateStoreobjects that contain certificatestimestamp – The timestamp to verify with. If
None, the current time is used. Must be a timezone-aware timestamp.key_usages – An iterable with the keyUsages to check for. For valid options, see
certvalidator.CertificateValidator.validate_usage()optional_ku – If
True, sets thekey_usagesas optionally present in the certificates, i.e. the certificate successfully validates when the keyUsage extension is missing from the certificate. WhenFalse, thekey_usagesmust be present. Whencritical, the key usage is considered validly absent when the keyUsage extension is not marked as critical.extended_key_usages – An iterable with the EKU’s to check for. See
certvalidator.CertificateValidator.validate_usage()optional_eku – If
True, sets theextended_key_usagesas optionally present in the certificates, i.e. the certificate validates successfully validates when the extendedKeyUsage extension is missing from the certificate. WhenFalse, theextended_key_usagesmust be present. Whencritical, the extended key usage is considered validly absent when the extendedKeyUsage extension is not marked as critical.allow_legacy – If
True, allows chain verification if the signature hash algorithm is very old (e.g. MD2). Additionally, allows the verification of encrypted hashes inCertificate.verify_signature()instead of encrypted DigestInfo ASN.1 structures. Both are found in the wild, but setting toTruedoes reduce the reliability of the verification.revocation_mode – Can be either
soft-fail,hard-failorrequire. See the documentation ofcertvalidator.ValidationContext()for the full definitionallow_fetching – If
True, allows the underlying verification module to obtain CRL and OSCP responses when needed.fetch_timeout – The timeout used when fetching CRL/OSCP responses
crls – List of
asn1crypto.crl.CertificateListobjects to aid in verifying revocation statuses.ocsps – List of
asn1crypto.ocsp.OCSPResponseobjects to aid in verifying revocation statuses.
- add_store(store: CertificateStore) None
Adds a certificate store to the VerificationContext
- property certificates: Iterator[Certificate]
Iterates over all certificates in the associated stores.
- find_certificate(**kwargs: Any) Certificate
Finds the certificate as specified by the keyword arguments. See
find_certificates()for all possible arguments. If there is not exactly 1 certificate matching the parameters, i.e. there are zero or there are multiple, an error is raised.- Raises:
KeyError –
- find_certificates(**kwargs: Any) Iterator[Certificate]
Finds all certificates given by the specified keyword arguments. See
CertificateStore.find_certificates()for a list of all supported arguments.
- is_trusted(certificate: Certificate) bool
Returns whether the provided certificate is trusted by a trusted certificate store.
Warning
This check does not verify that the certificate is valid according to the Trust List, if set. It merely checks that the provided certificate is in a trusted certificate store. You still need to verify the chain for its full trust.
- potential_chains(certificate: Certificate, depth: int = 10) Iterator[list[Certificate]]
Returns all possible chains from the provided certificate, solely based on issuer/subject matching.
THIS METHOD DOES NOT VERIFY WHETHER A CHAIN IS ACTUALLY VALID. Use
verify()for that.- Parameters:
certificate – The certificate to build a potential chain for
depth – The maximum depth, used for recursion
- Returns:
A iterable of all possible certificate chains
- verify(certificate: Certificate) list[Certificate]
Verifies the certificate, and its chain.
- Parameters:
certificate – The certificate to verify
- Returns:
A valid certificate chain for this certificate.
- Raises:
AuthenticodeVerificationError – When the certificate could not be verified.
- verify_trust(chain: list[Certificate]) bool
Determines whether the given certificate chain is trusted by a trusted certificate store.
- Parameters:
chain – The certificate chain to verify trust for.
- Returns:
Trueif the certificate chain is trusted by a certificate store.