====== 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}}