Verifying an SSL/TLS certificate is crucial to guaranteeing a safe and reliable connection. This procedure makes that the certificate matches the requested domain or identity, verifies that it was issued by a reliable Certificate Authority (CA), and checks its validity.
1. Retrieve the SSL Certificate
Using OpenSSL:
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -noout -subject -dates
Programmatically: Use SSL/TLS libraries in programming languages like Python, Java, or Node.js to connect and retrieve the certificate.
2. Check Certificate Validity
- Validity Period: Confirm the certificate is within its "notBefore" and "notAfter" dates.
- Revocation Status: Ensure the certificate hasn’t been revoked by consulting Certificate Revocation Lists (CRLs) or Online Certificate Status Protocol (OCSP), though TLS libraries often handle this automatically.
3. Verify Certificate Chain
- Ensure the certificate was issued by a trusted CA by checking the certificate chain up to a trusted root CA.
- Validate each certificate in the chain and confirm none have been revoked.
4. Domain/Identity Verification
Check the Subject Alternative Name (SAN) or Common Name (CN) fields in the certificate to ensure they match the intended domain.
Libraries and Tools for SSL Verification
- Python:
- ssl and socket modules for TLS connections.
- cryptography library for advanced certificate verification.
- certifi and pyOpenSSL for trust chain and validity verification.
- Java:
- java.security and javax.net.ssl packages for built-in TLS management.
- Bouncy Castle library for additional cryptographic features.
- Node.js:
- tls module for TLS connections.
- crypto module for cryptographic operations.
Verifying an SSL Certificate in Python
Using the ssl and cryptography libraries in Python, you can verify a certificate as shown in this example:
import ssl
import socket
from cryptography import x509
from cryptography.x509.oid import NameOID
from cryptography.hazmat.backends import default_backend
import datetime
def verify_ssl_certificate(hostname, port=443):
# Establish a connection to retrieve the certificate
context = ssl.create_default_context()
with socket.create_connection((hostname, port)) as sock:
with context.wrap_socket(sock, server_hostname=hostname) as ssock:
der_cert = ssock.getpeercert(binary_form=True)
# Load the certificate
cert = x509.load_der_x509_certificate(der_cert, default_backend())
# Check validity period
not_before = cert.not_valid_before
not_after = cert.not_valid_after
now = datetime.datetime.now()
if not (not_before <= now <= not_after):
print("Certificate is not within its validity period.")
return False
# Verify domain matches
try:
cert_subject_alt_name = cert.extensions.get_extension_for_oid(NameOID.COMMON_NAME).value
except x509.ExtensionNotFound:
cert_subject_alt_name = cert.subject.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value
if hostname not in str(cert_subject_alt_name):
print("Certificate domain mismatch.")
return False
# Additional checks (e.g., certificate chain verification) would typically be handled by the TLS library
return True
# Example usage
if verify_ssl_certificate('example.com'):
print("SSL Certificate for example.com is valid.")