Python wrapper module around the OpenSSL library providing cryptographic functionality and TLS/SSL capabilities
—
Certificate trust store management and verification operations with support for certificate chains, CRL checking, and custom verification policies.
Manage collections of trusted certificates and certificate revocation lists for verification operations.
class X509Store:
def __init__(self):
"""Create new empty certificate store"""
def add_cert(self, cert: X509):
"""
Add trusted certificate to store.
Parameters:
- cert: X509 certificate to trust
"""
def add_crl(self, crl):
"""
Add certificate revocation list.
Parameters:
- crl: Certificate revocation list object
"""
def set_flags(self, flags: int):
"""
Set verification behavior flags.
Parameters:
- flags: Combination of X509StoreFlags constants
"""
def set_time(self, vfy_time):
"""
Set verification time for time-sensitive checks.
Parameters:
- vfy_time: datetime object for verification time
"""
def load_locations(self, cafile, capath=None):
"""
Load CA certificates from file or directory.
Parameters:
- cafile: Path to CA certificate file (PEM format)
- capath: Path to directory containing CA certificates
"""Perform actual certificate verification against trust stores with detailed error reporting.
class X509StoreContext:
def __init__(self, store: X509Store, certificate: X509, chain=None):
"""
Create verification context.
Parameters:
- store: Trust store containing CA certificates
- certificate: Certificate to verify
- chain: Optional list of intermediate certificates
"""
def set_store(self, store: X509Store):
"""
Change the trust store.
Parameters:
- store: New trust store to use
"""
def verify_certificate(self):
"""
Verify certificate against store.
Raises:
X509StoreContextError: If verification fails
"""
def get_verified_chain(self) -> list:
"""
Get complete verified certificate chain.
Returns:
List of X509 certificates from end-entity to root
"""Control certificate verification behavior with detailed policy options.
class X509StoreFlags:
CRL_CHECK: int
CRL_CHECK_ALL: int
IGNORE_CRITICAL: int
X509_STRICT: int
ALLOW_PROXY_CERTS: int
POLICY_CHECK: int
EXPLICIT_POLICY: int
INHIBIT_MAP: int
CHECK_SS_SIGNATURE: int
PARTIAL_CHAIN: intDetailed error reporting for certificate verification failures.
class X509StoreContextError(Exception):
"""Exception raised when certificate verification fails"""
certificate: X509 # Certificate that caused the error
errors: list # List of detailed error informationStandard X.509 verification result codes for detailed error analysis.
# Note: X509VerificationCodes is defined in the SSL module
from OpenSSL.SSL import X509VerificationCodes
class X509VerificationCodes:
OK: int
ERR_UNABLE_TO_GET_ISSUER_CERT: int
ERR_UNABLE_TO_GET_CRL: int
ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: int
ERR_CERT_SIGNATURE_FAILURE: int
ERR_CRL_SIGNATURE_FAILURE: int
ERR_CERT_NOT_YET_VALID: int
ERR_CERT_HAS_EXPIRED: int
ERR_CRL_NOT_YET_VALID: int
ERR_CRL_HAS_EXPIRED: int
ERR_DEPTH_ZERO_SELF_SIGNED_CERT: int
ERR_SELF_SIGNED_CERT_IN_CHAIN: int
ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: int
ERR_CERT_CHAIN_TOO_LONG: int
ERR_CERT_REVOKED: intfrom OpenSSL import crypto
# Load certificates
with open('ca.crt', 'rb') as f:
ca_cert = crypto.load_certificate(crypto.FILETYPE_PEM, f.read())
with open('server.crt', 'rb') as f:
server_cert = crypto.load_certificate(crypto.FILETYPE_PEM, f.read())
# Create trust store and add CA
store = crypto.X509Store()
store.add_cert(ca_cert)
# Create verification context
context = crypto.X509StoreContext(store, server_cert)
try:
# Verify certificate
context.verify_certificate()
print("Certificate verification successful")
# Get verified chain
chain = context.get_verified_chain()
print(f"Verified chain length: {len(chain)}")
except crypto.X509StoreContextError as e:
print(f"Verification failed: {e}")
print(f"Failed certificate: {e.certificate.get_subject().CN}")from OpenSSL import crypto
# Load certificate chain
with open('ca.crt', 'rb') as f:
ca_cert = crypto.load_certificate(crypto.FILETYPE_PEM, f.read())
with open('intermediate.crt', 'rb') as f:
intermediate_cert = crypto.load_certificate(crypto.FILETYPE_PEM, f.read())
with open('server.crt', 'rb') as f:
server_cert = crypto.load_certificate(crypto.FILETYPE_PEM, f.read())
# Create trust store with root CA
store = crypto.X509Store()
store.add_cert(ca_cert)
# Verify with intermediate certificate in chain
context = crypto.X509StoreContext(store, server_cert, [intermediate_cert])
try:
context.verify_certificate()
print("Chain verification successful")
# Print full chain
chain = context.get_verified_chain()
for i, cert in enumerate(chain):
print(f"Chain[{i}]: {cert.get_subject().CN}")
except crypto.X509StoreContextError as e:
print(f"Chain verification failed: {e}")from OpenSSL import crypto
import datetime
# Create store with custom flags
store = crypto.X509Store()
# Enable strict checking and CRL validation
flags = (crypto.X509StoreFlags.X509_STRICT |
crypto.X509StoreFlags.CRL_CHECK_ALL)
store.set_flags(flags)
# Set specific verification time
verification_time = datetime.datetime(2023, 6, 1)
store.set_time(verification_time)
# Load CA certificates from directory
store.load_locations(None, '/etc/ssl/certs')
# Add specific trusted certificate
with open('trusted.crt', 'rb') as f:
trusted_cert = crypto.load_certificate(crypto.FILETYPE_PEM, f.read())
store.add_cert(trusted_cert)
# Verify certificate with strict policies
with open('test.crt', 'rb') as f:
test_cert = crypto.load_certificate(crypto.FILETYPE_PEM, f.read())
context = crypto.X509StoreContext(store, test_cert)
try:
context.verify_certificate()
print("Strict verification passed")
except crypto.X509StoreContextError as e:
print(f"Strict verification failed: {e}")from OpenSSL import SSL, crypto
def verify_callback(conn, cert, errno, depth, ok):
"""
Custom certificate verification callback.
Parameters:
- conn: SSL connection object
- cert: Certificate being verified
- errno: Error number (0 if OK)
- depth: Chain depth (0 for end-entity)
- ok: OpenSSL's verification result
Returns:
True to accept, False to reject
"""
subject = cert.get_subject()
print(f"Verifying: {subject.CN} at depth {depth}")
if errno == 0:
print(" Certificate OK")
return True
# Custom logic for specific errors
if errno == crypto.X509VerificationCodes.ERR_CERT_HAS_EXPIRED:
print(" Certificate expired - checking grace period")
# Could implement grace period logic here
return False
if errno == crypto.X509VerificationCodes.ERR_SELF_SIGNED_CERT_IN_CHAIN:
print(" Self-signed certificate in chain")
# Could allow self-signed for development
return False
print(f" Verification error: {errno}")
return False
# Use callback in SSL context
context = SSL.Context(SSL.TLS_CLIENT_METHOD)
context.set_verify(SSL.VERIFY_PEER, verify_callback)
context.set_default_verify_paths()from OpenSSL import crypto
import os
# Create store and load system CA certificates
store = crypto.X509Store()
# Method 1: Load default locations
store.load_locations('/etc/ssl/certs/ca-certificates.crt')
# Method 2: Load from CA bundle
ca_bundle_paths = [
'/etc/ssl/certs/ca-certificates.crt', # Debian/Ubuntu
'/etc/ssl/ca-bundle.pem', # Red Hat/CentOS
'/etc/ssl/certs/ca-bundle.crt', # SUSE
'/usr/local/share/ca-certificates/', # Local additions
]
for path in ca_bundle_paths:
if os.path.exists(path):
try:
store.load_locations(path)
print(f"Loaded CA certificates from {path}")
break
except Exception as e:
print(f"Failed to load from {path}: {e}")
# Add custom enterprise CA
try:
with open('/usr/local/share/ca-certificates/enterprise-ca.crt', 'rb') as f:
enterprise_ca = crypto.load_certificate(crypto.FILETYPE_PEM, f.read())
store.add_cert(enterprise_ca)
print("Added enterprise CA certificate")
except FileNotFoundError:
print("No enterprise CA found")from OpenSSL import crypto
def detailed_verification(store, cert, chain=None):
"""Perform certificate verification with detailed error reporting"""
context = crypto.X509StoreContext(store, cert, chain)
try:
context.verify_certificate()
print("✓ Certificate verification successful")
# Show verification details
verified_chain = context.get_verified_chain()
print(f"✓ Verified chain length: {len(verified_chain)}")
for i, cert in enumerate(verified_chain):
subject = cert.get_subject()
print(f" [{i}] {subject.CN}")
return True
except crypto.X509StoreContextError as e:
print("✗ Certificate verification failed")
print(f" Error: {e}")
if hasattr(e, 'certificate'):
failed_cert = e.certificate
print(f" Failed certificate: {failed_cert.get_subject().CN}")
# Provide helpful error messages
error_messages = {
crypto.X509VerificationCodes.ERR_CERT_HAS_EXPIRED:
"Certificate has expired - check validity dates",
crypto.X509VerificationCodes.ERR_CERT_NOT_YET_VALID:
"Certificate is not yet valid - check system time",
crypto.X509VerificationCodes.ERR_SELF_SIGNED_CERT_IN_CHAIN:
"Self-signed certificate in chain - add to trust store",
crypto.X509VerificationCodes.ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
"Missing issuer certificate - add intermediate certificates",
}
# Check specific error codes in the errors list
if hasattr(e, 'errors'):
for error in e.errors:
if error in error_messages:
print(f" Suggestion: {error_messages[error]}")
return False
# Usage example
store = crypto.X509Store()
# ... configure store ...
with open('certificate.crt', 'rb') as f:
cert = crypto.load_certificate(crypto.FILETYPE_PEM, f.read())
detailed_verification(store, cert)Install with Tessl CLI
npx tessl i tessl/pypi-pyopenssl