Szenario 6.1: CRL erstellen

Kategorie: Widerruf (Revocation)
Komplexität: ⭐⭐⭐ (Mittel)
Voraussetzungen: CA-Zertifikat und -Schlüssel
Geschätzte Zeit: 15-20 Minuten


Beschreibung

Dieses Szenario beschreibt die Erstellung einer Certificate Revocation List (CRL) nach RFC 5280. CRLs sind signierte Listen widerrufener Zertifikate, die von CAs veröffentlicht werden.

CRL-Felder:


Workflow

flowchart LR REV[Widerrufene Zertifikate] --> BUILD[CRL Builder] BUILD --> SIGN[Mit CA signieren] SIGN --> PUBLISH[Veröffentlichen] PUBLISH --> CDP[CDP URL aktualisieren] style SIGN fill:#e8f5e9


Code-Beispiel (C#)

using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ;
using System.Security.Cryptography.X509Certificates;
 
using var ctx = PqCryptoContext.Initialize();
 
// CA laden
var caCert = ctx.LoadCertificate("intermediate-ca.crt.pem");
var caKey = ctx.LoadPrivateKey("intermediate-ca.key.pem", "CaPassword!");
 
// CRL Builder erstellen
var crlBuilder = new CertificateRevocationListBuilder();
 
// Widerrufene Zertifikate hinzufügen
crlBuilder.AddEntry(
    serialNumber: new byte[] { 0x01, 0x02, 0x03 },
    revocationTime: new DateTimeOffset(2024, 6, 15, 10, 30, 0, TimeSpan.Zero),
    reason: X509RevocationReason.KeyCompromise
);
 
crlBuilder.AddEntry(
    serialNumber: new byte[] { 0x01, 0x02, 0x04 },
    revocationTime: DateTimeOffset.UtcNow.AddDays(-7),
    reason: X509RevocationReason.CessationOfOperation
);
 
// CRL generieren
byte[] crlBytes = crlBuilder.Build(
    issuerCertificate: caCert,
    crlNumber: BigInteger.Parse("1000"),
    nextUpdate: DateTimeOffset.UtcNow.AddDays(7),
    hashAlgorithm: HashAlgorithmName.SHA256,
    rsaSignaturePadding: null,  // Für PQ nicht relevant
    mode: CryptoMode.Hybrid
);
 
// CRL speichern
File.WriteAllBytes("intermediate-ca.crl", crlBytes);
 
// CRL zu PEM konvertieren
var crlPem = ctx.ToPem(crlBytes, "X509 CRL");
File.WriteAllText("intermediate-ca.crl.pem", crlPem);
 
Console.WriteLine("CRL erstellt:");
Console.WriteLine($"  Einträge: {crlBuilder.Entries.Count}");
Console.WriteLine($"  CRL Number: 1000");
Console.WriteLine($"  Next Update: {DateTimeOffset.UtcNow.AddDays(7):yyyy-MM-dd}");

CRL aus bestehender CRL aktualisieren

public class CrlUpdater
{
    public byte[] UpdateCrl(
        byte[] existingCrl,
        X509Certificate2 caCert,
        AsymmetricAlgorithm caKey,
        IEnumerable<CrlEntry>? newEntries = null)
    {
        using var ctx = PqCryptoContext.Initialize();
 
        // Bestehende CRL parsen
        var parsedCrl = ctx.ParseCrl(existingCrl);
 
        // Neuen Builder mit bestehenden Einträgen
        var builder = new CertificateRevocationListBuilder();
 
        foreach (var entry in parsedCrl.Entries)
        {
            builder.AddEntry(entry.SerialNumber, entry.RevocationTime, entry.Reason);
        }
 
        // Neue Einträge hinzufügen
        if (newEntries != null)
        {
            foreach (var entry in newEntries)
            {
                builder.AddEntry(entry.SerialNumber, entry.RevocationTime, entry.Reason);
            }
        }
 
        // Neue CRL-Nummer (inkrementiert)
        var newCrlNumber = parsedCrl.CrlNumber + 1;
 
        // Neue CRL erstellen
        return builder.Build(
            issuerCertificate: caCert,
            crlNumber: newCrlNumber,
            nextUpdate: DateTimeOffset.UtcNow.AddDays(7),
            hashAlgorithm: HashAlgorithmName.SHA256,
            mode: CryptoMode.Hybrid
        );
    }
}

CRL Extensions

// CRL mit Extensions
var crlBuilder = new CertificateRevocationListBuilder();
 
// CRL Extensions
crlBuilder.AddExtension(
    oid: "2.5.29.20",  // CRL Number
    critical: false,
    value: BuildCrlNumberExtension(1001)
);
 
crlBuilder.AddExtension(
    oid: "2.5.29.35",  // Authority Key Identifier
    critical: false,
    value: BuildAkiExtension(caCert)
);
 
crlBuilder.AddExtension(
    oid: "2.5.29.28",  // Issuing Distribution Point
    critical: true,
    value: BuildIdpExtension(
        distributionPoint: "http://crl.example.com/intermediate.crl",
        onlyContainUserCerts: true
    )
);
 
// Entry Extensions (pro widerrufenes Zertifikat)
crlBuilder.AddEntry(
    serialNumber: revokedSerial,
    revocationTime: DateTimeOffset.UtcNow,
    reason: X509RevocationReason.KeyCompromise,
    extensions: new X509ExtensionCollection
    {
        // Invalidity Date (wann tatsächlich kompromittiert)
        BuildInvalidityDateExtension(compromiseDate),
        // Certificate Issuer (falls Indirect CRL)
        BuildCertificateIssuerExtension(certIssuerDn)
    }
);

Revocation Reasons (RFC 5280)

Code Reason Beschreibung
0 unspecified Kein spezifischer Grund
1 keyCompromise Schlüssel kompromittiert
2 cACompromise CA kompromittiert
3 affiliationChanged Zugehörigkeit geändert
4 superseded Durch neues Zertifikat ersetzt
5 cessationOfOperation Betrieb eingestellt
6 certificateHold Temporär gesperrt
8 removeFromCRL Aus CRL entfernen (Hold aufheben)
9 privilegeWithdrawn Berechtigung entzogen
10 aACompromise Attribut-Autorität kompromittiert

CRL Distribution Point konfigurieren

// Zertifikat mit CDP ausstellen
var cert = ctx.IssueCertificate(
    csr,
    issuerCert: caCert,
    issuerKey: caKey,
    extensions: new ExtBuilder()
        .CrlDistributionPoint(
            uri: "http://crl.example.com/intermediate.crl",
            ldapUri: "ldap://ldap.example.com/cn=Intermediate-CA,o=Example,c=DE?certificateRevocationList"
        )
        .Build()
);

Branchenspezifische CRL-Anforderungen

Branche Max. nextUpdate Format Distribution
WebPKI 7 Tage DER HTTP
Enterprise 24 Stunden DER/PEM HTTP, LDAP
Energie/SCADA 30 Tage DER Offline
Healthcare 24 Stunden DER HTTP

Best Practice: CRL vor nextUpdate aktualisieren (50-75% der Gültigkeitsdauer).


Verwandte Szenarien

Beziehung Szenario Beschreibung
Alternative 6.2 OCSP Responder Online-Prüfung
Erweiterung 6.3 Delta-CRL Inkrementelle Updates
Voraussetzung 6.4 Zertifikat widerrufen Widerrufsprozess

« ← Widerruf-Übersicht | ↑ Szenarien | 6.2 OCSP Responder → »


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