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:
CertificateError
is raised if the certificate contains nosubjectAltName
s 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
subjectAltName
s.
New in version 18.1.0.
Changed in version 24.1.0:
CertificateError
is raised if the certificate contains nosubjectAltName
s 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:
commonName
is 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
subjectAltName
s.
Changed in version 24.1.0:
CertificateError
is raised if the certificate contains nosubjectAltName
s 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.
New in version 18.1.0.
Changed in version 24.1.0:
CertificateError
is raised if the certificate contains nosubjectAltName
s 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:
commonName
is 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
Union
of 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.
- 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.
- 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.
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
subjectAltName
s.
- 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
CommonName
which is deprecated.Deprecated since version 23.1.0.