Scenario 6.4: Revocare certificato

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


Descrizione

Questo scenario descrive il processo completo per la revoca di un certificato. Una revoca è necessaria in caso di:


Workflow

flowchart TD REQUEST[Richiesta revoca] --> VERIFY[Verificare autorizzazione] VERIFY --> REASON[Documentare motivo] REASON --> DB[Inserire in Revocation DB] DB --> CRL[Aggiornare CRL] DB --> OCSP[Aggiornare OCSP] CRL --> PUBLISH[Pubblicare] OCSP --> PUBLISH PUBLISH --> NOTIFY[Notificare stakeholder] NOTIFY --> ARCHIVE[Archiviare documentazione] style REQUEST fill:#ffebee style PUBLISH fill:#e8f5e9


Esempio codice (C#)

using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ;
 
using var ctx = PqCryptoContext.Initialize();
 
// Zu widerrufendes Zertifikat laden
var certToRevoke = ctx.LoadCertificate("server.crt.pem");
 
// CA-Zugriff
var caCert = ctx.LoadCertificate("intermediate-ca.crt.pem");
var caKey = ctx.LoadPrivateKey("intermediate-ca.key.pem", "CaPassword!");
 
// Widerruf dokumentieren
var revocationRecord = new RevocationRecord
{
    SerialNumber = certToRevoke.SerialNumber,
    Subject = certToRevoke.Subject,
    RevocationTime = DateTimeOffset.UtcNow,
    Reason = X509RevocationReason.KeyCompromise,
    RequestedBy = "admin@example.com",
    RequestedAt = DateTimeOffset.UtcNow,
    ApprovedBy = "security@example.com",
    Notes = "Private Key möglicherweise in Git Repository exponiert"
};
 
// In Datenbank speichern
var revocationDb = new RevocationDatabase("revocations.db");
revocationDb.AddRevocation(revocationRecord);
 
Console.WriteLine($"Zertifikat widerrufen:");
Console.WriteLine($"  Serial: {revocationRecord.SerialNumber}");
Console.WriteLine($"  Subject: {revocationRecord.Subject}");
Console.WriteLine($"  Grund: {revocationRecord.Reason}");
Console.WriteLine($"  Zeit: {revocationRecord.RevocationTime:yyyy-MM-dd HH:mm:ss} UTC");

Aggiornare CRL e OCSP

public class RevocationManager
{
    private readonly RevocationDatabase _db;
    private readonly X509Certificate2 _caCert;
    private readonly AsymmetricAlgorithm _caKey;
 
    public async Task RevokeAndPublish(
        X509Certificate2 certificate,
        X509RevocationReason reason,
        string requestedBy)
    {
        using var ctx = PqCryptoContext.Initialize();
 
        // 1. In Datenbank eintragen
        var record = new RevocationRecord
        {
            SerialNumber = certificate.SerialNumber,
            Subject = certificate.Subject,
            RevocationTime = DateTimeOffset.UtcNow,
            Reason = reason,
            RequestedBy = requestedBy
        };
        _db.AddRevocation(record);
 
        // 2. Neue CRL generieren
        var crlBuilder = new CertificateRevocationListBuilder();
        foreach (var rev in _db.GetAllRevocations())
        {
            crlBuilder.AddEntry(
                HexToBytes(rev.SerialNumber),
                rev.RevocationTime,
                rev.Reason
            );
        }
 
        var nextCrlNumber = _db.GetNextCrlNumber();
        var crlBytes = crlBuilder.Build(
            _caCert,
            nextCrlNumber,
            DateTimeOffset.UtcNow.AddDays(7),
            HashAlgorithmName.SHA256,
            mode: CryptoMode.Hybrid
        );
 
        // 3. CRL veröffentlichen
        await PublishCrl(crlBytes);
 
        // 4. OCSP Cache invalidieren (falls Stapling)
        InvalidateOcspCache(certificate.SerialNumber);
 
        // 5. Benachrichtigung senden
        await NotifyStakeholders(record);
    }
 
    private async Task PublishCrl(byte[] crlBytes)
    {
        // Lokal speichern
        File.WriteAllBytes("current.crl", crlBytes);
 
        // Auf CDP hochladen
        using var http = new HttpClient();
        var content = new ByteArrayContent(crlBytes);
        await http.PutAsync("https://crl.example.com/intermediate.crl", content);
 
        Console.WriteLine("CRL veröffentlicht");
    }
 
    private async Task NotifyStakeholders(RevocationRecord record)
    {
        // E-Mail an Zertifikatsinhaber
        // E-Mail an Security-Team
        // Ticket erstellen
        Console.WriteLine($"Benachrichtigungen gesendet für {record.SerialNumber}");
    }
}

Motivi di revoca e utilizzo

Codice Motivo Quando utilizzare Urgenza
0 unspecified Nessun motivo specifico Normale
1 keyCompromise Chiave compromessa/rubata CRITICO
2 cACompromise CA compromessa CRITICO
3 affiliationChanged Organizzazione cambiata Normale
4 superseded Nuovo certificato emesso Normale
5 cessationOfOperation Servizio cessato Normale
6 certificateHold Sospeso temporaneamente Bassa
9 privilegeWithdrawn Privilegio revocato Normale

keyCompromise (1): Azioni immediate richieste!

  • Aggiornare CRL immediatamente
  • Informare tutti i sistemi interessati
  • Emettere nuovo certificato
  • Avviare analisi forense

Certificate Hold e revoca

public class CertificateHoldManager
{
    // Zertifikat temporär sperren
    public void PlaceOnHold(string serialNumber, string reason)
    {
        _db.AddRevocation(new RevocationRecord
        {
            SerialNumber = serialNumber,
            RevocationTime = DateTimeOffset.UtcNow,
            Reason = X509RevocationReason.CertificateHold,
            Notes = reason,
            IsOnHold = true
        });
 
        RegenerateCrl();
    }
 
    // Hold aufheben
    public void RemoveFromHold(string serialNumber, string reason)
    {
        var record = _db.GetRevocation(serialNumber);
        if (record?.Reason != X509RevocationReason.CertificateHold)
        {
            throw new InvalidOperationException("Nur Hold-Zertifikate können freigegeben werden");
        }
 
        // In Delta-CRL mit RemoveFromCrl markieren
        _db.MarkAsRemovedFromHold(serialNumber);
 
        // Oder aus Basis-CRL entfernen
        _db.DeleteRevocation(serialNumber);
 
        RegenerateCrl();
    }
}

Audit Trail

public class RevocationAudit
{
    public void LogRevocation(RevocationRecord record)
    {
        var auditEntry = new
        {
            Timestamp = DateTimeOffset.UtcNow,
            Action = "CERTIFICATE_REVOKED",
            SerialNumber = record.SerialNumber,
            Subject = record.Subject,
            Reason = record.Reason.ToString(),
            RequestedBy = record.RequestedBy,
            ApprovedBy = record.ApprovedBy,
            Notes = record.Notes,
            ClientIp = GetClientIp(),
            UserAgent = GetUserAgent()
        };
 
        // In Audit-Log schreiben
        var json = JsonSerializer.Serialize(auditEntry);
        File.AppendAllText("audit.log", json + Environment.NewLine);
 
        // SIEM benachrichtigen
        SendToSiem(auditEntry);
    }
}

Requisiti di revoca specifici per settore

Settore Max. tempo propagazione Quattro occhi Audit
WebPKI 24 ore Opzionale Obbligatorio
Settore finanziario 4 ore Obbligatorio Obbligatorio
Sanità 24 ore Obbligatorio 10 anni
Energia/SCADA 7 giorni Obbligatorio Obbligatorio
Governo 24 ore Obbligatorio 30 anni

Scenari correlati

Relazione Scenario Descrizione
Passo successivo 6.1 Creare CRL Aggiornare CRL
Passo successivo 6.2 OCSP Responder Fornire stato
Correlato 4.2 Rekey Nuovo certificato

« ← 6.3 Delta-CRL | ↑ Panoramica revoca | → Tutti gli scenari »


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