{"id":4660,"library":"ocspresponder","title":"OCSP Responder Framework","description":"ocspresponder is an RFC 6960 compliant OCSP Responder framework written in Python 3.5+. It provides a foundation for building an OCSP responder service, leveraging the ocspbuilder and asn1crypto libraries for cryptographic operations, and using Bottle for the HTTP server. It is currently in an alpha development stage (version 0.5.0) and is not recommended for production use.","status":"active","version":"0.5.0","language":"en","source_language":"en","source_url":"https://github.com/threema-ch/ocspresponder/","tags":["security","PKI","OCSP","cryptography","certificate revocation"],"install":[{"cmd":"pip install ocspresponder","lang":"bash","label":"Install latest version"}],"dependencies":[{"reason":"Core dependency for building OCSP responses.","package":"ocspbuilder"},{"reason":"Core dependency for ASN.1 parsing and serialization.","package":"asn1crypto"},{"reason":"HTTP server framework used by ocspresponder.","package":"Bottle"},{"reason":"Commonly used for cryptographic operations in Python PKI, implicitly relied upon by ocspbuilder/asn1crypto or directly in custom implementations.","package":"cryptography","optional":true},{"reason":"Required if using a MySQL database for certificate status and retrieval.","package":"mysql-connector-python","optional":true}],"imports":[{"symbol":"OCSPResponder","correct":"from ocspresponder import OCSPResponder"},{"symbol":"CertificateStatus","correct":"from ocspresponder import CertificateStatus"}],"quickstart":{"code":"import os\nfrom datetime import datetime, timedelta\nfrom typing import Optional\nfrom ocspresponder import OCSPResponder, CertificateStatus\nfrom cryptography.hazmat.primitives import serialization, hashes\nfrom cryptography.hazmat.primitives.asymmetric import rsa\nfrom cryptography.x509.oid import NameOID\nfrom cryptography import x509\nfrom ocspbuilder import OCSPResponseBuilder\n\n# NOTE: This quickstart uses dummy certificates and keys for demonstration.\n# In a real scenario, these would be loaded from secure storage.\n# Also, ocspresponder is currently alpha; not for production use.\n\n# Generate dummy CA and OCSP responder certificates/keys for demonstration\ndef generate_dummy_certs():\n    ca_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)\n    ca_subject = x509.Name([\n        x509.NameAttribute(NameOID.COUNTRY_NAME, u\"US\"),\n        x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u\"California\"),\n        x509.NameAttribute(NameOID.LOCALITY_NAME, u\"San Francisco\"),\n        x509.NameAttribute(NameOID.ORGANIZATION_NAME, u\"My CA\"),\n        x509.NameAttribute(NameOID.COMMON_NAME, u\"My Root CA\"),\n    ])\n    ca_cert = (\n        x509.CertificateBuilder()\n        .subject_name(ca_subject)\n        .issuer_name(ca_subject)\n        .public_key(ca_key.public_key())\n        .serial_number(x509.random_serial_number())\n        .not_valid_before(datetime.utcnow())\n        .not_valid_after(datetime.utcnow() + timedelta(days=365))\n        .add_extension(x509.BasicConstraints(ca=True, path_length=None), critical=True)\n        .sign(ca_key, hashes.SHA256())\n    )\n\n    ocsp_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)\n    ocsp_subject = x509.Name([\n        x509.NameAttribute(NameOID.COUNTRY_NAME, u\"US\"),\n        x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u\"California\"),\n        x509.NameAttribute(NameOID.LOCALITY_NAME, u\"San Francisco\"),\n        x509.NameAttribute(NameOID.ORGANIZATION_NAME, u\"My OCSP Responder\"),\n        x509.NameAttribute(NameOID.COMMON_NAME, u\"ocsp.example.com\"),\n    ])\n    ocsp_cert = (\n        x509.CertificateBuilder()\n        .subject_name(ocsp_subject)\n        .issuer_name(ca_subject)\n        .public_key(ocsp_key.public_key())\n        .serial_number(x509.random_serial_number())\n        .not_valid_before(datetime.utcnow())\n        .not_valid_after(datetime.utcnow() + timedelta(days=90))\n        .add_extension(x509.BasicConstraints(ca=False, path_length=None), critical=True)\n        .add_extension(x509.ExtendedKeyUsage([x509.ExtendedKeyUsageOID.OCSP_SIGNING]), critical=True)\n        .sign(ca_key, hashes.SHA256())\n    )\n    \n    return ca_cert, ca_key, ocsp_cert, ocsp_key\n\nCA_CERT, CA_KEY, OCSP_CERT, OCSP_KEY = generate_dummy_certs()\n\n# Example data store for certificate statuses\n# In a real application, this would be a database or other persistent store.\ndummy_cert_db = {\n    12345: (CertificateStatus.good, None, CA_CERT.public_bytes(serialization.Encoding.PEM)),\n    67890: (CertificateStatus.revoked, datetime.utcnow() - timedelta(days=5), CA_CERT.public_bytes(serialization.Encoding.PEM))\n}\n\n# Custom function to validate a certificate serial number\ndef validate_cert_status(serial: int) -> (CertificateStatus, Optional[datetime]):\n    status, revoked_at, _ = dummy_cert_db.get(serial, (CertificateStatus.unknown, None, None))\n    return status, revoked_at\n\n# Custom function to retrieve the issuer certificate for a given serial\ndef get_issuer_certificate(serial: int) -> Optional[bytes]:\n    # In a real scenario, you'd find the actual issuer of the certificate\n    # identified by 'serial'. For this dummy example, we return the CA_CERT.\n    _, _, issuer_cert_pem = dummy_cert_db.get(serial, (None, None, None))\n    return issuer_cert_pem\n\n# Instantiate the OCSP Responder\nresponder = OCSPResponder(\n    issuer_cert=CA_CERT.public_bytes(serialization.Encoding.PEM),\n    ocsp_cert=OCSP_CERT.public_bytes(serialization.Encoding.PEM),\n    ocsp_key=OCSP_KEY.private_bytes(\n        encoding=serialization.Encoding.PEM,\n        format=serialization.PrivateFormat.PKCS8,\n        encryption_algorithm=serialization.NoEncryption()\n    ),\n    retrieve_certificate_status=validate_cert_status,\n    retrieve_issuer_certificate=get_issuer_certificate\n)\n\nprint(\"OCSPResponder instantiated successfully.\")\nprint(\"This is a framework. To run a server, you would integrate this into an HTTP server (e.g., Bottle).\")\nprint(\"For example, with Bottle:\")\nprint(\"from bottle import run, request, post\")\nprint(\"@post('/ocsp')\")\nprint(\"def ocsp_service():\")\nprint(\"    return responder.handle_ocsp_request(request.body.read())\")\nprint(\"run(host='localhost', port=8080)\")\n","lang":"python","description":"This quickstart demonstrates how to instantiate the `OCSPResponder` class. It includes dummy certificate generation and simple functions for validating certificate status and retrieving issuer certificates. In a real application, `issuer_cert`, `ocsp_cert`, and `ocsp_key` would be loaded securely, and `retrieve_certificate_status` and `retrieve_issuer_certificate` would interact with a robust certificate database. The example also shows how it would be integrated into a Bottle web server."},"warnings":[{"fix":"Use for experimental purposes only. Monitor the project's development for a stable release suitable for production environments.","message":"The `ocspresponder` library is currently in 'Alpha' status and explicitly marked 'Don't use for production yet' on its PyPI page. Its API or internal workings may change significantly.","severity":"breaking","affected_versions":"0.5.0 and earlier"},{"fix":"Evaluate your specific use case to determine if OCSP remains a suitable revocation mechanism. Consider the implications of browsers and other clients potentially reducing or ceasing OCSP checks by 2025.","message":"Major Certificate Authorities (e.g., Let's Encrypt) are phasing out OCSP support in favor of Certificate Revocation Lists (CRLs) due to privacy concerns and operational simplicity. While `ocspresponder` provides OCSP functionality, the broader ecosystem's shift may impact its long-term utility.","severity":"gotcha","affected_versions":"All versions of ocspresponder, as this is an external ecosystem change."},{"fix":"Design and implement these custom functions carefully, ensuring robust database interaction, error handling, and security best practices for handling certificate status and issuer information.","message":"The library requires you to implement custom functions for `retrieve_certificate_status` and `retrieve_issuer_certificate`. These functions are critical for the responder's operation and must securely access and manage your certificate revocation data.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Implement OCSP stapling where possible, or ensure the communication channel to the OCSP responder is secured (e.g., within a trusted network or via HTTPS for the responder itself, although the OCSP request inside is often not encrypted). Be aware of the privacy implications of direct OCSP queries.","message":"OCSP requests are typically sent over plain HTTP and can be vulnerable to interception and modification if not properly secured (e.g., through OCSP stapling or secure transport). Attackers could alter responses or block them, potentially leading to clients accepting revoked certificates.","severity":"gotcha","affected_versions":"All versions, as this is a protocol-level concern."}],"env_vars":null,"last_verified":"2026-04-12T00:00:00.000Z","next_check":"2026-07-11T00:00:00.000Z"}