Begleitdienst · RFC-6960-Widerruf

OCSP-Responder — RFC-6960-Widerruf für CodeB-Signaturzertifikate.

Jeder CodeB-Tenant betreibt einen internen RFC-6960-OCSP-Responder unter POST /csc/v2/ocsp. Er beantwortet CertID-Anfragen für alle Zertifikate, die der Tenant ausstellt — Pro-Nutzer-Signaturzertifikate, das TSA-Responder-Zertifikat und die OIDC-/VCI-Aussteller-Zertifikate — und liefert eine vom eigenen Responder-Schlüssel signierte BasicOCSPResponse. Der Browser-Signer (sign.html) nutzt diesen Endpunkt, um id-aa-ets-revocationValues in jede PAdES-B-LT- und PAdES-B-LTA-Hülle einzubetten, sodass verlassende Parteien Signaturen offline prüfen können, nachdem das Signer-Zertifikat abgelaufen ist.

Umfangserklärung. Der Responder ist vom Tenant selbstsigniert — er ist kein qualifizierter OCSP-Responder nach Verordnung (EU) 910/2014. Er vervollständigt die lokale Vertrauensgeschichte für die interne PKI: CodeB-ausgestellte Zertifikate verweisen auf einen CodeB-signierten OCSP-Responder, und die gesamte Kette ist ohne externen Dienst prüfbar.

POST /csc/v2/ocsp

Vollständiges RFC-6960-Wire-Protokoll. Kein Bearer erforderlich — RFC 6960 §A.1 beschreibt OCSP-Anfrage/Antwort über HTTP und OCSP-Responder sind konventionell offen. Host-Rate-Limits gelten weiterhin (30 Anfragen pro Minute pro Aktion pro IP).

Anfrage

Content-Type:   application/ocsp-request
Body:           DER-kodierter OCSPRequest (RFC 6960 s4.1.1)

Antwort

Content-Type:   application/ocsp-response
Body:           DER-kodierter OCSPResponse (RFC 6960 s4.2.1)
                responseStatus INTEGER + optional BasicOCSPResponse

Beispiel

openssl ocsp -reqin request.ocsp -respout response.ocsp \
  -url https://phone.aloaha.com/csc/v2/ocsp -noverify -text

Welche Zertifikate abgedeckt sind

Beim Start und bei jedem Cache-Miss scannt der Responder vier Ordner unter App_Data/<tenant>/ und indexiert jede gefundene *.pfx oder *.pem:

  • csc-signer-certs/ — Pro-Nutzer-EC-P-256-Signaturzertifikate (Phase-1b-Credentials aus dem Browser-Signer)
  • signing-cert/ — der gemeinsame Tenant-weite Fallback-Signer (wenn Csc:PerUserCerts=false)
  • tsa-cert/ — das TSA-Responder-Zertifikat des Tenants (EKU id-kp-timeStamping)
  • vci/ — das PID-/-SD-JWT-VC-Aussteller-Zertifikat, das vci.ashx nutzt

Der Index wird nach issuerNameHash (SHA-1) + serialNumber geschlüsselt — genau die CertID, die ein Anfragender sendet. Ein Miss liefert certStatus = unknown gemäß RFC 6960 §4.2.2. Bewusste Wahl: lieber "wir kennen dieses Zertifikat nicht" als fälschlich "good".

Aktualisierung

Der Cache lädt bei jeder Anfrage neu, die älter als 60 Sekunden ist, und bei Tenant-Neustart. Neu ausgestellte Pro-Nutzer-Signaturzertifikate werden bei der nächsten Anfrage aufgenommen; es gibt keinen separaten "Publish-to-OCSP"-Schritt.

RFC-5019-Lightweight-Profil

Anfragen nutzen SHA-1-CertID-Hashes gemäß RFC 5019 für die Interop mit Standard-OCSP-Clients. Der Responder normalisiert intern zwischen SHA-256 und SHA-1, sodass sowohl RFC-6960- als auch RFC-5019-Clients gültige Antworten erhalten.

Nonce-Erweiterung (RFC 6960 §4.4.1) wird gespiegelt, wenn vorhanden. Antworten werden pro Anfrage frisch gebaut (kein Caching signierter Antworten), sodass producedAt stets die Echtzeit widerspiegelt.

Responder-Schlüssel und -Zertifikat

Der Responder signiert mit einem EC-P-256-Schlüssel per ECDSA-mit-SHA-256 (1.2.840.10045.4.3.2). Das certs [0]-Element bettet das eigene Responder-Zertifikat ein, damit Verifier die Kette offline aufbauen können.

Delegierte Signierung

Standardmäßig ist der Responder die Tenant-CA: ResponderID.byKey zeigt auf den SubjectPublicKeyInfo-Hash der Tenant-CA, und diese signiert direkt. Dies erfüllt RFC 6960 §4.2.2.2 trivial, weil CA- und Responder-Schlüssel identisch sind. Ein künftiges Release wird über Ocsp:ResponderCert=<pfad> ein separates delegiertes Responder-Zertifikat ermöglichen (EKU id-kp-OCSPSigning).

Auto-Erzeugung

Fehlt App_Data/<tenant>/signing-cert/tenant-ca.pfx beim Start, erzeugt der Tenant eine frische EC-P-256-CA (5 Jahre Gültigkeit, BasicConstraints CA:TRUE critical, KeyUsage keyCertSign+cRLSign+digitalSignature).

Woher der Widerruf-Zustand kommt

Widerruf ist eine flache Datei: App_Data/<tenant>/csc-revoked-serials.json. Jeder Eintrag ist {serial_hex, reason, revoked_at}. Der Responder prüft diese Liste vor der Antwort; Treffer liefert certStatus = revoked mit revocationTime; Miss liefert good für bekannte Zertifikate und unknown für unbekannte.

Zertifikat widerrufen

POST /admin.ashx?action=csc-revoke-serial
Authorization: Bearer <admin token>
Content-Type: application/json

{ "serial": "00edf255b159a07145",
  "reason": "keyCompromise",
  "revoked_at": "2026-07-27T18:31:19Z" }

Widerrufsgründe

Nach RFC 5280 §5.3.1: unspecified (0), keyCompromise (1), cACompromise (2), affiliationChanged (3), superseded (4), cessationOfOperation (5), certificateHold (6, umkehrbar), privilegeWithdrawn (9), aACompromise (10).

Observability und Rate Limiting

Jede OCSP-Anfrage emittiert Diagnose-Trace-Zeilen:

[CSC-OCSP-DIAG] tenant=<t> ct=application/ocsp-request len=76 issuerHash8=... serialHex=00edf255...
[CSC-OCSP-DIAG] tenant=<t> cache index=42 hit=1 status=good producedAt=2026-07-27T18:31:19Z
[METRIC] csc.ocsp.answered tenant=<t> status=good cert_source=csc-signer-certs

Metrik-Tags: status = good|revoked|unknown; cert_source = einer der vier gescannten Ordner. Ablehnungen emittieren [METRIC] csc.ocsp.rejected reason=... abgestimmt auf die sechs RFC-6960-responseStatus-Codes.

Standards & Verweise