Scenario 6.2: OCSP Responder
Category: Revocation
Complexity: ⭐⭐⭐⭐ (High)
Prerequisites: CA infrastructure, OCSP signing certificate
Estimated Time: 30-45 Minutes
Description
This scenario describes the implementation of an OCSP Responder (Online Certificate Status Protocol, RFC 6960). OCSP enables real-time certificate status verification.
Advantages over CRL:
- Real-time status
- Smaller responses
- No complete download
- Privacy (only one certificate checked)
Workflow
flowchart LR
CLIENT[Client] -->|OCSP Request| RESPONDER[OCSP Responder]
RESPONDER --> DB[(Revocation DB)]
RESPONDER -->|OCSP Response| CLIENT
subgraph Response
GOOD[good]
REVOKED[revoked]
UNKNOWN[unknown]
end
style RESPONDER fill:#e8f5e9
Code Example: Create OCSP Request
using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ; using System.Security.Cryptography; using var ctx = PqCryptoContext.Initialize(); // Load certificate to check and issuer var cert = ctx.LoadCertificate("server.crt.pem"); var issuer = ctx.LoadCertificate("intermediate-ca.crt.pem"); // Create OCSP request var ocspRequest = ctx.CreateOcspRequest( certificate: cert, issuer: issuer, hashAlgorithm: HashAlgorithmName.SHA256, nonce: true // Replay protection ); // Request as DER byte[] requestBytes = ocspRequest.Encode(); // Send request using var http = new HttpClient(); var content = new ByteArrayContent(requestBytes); content.Headers.ContentType = new MediaTypeHeaderValue("application/ocsp-request"); var ocspUrl = ctx.GetOcspUrl(cert); // Read AIA extension var response = await http.PostAsync(ocspUrl, content); var responseBytes = await response.Content.ReadAsByteArrayAsync(); // Parse response var status = ctx.ParseOcspResponse(responseBytes, cert, issuer); Console.WriteLine($"OCSP Status: {status.Status}"); Console.WriteLine($" Produced: {status.ProducedAt}"); Console.WriteLine($" This Update: {status.ThisUpdate}"); Console.WriteLine($" Next Update: {status.NextUpdate}");
Code Example: Implement OCSP Responder
public class OcspResponder { private readonly X509Certificate2 _responderCert; private readonly AsymmetricAlgorithm _responderKey; private readonly IRevocationDatabase _revocationDb; private readonly PqCryptoContext _ctx; public OcspResponder( X509Certificate2 responderCert, AsymmetricAlgorithm responderKey, IRevocationDatabase revocationDb) { _responderCert = responderCert; _responderKey = responderKey; _revocationDb = revocationDb; _ctx = PqCryptoContext.Initialize(); } public byte[] ProcessRequest(byte[] requestBytes) { try { // Parse request var request = _ctx.ParseOcspRequest(requestBytes); // Response builder var responseBuilder = new OcspResponseBuilder(); foreach (var certId in request.CertificateIds) { // Look up status in database var revocationInfo = _revocationDb.GetRevocationStatus( certId.IssuerNameHash, certId.IssuerKeyHash, certId.SerialNumber ); if (revocationInfo == null) { // Unknown certificate responseBuilder.AddStatus(certId, OcspCertStatus.Unknown); } else if (revocationInfo.IsRevoked) { // Revoked responseBuilder.AddStatus( certId, OcspCertStatus.Revoked, revocationInfo.RevocationTime, revocationInfo.RevocationReason ); } else { // Valid responseBuilder.AddStatus(certId, OcspCertStatus.Good); } } // Sign response return responseBuilder.Build( responderCert: _responderCert, responderKey: _responderKey, producedAt: DateTimeOffset.UtcNow, nextUpdate: DateTimeOffset.UtcNow.AddMinutes(5), nonce: request.Nonce, mode: CryptoMode.Hybrid ); } catch (Exception ex) { // Internal Error Response return BuildErrorResponse(OcspResponseStatus.InternalError); } } private byte[] BuildErrorResponse(OcspResponseStatus status) { return _ctx.BuildOcspErrorResponse(status); } }
Create OCSP Responder Certificate
// OCSP Responder needs special certificate using var ocspKey = ctx.GenerateKeyPair(PqAlgorithm.MlDsa65); var dn = new DnBuilder() .AddCN("OCSP Responder - Example CA") .AddO("Example GmbH") .AddC("DE") .Build(); var csr = ctx.CreateCertificateRequest(ocspKey, dn); var ocspCert = ctx.IssueCertificate( csr, issuerCert: caCert, issuerKey: caKey, validDays: 30, // Short validity for OCSP responder extensions: new ExtBuilder() .BasicConstraints(ca: false, critical: true) // OCSP Signing Key Usage .KeyUsage(KeyUsageFlags.DigitalSignature, critical: true) // OCSP Signing EKU .ExtendedKeyUsage(ExtKeyUsage.OcspSigning) // id-pkix-ocsp-nocheck Extension (no revocation check for responder) .OcspNoCheck() .SubjectKeyIdentifier(ocspKey.PublicKey) .AuthorityKeyIdentifier(caCert) .Build() ); ocspCert.ToPemFile("ocsp-responder.crt.pem"); ocspKey.ToEncryptedPemFile("ocsp-responder.key.pem", "OcspPassword!");
ASP.NET Core OCSP Endpoint
[ApiController] [Route("ocsp")] public class OcspController : ControllerBase { private readonly OcspResponder _responder; public OcspController(OcspResponder responder) { _responder = responder; } // POST /ocsp [HttpPost] [Consumes("application/ocsp-request")] [Produces("application/ocsp-response")] public IActionResult Post() { using var ms = new MemoryStream(); Request.Body.CopyTo(ms); var requestBytes = ms.ToArray(); var responseBytes = _responder.ProcessRequest(requestBytes); return File(responseBytes, "application/ocsp-response"); } // GET /ocsp/{base64-request} (for OCSP GET) [HttpGet("{encodedRequest}")] [Produces("application/ocsp-response")] public IActionResult Get(string encodedRequest) { var requestBytes = Convert.FromBase64String( Uri.UnescapeDataString(encodedRequest) ); var responseBytes = _responder.ProcessRequest(requestBytes); return File(responseBytes, "application/ocsp-response"); } }
OCSP Response Status
| Status | HTTP | Meaning |
|---|---|---|
| successful | 200 | Request processed |
| malformedRequest | 200 | Invalid request |
| internalError | 200 | Server error |
| tryLater | 200 | Temporarily unavailable |
| sigRequired | 200 | Signature required |
| unauthorized | 200 | Not authorized |
Important: OCSP always returns HTTP 200! The status is encoded in the response.
Industry-Specific OCSP Requirements
| Industry | Response Caching | Stapling | High Availability |
|---|---|---|---|
| WebPKI | Maximum 10 min | Mandatory | 99.9% |
| Enterprise | Maximum 1 hour | Recommended | Per SLA |
| Financial Sector | Maximum 5 min | Mandatory | 99.99% |
| Healthcare | Maximum 1 hour | Optional | 99.9% |
Related Scenarios
| Relationship | Scenario | Description |
|---|---|---|
| Alternative | 6.1 Create CRL | Offline verification |
| Related | 5.3 Revocation Check | Client-side verification |
| Prerequisite | 6.4 Revoke Certificate | Revocation process |
« ← 6.1 Create CRL | ↑ Revocation Overview | 6.3 Delta CRL → »
Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional
Zuletzt geändert: on 2026/01/30 at 06:56 AM