{"id":1705,"library":"service-identity","title":"Service Identity Verification","description":"Service-identity provides robust service identity verification for Python applications using `pyOpenSSL` and `cryptography`. It ensures that a presented certificate matches the expected identity of the service being connected to, preventing common man-in-the-middle attacks. The current version is 24.2.0, with a release cadence that is irregular but typically sees major updates annually or as needed for security fixes and breaking changes.","status":"active","version":"24.2.0","language":"en","source_language":"en","source_url":"https://github.com/pyca/service-identity","tags":["security","ssl","tls","cryptography","certificates","verification"],"install":[{"cmd":"pip install service-identity","lang":"bash","label":"Install service-identity"}],"dependencies":[{"reason":"Used for defining pattern objects.","package":"attrs","optional":false},{"reason":"Backend for extracting service identity patterns from pyOpenSSL certificate objects.","package":"pyopenssl","optional":false},{"reason":"Backend for extracting service identity patterns from cryptography certificate objects.","package":"cryptography","optional":false},{"reason":"Used for IDNA (Internationalized Domain Names in Applications) encoding/decoding.","package":"idna","optional":false}],"imports":[{"symbol":"verify_service_identity","correct":"from service_identity import verify_service_identity"},{"symbol":"CertificateError","correct":"from service_identity.exceptions import CertificateError"},{"note":"Choose the correct `extract_patterns` based on whether you're using `cryptography` or `pyOpenSSL` certificate objects.","wrong":"from service_identity.pyopenssl import extract_patterns","symbol":"extract_patterns","correct":"from service_identity.cryptography import extract_patterns"},{"symbol":"DNS_ID","correct":"from service_identity.patterns import DNS_ID"},{"symbol":"DNSPattern","correct":"from service_identity.patterns import DNSPattern"}],"quickstart":{"code":"from service_identity import verify_service_identity\nfrom service_identity.patterns import DNS_ID, DNSPattern\nfrom service_identity.exceptions import CertificateError\n\n# --- Example 1: Successful verification ---\n# In a real scenario, certificate_patterns would be extracted from an actual\n# certificate object using service_identity.cryptography.extract_patterns()\n# or service_identity.pyopenssl.extract_patterns().\ncertificate_patterns_ok = [\n    DNSPattern(\"example.com\"),\n    DNSPattern(\"www.example.com\")\n]\nservice_identity_ok = DNS_ID(\"www.example.com\")\n\ntry:\n    verify_service_identity(certificate_patterns_ok, service_identity_ok)\n    print(f\"[SUCCESS] Service identity '{service_identity_ok.id}' verified.\")\nexcept CertificateError as e:\n    print(f\"[FAILURE] Verification failed: {e}\")\n\n# --- Example 2: Failed verification (mismatched hostname) ---\ncertificate_patterns_mismatch = [DNSPattern(\"example.com\")]\nservice_identity_mismatch = DNS_ID(\"wrong-host.com\")\n\ntry:\n    verify_service_identity(certificate_patterns_mismatch, service_identity_mismatch)\n    print(f\"[SUCCESS] Service identity '{service_identity_mismatch.id}' verified.\")\nexcept CertificateError as e:\n    print(f\"[FAILURE] Verification failed: {e}\")\n\n# --- Example 3: Failed verification (simulated missing subjectAltName) ---\n# This simulates a certificate that has no subjectAltName entries,\n# which will always lead to a CertificateError.\ncertificate_patterns_no_san = []\nservice_identity_no_san = DNS_ID(\"anyhost.com\")\n\ntry:\n    verify_service_identity(certificate_patterns_no_san, service_identity_no_san)\n    print(f\"[SUCCESS] Service identity '{service_identity_no_san.id}' verified.\")\nexcept CertificateError as e:\n    print(f\"[FAILURE] Verification failed (missing SAN): {e}\")","lang":"python","description":"This quickstart demonstrates how to use `service-identity` to verify a service's identity against certificate patterns. It shows both successful and failed verification cases, including a simulation of a certificate lacking `subjectAltName` entries, which is a common error scenario."},"warnings":[{"fix":"Ensure all certificates used for identity verification include `subjectAltName` entries corresponding to the expected hostnames or IP addresses. Regenerate certificates if necessary, or update your certificate issuance policies.","message":"Since version 23.1.0, `service-identity` completely ignores the `commonName` field in certificates for identity verification. Certificates relying solely on `commonName` will fail verification, requiring `subjectAltName` for host identity.","severity":"breaking","affected_versions":">=23.1.0"},{"fix":"Update `except` blocks to catch `service_identity.CertificateError` when handling cases where certificates might be missing `subjectAltName` entries.","message":"As of version 24.1.0, if a certificate lacks any `subjectAltName` entries, `service_identity.CertificateError` is raised instead of `service_identity.VerificationError`. This change improves clarity but may require updates to error handling logic in existing applications.","severity":"breaking","affected_versions":">=24.1.0"},{"fix":"Always import and use the `extract_patterns` function that matches the library used to load or create your certificate objects.","message":"Ensure you use the correct `extract_patterns` function based on your certificate object type. Use `service_identity.cryptography.extract_patterns` for `cryptography.x509.Certificate` objects and `service_identity.pyopenssl.extract_patterns` for `pyOpenSSL.SSL.X509` objects. Mixing these will lead to `TypeError` or `AttributeError`.","severity":"gotcha","affected_versions":"All"}],"env_vars":null,"last_verified":"2026-04-09T00:00:00.000Z","next_check":"2026-07-08T00:00:00.000Z"}