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