Scenario 5.3: Revocation Check

Category: Validation & Trust
Complexity: * (Medium)
Prerequisites: Certificate with CDP/OCSP
Estimated Time: 10-15 minutes </WRAP> —- ===== Description ===== This scenario describes checking the revocation status of a certificate using CRL (Certificate Revocation List) or OCSP (Online Certificate Status Protocol). Methods: ^ Method ^ Advantages ^ Disadvantages ^ | CRL | Offline capable, batch | Large files, delay | | OCSP | Real-time, small responses | Online dependency | | OCSP Stapling | Privacy, performance | Server configuration | —- ===== Workflow ===== <mermaid> flowchart TD CERT[Check certificate] –> HAS_OCSP{OCSP URL?} HAS_OCSP –>|Yes| OCSP[OCSP request] HAS_OCSP –>|No| CRL[Download CRL] OCSP –> OCSP_CHECK{Status?} CRL –> CRL_CHECK{In CRL?} OCSP_CHECK –>|good| OK[Not revoked] OCSP_CHECK –>|revoked| REVOKED[Revoked] OCSP_CHECK –>|unknown| CRL CRL_CHECK –>|No| OK CRL_CHECK –>|Yes| REVOKED style OK fill:#e8f5e9 style REVOKED fill:#ffebee </mermaid> —- ===== Code Example: OCSP Check ===== <code csharp> using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ; using System.Security.Cryptography.X509Certificates; using var ctx = PqCryptoContext.Initialize(); Load certificate var cert = ctx.LoadCertificate(„server.crt.pem“); var issuer = ctx.LoadCertificate(„intermediate-ca.crt.pem“); Extract OCSP URL from certificate var ocspUrl = ctx.GetOcspUrl(cert); if (!string.IsNullOrEmpty(ocspUrl)) { Create OCSP request var ocspRequest = ctx.CreateOcspRequest(cert, issuer); Send OCSP request using var http = new HttpClient(); http.DefaultRequestHeaders.Add(„Content-Type“, „application/ocsp-request“); var response = await http.PostAsync(ocspUrl, new ByteArrayContent(ocspRequest)); var ocspResponseBytes = await response.Content.ReadAsByteArrayAsync(); Parse OCSP response var status = ctx.ParseOcspResponse(ocspResponseBytes, cert, issuer); Console.WriteLine($„OCSP Status: {status.Status}“); Console.WriteLine($„ Produced: {status.ProducedAt}“); Console.WriteLine($„ Valid until: {status.NextUpdate}“); if (status.Status == OcspStatus.Revoked) { Console.WriteLine($„ Revoked: {status.RevocationTime}“); Console.WriteLine($„ Reason: {status.RevocationReason}“); } } </code> —- ===== Code Example: CRL Check ===== <code csharp> public class CrlChecker { private readonly Dictionary<string, CrlCache> _crlCache = new(); public async Task<RevocationStatus> CheckCrl(X509Certificate2 cert, X509Certificate2 issuer) { using var ctx = PqCryptoContext.Initialize(); Extract CDP URL from certificate var cdpUrl = ctx.GetCrlDistributionPoint(cert); if (string.IsNullOrEmpty(cdpUrl)) { return new RevocationStatus { Status = RevocationStatusCode.Unknown }; } Get CRL from cache or download var crl = await GetOrDownloadCrl(cdpUrl, issuer); Search for serial number in CRL var serialNumber = cert.SerialNumber; var entry = crl.Entries.FirstOrDefault(e ⇒ e.SerialNumber.Equals(serialNumber, StringComparison.OrdinalIgnoreCase)); if (entry != null) { return new RevocationStatus { Status = RevocationStatusCode.Revoked, RevocationTime = entry.RevocationDate, Reason = entry.Reason }; } return new RevocationStatus { Status = RevocationStatusCode.Good, NextUpdate = crl.NextUpdate }; } private async Task<ParsedCrl> GetOrDownloadCrl(string cdpUrl, X509Certificate2 issuer) { Check cache if (_crlCache.TryGetValue(cdpUrl, out var cached)) { if (cached.NextUpdate > DateTime.UtcNow) { return cached.Crl; } } Download CRL using var http = new HttpClient(); var crlBytes = await http.GetByteArrayAsync(cdpUrl); Parse and verify CRL using var ctx = PqCryptoContext.Initialize(); var crl = ctx.ParseCrl(crlBytes); Verify signature if (!ctx.VerifyCrlSignature(crl, issuer)) { throw new CryptographicException(„CRL signature invalid“); } Update cache _crlCache[cdpUrl] = new CrlCache { Crl = crl, NextUpdate = crl.NextUpdate }; return crl; } } </code> —- ===== OCSP Stapling ===== <code csharp> public class OcspStapling { Server-side: Pre-fetch OCSP response public async Task<byte[]> GetStapledOcspResponse( X509Certificate2 serverCert, X509Certificate2 issuer) { using var ctx = PqCryptoContext.Initialize(); var ocspUrl = ctx.GetOcspUrl(serverCert); var request = ctx.CreateOcspRequest(serverCert, issuer); using var http = new HttpClient(); var response = await http.PostAsync(ocspUrl, new ByteArrayContent(request)); return await response.Content.ReadAsByteArrayAsync(); } Client-side: Validate stapled response public OcspStatus ValidateStapledResponse( byte[] stapledResponse, X509Certificate2 serverCert, X509Certificate2 issuer) { using var ctx = PqCryptoContext.Initialize(); var status = ctx.ParseOcspResponse(stapledResponse, serverCert, issuer); Check freshness if (status.ProducedAt < DateTime.UtcNow.AddHours(-24)) { throw new CryptographicException(„OCSP response too old“); } return status; } } </code> —- ===== .NET Chain-based Revocation Check ===== <code csharp> Simplest method: Use X509Chain var chain = new X509Chain(); chain.ChainPolicy.RevocationMode = X509RevocationMode.Online; chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain; chain.ChainPolicy.UrlRetrievalTimeout = TimeSpan.FromSeconds(15); Optional: Only CRL or only OCSP chain.ChainPolicy.RevocationMode = X509RevocationMode.Offline; Only cached CRLs bool isValid = chain.Build(cert); Extract revocation status from chain var revocationErrors = chain.ChainElements .SelectMany(e ⇒ e.ChainElementStatus) .Where(s ⇒ s.Status.HasFlag(X509ChainStatusFlags.Revoked) || s.Status.HasFlag(X509ChainStatusFlags.RevocationStatusUnknown)) .ToList(); if (revocationErrors.Any()) { foreach (var error in revocationErrors) { Console.WriteLine($„Revocation issue: {error.StatusInformation}“); } } </code> —- ===== Industry-Specific Requirements ===== ^ Industry ^ Method ^ Max. Delay ^ Fallback ^ | WebPKI | OCSP Must-Staple | Real-time | Soft-Fail | | Financial | OCSP + CRL | 4 hours | Hard-Fail | | Healthcare | CRL | 24 hours | Soft-Fail | | Energy/SCADA | CRL (Offline) | 7 days | Hard-Fail |

Soft-Fail vs Hard-Fail:

  • Soft-Fail: If unreachable → Accept certificate
  • Hard-Fail: If unreachable → Reject certificate

—- ===== Related Scenarios ===== ^ Relationship ^ Scenario ^ Description ^ | Prerequisite | 5.2 Chain Validation | Build chain | | Related | 6.1 Create CRL | Generate CRL | | Related | 6.2 OCSP Responder | Operate OCSP | —- « <- 5.2 Chain Validation | ^ Validation Overview | 5.4 Policy Validation -> »

—- Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional