~~NOTOC~~ ====== Scenarij 6.4: Opoziv certifikata ====== **Kategorija:** [[.:start|Opoziv (Revocation)]] \\ **Složenost:** ⭐⭐⭐ (Srednja) \\ **Preduvjeti:** Certifikat i pristup CA \\ **Procijenjeno vrijeme:** 10-15 minuta ---- ===== Opis ===== Ovaj scenarij opisuje **potpuni proces opoziva certifikata**. Opoziv je potreban kod: * **Kompromitacije ključa** - Ključ ukraden/izgubljen * **Zamjene** - Izdan novi certifikat * **Ukidanja rada** - Usluga više nije aktivna * **Promjene pripadnosti** - Zaposlenik napušta organizaciju * **Kršenja politike** - Certifikat više ne odgovara pravilima ---- ===== Tijek rada ===== flowchart TD REQUEST[Zahtjev za opoziv] --> VERIFY[Provjera ovlaštenja] VERIFY --> REASON[Dokumentiranje razloga] REASON --> DB[Unos u Revocation-DB] DB --> CRL[Ažuriranje CRL-a] DB --> OCSP[Ažuriranje OCSP-a] CRL --> PUBLISH[Objavljivanje] OCSP --> PUBLISH PUBLISH --> NOTIFY[Obavještavanje dionika] NOTIFY --> ARCHIVE[Arhiviranje dokumentacije] style REQUEST fill:#ffebee style PUBLISH fill:#e8f5e9 ---- ===== Primjer koda (C#) ===== using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ; using var ctx = PqCryptoContext.Initialize(); // Učitavanje certifikata za opoziv var certToRevoke = ctx.LoadCertificate("server.crt.pem"); // Pristup CA var caCert = ctx.LoadCertificate("intermediate-ca.crt.pem"); var caKey = ctx.LoadPrivateKey("intermediate-ca.key.pem", "CaPassword!"); // Dokumentiranje opoziva 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 = "Privatni ključ možda izložen u Git repozitoriju" }; // Spremanje u bazu podataka var revocationDb = new RevocationDatabase("revocations.db"); revocationDb.AddRevocation(revocationRecord); Console.WriteLine($"Certifikat opozvan:"); Console.WriteLine($" Serial: {revocationRecord.SerialNumber}"); Console.WriteLine($" Subject: {revocationRecord.Subject}"); Console.WriteLine($" Razlog: {revocationRecord.Reason}"); Console.WriteLine($" Vrijeme: {revocationRecord.RevocationTime:yyyy-MM-dd HH:mm:ss} UTC"); ---- ===== Ažuriranje CRL-a i OCSP-a ===== 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. Unos u bazu podataka var record = new RevocationRecord { SerialNumber = certificate.SerialNumber, Subject = certificate.Subject, RevocationTime = DateTimeOffset.UtcNow, Reason = reason, RequestedBy = requestedBy }; _db.AddRevocation(record); // 2. Generiranje novog CRL-a 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. Objavljivanje CRL-a await PublishCrl(crlBytes); // 4. Invalidacija OCSP predmemorije (ako je Stapling) InvalidateOcspCache(certificate.SerialNumber); // 5. Slanje obavijesti await NotifyStakeholders(record); } private async Task PublishCrl(byte[] crlBytes) { // Lokalno spremanje File.WriteAllBytes("current.crl", crlBytes); // Upload na CDP using var http = new HttpClient(); var content = new ByteArrayContent(crlBytes); await http.PutAsync("https://crl.example.com/intermediate.crl", content); Console.WriteLine("CRL objavljen"); } private async Task NotifyStakeholders(RevocationRecord record) { // E-mail vlasniku certifikata // E-mail sigurnosnom timu // Kreiranje tiketa Console.WriteLine($"Obavijesti poslane za {record.SerialNumber}"); } } ---- ===== Razlozi opoziva i korištenje ===== ^ Kod ^ Razlog ^ Kada koristiti ^ Hitnost ^ | 0 | unspecified | Bez specifičnog razloga | Normalna | | 1 | keyCompromise | Ključ kompromitiran/ukraden | **KRITIČNO** | | 2 | cACompromise | CA kompromitiran | **KRITIČNO** | | 3 | affiliationChanged | Organizacija promijenjena | Normalna | | 4 | superseded | Izdan novi certifikat | Normalna | | 5 | cessationOfOperation | Usluga ukinuta | Normalna | | 6 | certificateHold | Privremeno blokiran | Niska | | 9 | privilegeWithdrawn | Ovlaštenje povučeno | Normalna | **keyCompromise (1):** Potrebne hitne mjere! * Odmah ažurirati CRL * Obavijestiti sve pogođene sustave * Izdati novi certifikat * Pokrenuti forenzičku analizu ---- ===== Certificate Hold i ukidanje ===== public class CertificateHoldManager { // Privremeno blokiranje certifikata public void PlaceOnHold(string serialNumber, string reason) { _db.AddRevocation(new RevocationRecord { SerialNumber = serialNumber, RevocationTime = DateTimeOffset.UtcNow, Reason = X509RevocationReason.CertificateHold, Notes = reason, IsOnHold = true }); RegenerateCrl(); } // Ukidanje Hold stanja public void RemoveFromHold(string serialNumber, string reason) { var record = _db.GetRevocation(serialNumber); if (record?.Reason != X509RevocationReason.CertificateHold) { throw new InvalidOperationException("Samo Hold certifikati mogu biti oslobođeni"); } // Označavanje u Delta-CRL-u s RemoveFromCrl _db.MarkAsRemovedFromHold(serialNumber); // Ili uklanjanje iz baznog CRL-a _db.DeleteRevocation(serialNumber); RegenerateCrl(); } } ---- ===== Revizijski trag ===== 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() }; // Zapisivanje u audit log var json = JsonSerializer.Serialize(auditEntry); File.AppendAllText("audit.log", json + Environment.NewLine); // Obavještavanje SIEM-a SendToSiem(auditEntry); } } ---- ===== Zahtjevi za opoziv po industrijama ===== ^ Industrija ^ Maks. vrijeme propagacije ^ Četveroočni princip ^ Revizija ^ | **WebPKI** | 24 sata | Opcionalno | Obvezno | | **Financijski sektor** | 4 sata | Obvezno | Obvezno | | **Zdravstvo** | 24 sata | Obvezno | 10 godina | | **Energetika/SCADA** | 7 dana | Obvezno | Obvezno | | **Vlada** | 24 sata | Obvezno | 30 godina | ---- ===== Povezani scenariji ===== ^ Odnos ^ Scenarij ^ Opis ^ | **Sljedeći korak** | [[.:crl_erstellen|6.1 Kreiranje CRL-a]] | Ažuriranje CRL-a | | **Sljedeći korak** | [[.:ocsp_responder|6.2 OCSP Responder]] | Pružanje statusa | | **Povezano** | [[hr:int:pqcrypt:szenarien:verwaltung:rekey|4.2 Re-Key]] | Novi certifikat | ---- << [[.:delta_crl|← 6.3 Delta-CRL]] | [[.:start|↑ Pregled opoziva]] | [[hr:int:pqcrypt:szenarien:start|→ Svi scenariji]] >> {{tag>scenarij opoziv revocation proces revizija}} ---- //Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional//