~~NOTOC~~ ====== Szenario 6.3: Delta-CRL ====== **Kategorie:** [[.:start|Widerruf (Revocation)]] \\ **Komplexität:** ⭐⭐⭐⭐ (Hoch) \\ **Voraussetzungen:** Basis-CRL vorhanden \\ **Geschätzte Zeit:** 20-30 Minuten ---- ===== Beschreibung ===== Dieses Szenario beschreibt die **Erstellung von Delta-CRLs** (RFC 5280 §5.2.4). Delta-CRLs enthalten nur Änderungen seit der letzten Basis-CRL und ermöglichen effizientere Updates. **Vorteile:** * Kleinere Download-Größe * Häufigere Updates möglich * Reduzierte Bandbreite * Schnellere Propagation **Nachteile:** * Komplexere Implementierung * Basis-CRL muss verfügbar sein * Zusätzliche Infrastruktur ---- ===== Workflow ===== flowchart TD BASE[Basis-CRL] --> DELTA1[Delta-CRL 1] DELTA1 --> DELTA2[Delta-CRL 2] DELTA2 --> DELTA3[Delta-CRL 3] DELTA3 --> NEW_BASE[Neue Basis-CRL] NEW_BASE --> DELTA4[Delta-CRL 4] CLIENT[Client] --> |Download| BASE CLIENT --> |Updates| DELTA1 CLIENT --> |Updates| DELTA2 style BASE fill:#e3f2fd style NEW_BASE fill:#e3f2fd style DELTA1 fill:#fff3e0 style DELTA2 fill:#fff3e0 style DELTA3 fill:#fff3e0 style DELTA4 fill:#fff3e0 ---- ===== Code-Beispiel: Delta-CRL erstellen ===== using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ; using System.Numerics; using var ctx = PqCryptoContext.Initialize(); // CA laden var caCert = ctx.LoadCertificate("intermediate-ca.crt.pem"); var caKey = ctx.LoadPrivateKey("intermediate-ca.key.pem", "CaPassword!"); // Basis-CRL laden var baseCrl = ctx.ParseCrl(File.ReadAllBytes("intermediate-ca-base.crl")); var baseCrlNumber = baseCrl.CrlNumber; // Delta-CRL Builder var deltaCrlBuilder = new CertificateRevocationListBuilder(); // Nur NEUE Widerrufe seit Basis-CRL hinzufügen var newRevocations = GetRevocationsSince(baseCrl.ThisUpdate); foreach (var rev in newRevocations) { deltaCrlBuilder.AddEntry( rev.SerialNumber, rev.RevocationTime, rev.Reason ); } // Optional: Zertifikate aus "Hold" zurücknehmen var removedFromHold = GetRemovedFromHold(baseCrl.ThisUpdate); foreach (var serial in removedFromHold) { deltaCrlBuilder.AddEntry( serial, DateTimeOffset.UtcNow, X509RevocationReason.RemoveFromCrl // Code 8 ); } // Delta-CRL Extensions deltaCrlBuilder.AddExtension( oid: "2.5.29.27", // Delta CRL Indicator critical: true, value: EncodeDeltaCrlIndicator(baseCrlNumber) ); // Delta-CRL generieren byte[] deltaCrlBytes = deltaCrlBuilder.Build( issuerCertificate: caCert, crlNumber: baseCrlNumber + 10, // Delta-Nummern zwischen Basis-Nummern nextUpdate: DateTimeOffset.UtcNow.AddHours(4), // Häufiger als Basis hashAlgorithm: HashAlgorithmName.SHA256, mode: CryptoMode.Hybrid ); File.WriteAllBytes("intermediate-ca-delta.crl", deltaCrlBytes); Console.WriteLine($"Delta-CRL erstellt:"); Console.WriteLine($" Basis-CRL Number: {baseCrlNumber}"); Console.WriteLine($" Delta-CRL Number: {baseCrlNumber + 10}"); Console.WriteLine($" Neue Einträge: {newRevocations.Count}"); Console.WriteLine($" Removed from Hold: {removedFromHold.Count}"); ---- ===== Delta-CRL Indicator Extension ===== private byte[] EncodeDeltaCrlIndicator(BigInteger baseCrlNumber) { // Delta CRL Indicator ist einfach die Basis-CRL-Nummer als INTEGER var writer = new AsnWriter(AsnEncodingRules.DER); writer.WriteInteger(baseCrlNumber); return writer.Encode(); } ---- ===== Basis-CRL mit Delta-CRL-Support ===== // Basis-CRL muss auf Delta-CRLs verweisen var baseCrlBuilder = new CertificateRevocationListBuilder(); // Alle widerrufenen Zertifikate hinzufügen foreach (var rev in allRevocations) { baseCrlBuilder.AddEntry(rev.SerialNumber, rev.RevocationTime, rev.Reason); } // Freshest CRL Extension (verweist auf Delta-CRL) baseCrlBuilder.AddExtension( oid: "2.5.29.46", // Freshest CRL (Delta CRL Distribution Point) critical: false, value: EncodeFreshestCrl("http://crl.example.com/intermediate-delta.crl") ); byte[] baseCrlBytes = baseCrlBuilder.Build( issuerCertificate: caCert, crlNumber: BigInteger.Parse("1000"), nextUpdate: DateTimeOffset.UtcNow.AddDays(7), // Längere Gültigkeit hashAlgorithm: HashAlgorithmName.SHA256, mode: CryptoMode.Hybrid ); File.WriteAllBytes("intermediate-ca-base.crl", baseCrlBytes); ---- ===== Delta-CRL Client-seitige Verarbeitung ===== public class DeltaCrlProcessor { public CombinedRevocationList CombineCrls( byte[] baseCrlBytes, byte[] deltaCrlBytes, PqCryptoContext ctx) { var baseCrl = ctx.ParseCrl(baseCrlBytes); var deltaCrl = ctx.ParseCrl(deltaCrlBytes); // Prüfen ob Delta zur Basis passt var deltaIndicator = GetDeltaCrlIndicator(deltaCrl); if (deltaIndicator != baseCrl.CrlNumber) { throw new InvalidOperationException( $"Delta-CRL (Indicator: {deltaIndicator}) passt nicht zur Basis-CRL ({baseCrl.CrlNumber})" ); } // Kombinierte Liste erstellen var combined = new CombinedRevocationList { BaseCrlNumber = baseCrl.CrlNumber, DeltaCrlNumber = deltaCrl.CrlNumber, ThisUpdate = deltaCrl.ThisUpdate, // Delta ist aktueller NextUpdate = deltaCrl.NextUpdate, Entries = new Dictionary() }; // Basis-Einträge übernehmen foreach (var entry in baseCrl.Entries) { combined.Entries[entry.SerialNumber] = entry; } // Delta-Einträge anwenden foreach (var entry in deltaCrl.Entries) { if (entry.Reason == X509RevocationReason.RemoveFromCrl) { // Aus CRL entfernen (Hold aufgehoben) combined.Entries.Remove(entry.SerialNumber); } else { // Hinzufügen oder aktualisieren combined.Entries[entry.SerialNumber] = entry; } } return combined; } public bool IsRevoked(string serialNumber, CombinedRevocationList crl) { return crl.Entries.ContainsKey(serialNumber); } } ---- ===== Automatisierter Delta-CRL-Zyklus ===== public class DeltaCrlScheduler { private readonly TimeSpan _baseCrlInterval = TimeSpan.FromDays(7); private readonly TimeSpan _deltaCrlInterval = TimeSpan.FromHours(4); private BigInteger _currentBaseCrlNumber = 1000; private BigInteger _currentDeltaNumber = 0; public async Task RunScheduler(CancellationToken cancellationToken) { var lastBaseCrl = DateTimeOffset.UtcNow; while (!cancellationToken.IsCancellationRequested) { if (DateTimeOffset.UtcNow - lastBaseCrl >= _baseCrlInterval) { // Zeit für neue Basis-CRL await CreateBaseCrl(); lastBaseCrl = DateTimeOffset.UtcNow; _currentBaseCrlNumber += 100; _currentDeltaNumber = 0; } else { // Delta-CRL erstellen await CreateDeltaCrl(); _currentDeltaNumber++; } await Task.Delay(_deltaCrlInterval, cancellationToken); } } private async Task CreateBaseCrl() { Console.WriteLine($"Erstelle Basis-CRL #{_currentBaseCrlNumber}"); // ... Basis-CRL Logik } private async Task CreateDeltaCrl() { var deltaCrlNumber = _currentBaseCrlNumber + _currentDeltaNumber; Console.WriteLine($"Erstelle Delta-CRL #{deltaCrlNumber} (Basis: {_currentBaseCrlNumber})"); // ... Delta-CRL Logik } } ---- ===== Branchenspezifische Delta-CRL Zyklen ===== ^ Branche ^ Basis-CRL ^ Delta-CRL ^ Empfehlung ^ | **WebPKI** | 7 Tage | 4 Stunden | Optional, OCSP bevorzugt | | **Enterprise** | 24 Stunden | 1 Stunde | Empfohlen | | **Finanzsektor** | 12 Stunden | 15 Minuten | Pflicht | | **Energie/SCADA** | 7 Tage | 24 Stunden | Je nach Anbindung | ---- ===== Verwandte Szenarien ===== ^ Beziehung ^ Szenario ^ Beschreibung ^ | **Voraussetzung** | [[.:crl_erstellen|6.1 CRL erstellen]] | Basis-CRL | | **Alternative** | [[.:ocsp_responder|6.2 OCSP Responder]] | Echtzeit-Status | | **Verwandt** | [[de:int:pqcrypt:szenarien:validierung:revocation_check|5.3 Revocation Check]] | Client-Prüfung | ---- << [[.:ocsp_responder|← 6.2 OCSP Responder]] | [[.:start|↑ Widerruf-Übersicht]] | [[.:zertifikat_widerrufen|6.4 Zertifikat widerrufen →]] >> {{tag>szenario widerruf delta-crl inkrementell performance}} ---- //Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional//