{"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.","language":"python","status":"active","last_verified":"Fri May 15","install":{"commands":["pip install ocspresponder"],"cli":null},"imports":["from ocspresponder import OCSPResponder","from ocspresponder import CertificateStatus"],"auth":{"required":false,"env_vars":[]},"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.","tag":null,"tag_description":null,"last_tested":null,"results":[]},"compatibility":{"tag":null,"tag_description":null,"last_tested":"2026-05-15","installed_version":"0.5.0","pypi_latest":"0.5.0","is_stale":false,"summary":{"python_range":"3.10–3.9","success_rate":100,"avg_install_s":1.9,"avg_import_s":0.27,"wheel_type":"wheel"},"results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"ocspresponder","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"broken","install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":"21.1M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"ocspresponder","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":1.9,"import_time_s":0.22,"mem_mb":8.8,"disk_size":"22M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"ocspresponder","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"broken","install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":"23.5M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"ocspresponder","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"noisy","install_time_s":2,"import_time_s":0.35,"mem_mb":10,"disk_size":"24M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"ocspresponder","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"broken","install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":"15.3M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"ocspresponder","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"noisy","install_time_s":1.9,"import_time_s":0.32,"mem_mb":9.7,"disk_size":"16M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"ocspresponder","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"broken","install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":"15.0M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"ocspresponder","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"broken","install_time_s":1.8,"import_time_s":null,"mem_mb":null,"disk_size":"16M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"ocspresponder","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"broken","install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":"20.6M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"ocspresponder","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":2.1,"import_time_s":0.19,"mem_mb":8.6,"disk_size":"21M"}]}}