API¶
Note
So far, public high-level APIs are only available for host names (RFC 6125) and IP addresses (RFC 2818).
All IDs specified by RFC 6125 are already implemented though.
If you’d like to play with them and provide feedback have a look at the verify_service_identity function in the hazmat module.
PyCA cryptography¶
- service_identity.cryptography.verify_certificate_hostname(certificate, hostname)¶
Verify whether certificate is valid for hostname.
Note
Nothing is verified about the authority of the certificate; the caller must verify that the certificate chains to an appropriate trust root themselves.
- Parameters:
certificate (Certificate) – A cryptography X509 certificate object.
hostname (str) – The hostname that certificate should be valid for.
- Raises:
service_identity.VerificationError – If certificate is not valid for hostname.
service_identity.CertificateError – If certificate contains invalid / unexpected data. This includes the case where the certificate contains no subjectAltNames.
Changed in version 24.1.0:
CertificateErroris raised if the certificate contains nosubjectAltNames instead ofVerificationError.
- service_identity.cryptography.verify_certificate_ip_address(certificate, ip_address)¶
Verify whether certificate is valid for ip_address.
Note
Nothing is verified about the authority of the certificate; the caller must verify that the certificate chains to an appropriate trust root themselves.
- Parameters:
certificate (Certificate) – A cryptography X509 certificate object.
ip_address (str) – The IP address that connection should be valid for. Can be an IPv4 or IPv6 address.
- Raises:
service_identity.VerificationError – If certificate is not valid for ip_address.
service_identity.CertificateError – If certificate contains invalid / unexpected data. This includes the case where the certificate contains no
subjectAltNames.
Added in version 18.1.0.
Changed in version 24.1.0:
CertificateErroris raised if the certificate contains nosubjectAltNames instead ofVerificationError.
- service_identity.cryptography.extract_patterns(cert)¶
Extract all valid ID patterns from a certificate for service verification.
- Parameters:
cert (Certificate) – The certificate to be dissected.
- Returns:
List of IDs.
- Return type:
Sequence[SRVPattern | URIPattern | DNSPattern | IPAddressPattern]
Changed in version 23.1.0:
commonNameis not used as a fallback anymore.
pyOpenSSL¶
- service_identity.pyopenssl.verify_hostname(connection, hostname)¶
Verify whether the certificate of connection is valid for hostname.
- Parameters:
connection (Connection) – A pyOpenSSL connection object.
hostname (str) – The hostname that connection should be connected to.
- Raises:
service_identity.VerificationError – If connection does not provide a certificate that is valid for hostname.
service_identity.CertificateError – If certificate provided by connection contains invalid / unexpected data. This includes the case where the certificate contains no
subjectAltNames.
Changed in version 24.1.0:
CertificateErroris raised if the certificate contains nosubjectAltNames instead ofVerificationError.In practice, this may look like the following:
import argparse import pprint import socket import idna from OpenSSL import SSL import service_identity parser = argparse.ArgumentParser( description="Connect to HOST, inspect its certificate " "and verify if it's valid for its hostname." ) parser.add_argument("HOST") args = parser.parse_args() hostname = args.HOST ctx = SSL.Context(SSL.TLSv1_2_METHOD) ctx.set_verify(SSL.VERIFY_PEER, lambda conn, cert, errno, depth, ok: bool(ok)) ctx.set_default_verify_paths() conn = SSL.Connection(ctx, socket.socket(socket.AF_INET, socket.SOCK_STREAM)) conn.set_tlsext_host_name(idna.encode(hostname)) conn.connect((hostname, 443)) try: conn.do_handshake() if cert := conn.get_peer_certificate(): print("Server certificate is valid for the following patterns:\n") pprint.pprint(service_identity.pyopenssl.extract_patterns(cert)) try: service_identity.pyopenssl.verify_hostname(conn, hostname) except service_identity.VerificationError: print(f"\nPresented certificate is NOT valid for {hostname}.") finally: conn.shutdown() except SSL.Error as e: print(f"TLS Handshake failed: {e!r}.") finally: conn.close()
- service_identity.pyopenssl.verify_ip_address(connection, ip_address)¶
Verify whether the certificate of connection is valid for ip_address.
- Parameters:
connection (Connection) – A pyOpenSSL connection object.
ip_address (str) – The IP address that connection should be connected to. Can be an IPv4 or IPv6 address.
- Raises:
service_identity.VerificationError – If connection does not provide a certificate that is valid for ip_address.
service_identity.CertificateError – If the certificate chain of connection contains a certificate that contains invalid/unexpected data.
Added in version 18.1.0.
Changed in version 24.1.0:
CertificateErroris raised if the certificate contains nosubjectAltNames instead ofVerificationError.
- service_identity.pyopenssl.extract_patterns(cert)¶
Extract all valid ID patterns from a certificate for service verification.
- Parameters:
cert (X509) – The certificate to be dissected.
- Returns:
List of IDs.
- Return type:
Sequence[SRVPattern | URIPattern | DNSPattern | IPAddressPattern]
Changed in version 23.1.0:
commonNameis not used as a fallback anymore.
Hazardous Materials¶
Danger
The following APIs require reader’s discretion. They are stable and they’ve been using internally by service-identity for years, but you need to know what you’re doing.
Pattern Objects¶
The following are the objects return by the extract_patterns functions.
They each carry the attributes that are necessary to match an ID of their type.
- service_identity.hazmat.CertificatePattern¶
A
Unionof all possible patterns that can be extracted from a certificate.It includes all of those that follow now.
- class service_identity.hazmat.DNSPattern(pattern)¶
A DNS pattern as extracted from certificates.
- pattern: bytes¶
The pattern.
- class service_identity.hazmat.IPAddressPattern(pattern)¶
An IP address pattern as extracted from certificates.
- pattern: IPv4Address | IPv6Address¶
The pattern.
- class service_identity.hazmat.URIPattern(protocol_pattern, dns_pattern)¶
An URI pattern as extracted from certificates.
- dns_pattern: DNSPattern¶
The pattern for the DNS part.
- protocol_pattern: bytes¶
The pattern for the protocol part.
- class service_identity.hazmat.SRVPattern(name_pattern, dns_pattern)¶
An SRV pattern as extracted from certificates.
- dns_pattern: DNSPattern¶
The pattern for the DNS part.
- name_pattern: bytes¶
The pattern for the name part.
Universal Errors and Warnings¶
- exception service_identity.VerificationError(errors)¶
Service identity verification failed.
- exception service_identity.CertificateError¶
Certificate contains invalid or unexpected data.
This includes the case where s certificate contains no
subjectAltNames.
- exception service_identity.SubjectAltNameWarning¶
This warning is not used anymore and will be removed in a future version.
Formerly:
Server Certificate does not contain a
SubjectAltName.Hostname matching is performed on the
CommonNamewhich is deprecated.Deprecated since version 23.1.0.