Scenario 6.1: Creare CRL

Categoria: Revoca (Revocation)
Complessità: Media
Prerequisiti: Certificato e chiave CA
Tempo stimato: 15-20 minuti


Descrizione

Questo scenario descrive la creazione di una Certificate Revocation List (CRL) secondo RFC 5280. Le CRL sono liste firmate di certificati revocati, pubblicate dalle CA.

Campi CRL:


Workflow

flowchart LR REV[Certificati revocati] --> BUILD[CRL Builder] BUILD --> SIGN[Firmare con CA] SIGN --> PUBLISH[Pubblicare] PUBLISH --> CDP[Aggiornare CDP URL] style SIGN fill:#e8f5e9


Esempio codice (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}");

Aggiornare CRL da CRL esistente

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)
    }
);

Motivi di revoca (RFC 5280)

Codice Motivo Descrizione
0 unspecified Nessun motivo specifico
1 keyCompromise Chiave compromessa
2 cACompromise CA compromessa
3 affiliationChanged Affiliazione modificata
4 superseded Sostituito da nuovo certificato
5 cessationOfOperation Attività cessata
6 certificateHold Sospeso temporaneamente
8 removeFromCRL Rimuovere da CRL (annullare sospensione)
9 privilegeWithdrawn Privilegio revocato
10 aACompromise Attribute Authority compromessa

Configurare CRL Distribution Point

// 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()
);

Requisiti CRL specifici per settore

Settore Max. nextUpdate Formato Distribuzione
WebPKI 7 giorni DER HTTP
Enterprise 24 ore DER/PEM HTTP, LDAP
Energia/SCADA 30 giorni DER Offline
Sanità 24 ore DER HTTP

Best Practice: Aggiornare la CRL prima di nextUpdate (50-75% della durata di validità).


Scenari correlati

Relazione Scenario Descrizione
Alternativa 6.2 OCSP Responder Verifica online
Estensione 6.3 Delta-CRL Aggiornamenti incrementali
Prerequisito 6.4 Revocare certificato Processo di revoca

« ← Panoramica revoca | ↑ Scenari | 6.2 OCSP Responder → »


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