====== RevocationExtensions Class ====== Extension methods for checking certificate revocation. ---- ===== Definition ===== namespace WvdS.System.Security.Cryptography.X509Certificates; public static class RevocationExtensions ---- ===== Methods ===== ^ Method ^ Description ^ | IsRevoked | Checks if a certificate is revoked | | FetchCrlAsync | Downloads CRL from URL (from certificate extension) | | CheckRevocationAsync | Combined: Load CRL and check revocation | | GetCrlDistributionPoints | Extracts CRL URLs from certificate | | GetOcspUrls | Extracts OCSP URLs from certificate | ---- ===== Checking Revocation ===== **With existing CRL:** using System.Security.Cryptography.X509Certificates; using WvdS.System.Security.Cryptography.X509Certificates; var certificate = new X509Certificate2("user.cer"); byte[] crlData = File.ReadAllBytes("ca.crl"); var caCert = new X509Certificate2("ca.cer"); // Check with signature verification RevocationResult result = certificate.IsRevoked(crlData, caCert, CryptoMode.Hybrid); if (result.Success) { if (result.IsRevoked) { Console.WriteLine($"Certificate revoked on: {result.RevocationDate}"); Console.WriteLine($"Reason: {result.Reason}"); } else { Console.WriteLine("Certificate is valid"); } } else { Console.WriteLine($"Error: {result.ErrorMessage}"); } **Automatically load CRL:** // Loads CRL from URL in the certificate's CDP extension RevocationResult result = await certificate.CheckRevocationAsync( caCert, mode: CryptoMode.Hybrid); ---- ===== Loading CRL ===== // Only load CRL, without checking byte[]? crlData = await certificate.FetchCrlAsync(); if (crlData != null) { File.WriteAllBytes("downloaded.crl", crlData); } **With custom HttpClient:** using var httpClient = new HttpClient(); httpClient.Timeout = TimeSpan.FromSeconds(10); byte[]? crlData = await certificate.FetchCrlAsync(httpClient); ---- ===== Reading CRL Distribution Points ===== IReadOnlyList crlUrls = certificate.GetCrlDistributionPoints(); foreach (var url in crlUrls) { Console.WriteLine($"CRL URL: {url}"); } // Quick check bool hasCdp = certificate.HasCrlDistributionPoints(); ---- ===== Reading OCSP URLs ===== IReadOnlyList ocspUrls = certificate.GetOcspUrls(); foreach (var url in ocspUrls) { Console.WriteLine($"OCSP Responder: {url}"); } // Quick check bool hasOcsp = certificate.HasOcspUrls(); ---- ===== RevocationResult Class ===== ^ Property ^ Type ^ Description ^ | ''IsRevoked'' | bool | Certificate is revoked | | ''RevocationDate'' | DateTimeOffset? | Time of revocation | | ''Reason'' | CrlReason? | Revocation reason | | ''CrlVerified'' | bool | CRL signature was verified | | ''ErrorMessage'' | string? | Error message (if check failed) | | ''Success'' | bool | Check was successful | ---- ===== CRL Cache ===== For frequent checks with automatic caching: using var cache = new CrlCache(defaultCacheDuration: TimeSpan.FromHours(1)); // Check with automatic CRL caching RevocationResult result1 = await cache.CheckRevocationAsync(cert1, caCert); RevocationResult result2 = await cache.CheckRevocationAsync(cert2, caCert); // CRL from cache // Clear cache cache.Clear(); **With custom HttpClient:** using var httpClient = new HttpClient(); using var cache = new CrlCache(httpClient, TimeSpan.FromMinutes(30)); // Check multiple certificates foreach (var cert in certificates) { var result = await cache.CheckRevocationAsync(cert, caCert, CryptoMode.Hybrid); // ... } ---- ===== Integration with X509Chain ===== For complete chain validation with CRL checking: using var chain = new X509Chain(); chain.ChainPolicy.RevocationMode = X509RevocationMode.Online; chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain; bool valid = chain.Build(certificate, CryptoMode.Hybrid); if (!valid) { foreach (var status in chain.ChainStatus) { if (status.Status == X509ChainStatusFlags.Revoked) { Console.WriteLine("Certificate in chain revoked"); } } } ---- ===== Offline Checking ===== For air-gapped systems without network access: // Download CRLs in advance and store var crlFiles = new Dictionary { ["CN=Root CA"] = File.ReadAllBytes("root.crl"), ["CN=Issuing CA"] = File.ReadAllBytes("issuing.crl") }; // Offline check RevocationResult result = certificate.IsRevoked(crlFiles["CN=Issuing CA"], caCert); ---- ===== Best Practices ===== * **Enable CRL caching:** Use ''CrlCache'' for repeated checks * **Set timeouts:** Configure HttpClient timeouts for network operations * **Implement fallback:** Check OCSP when CRL is not available * **Offline copies:** Keep local CRL copies for critical systems ---- ===== See Also ===== * [[.:certificaterevocationlistextensions|CertificateRevocationListExtensions]] - Creating CRLs * [[.:x509chainextensions|X509ChainExtensions]] - Chain validation * [[en:int:pqcrypt:konzepte:revocation|Revocation Concept]] ---- //Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional// {{tag>crl revocation ocsp}}