Kategorija: Preklic (Revocation)
Kompleksnost: Srednja
Predpogoji: Certifikat in dostop do CA
Ocenjeni čas: 10-15 minut
Ta scenarij opisuje popoln postopek preklica certifikata. Preklic je potreben pri:
using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ; using var ctx = PqCryptoContext.Initialize(); // Nalaganje certifikata za preklic var certToRevoke = ctx.LoadCertificate("server.crt.pem"); // Dostop do CA var caCert = ctx.LoadCertificate("intermediate-ca.crt.pem"); var caKey = ctx.LoadPrivateKey("intermediate-ca.key.pem", "CaPassword!"); // Dokumentiranje preklica 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 = "Zasebni ključ morda izpostavljen v Git repozitoriju" }; // Shranjevanje v bazo podatkov var revocationDb = new RevocationDatabase("revocations.db"); revocationDb.AddRevocation(revocationRecord); Console.WriteLine($"Certifikat preklican:"); Console.WriteLine($" Serijska: {revocationRecord.SerialNumber}"); Console.WriteLine($" Subject: {revocationRecord.Subject}"); Console.WriteLine($" Razlog: {revocationRecord.Reason}"); Console.WriteLine($" Čas: {revocationRecord.RevocationTime:yyyy-MM-dd HH:mm:ss} UTC");
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. Vnos v bazo podatkov var record = new RevocationRecord { SerialNumber = certificate.SerialNumber, Subject = certificate.Subject, RevocationTime = DateTimeOffset.UtcNow, Reason = reason, RequestedBy = requestedBy }; _db.AddRevocation(record); // 2. Generiranje novega CRL 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. Objava CRL await PublishCrl(crlBytes); // 4. Razveljavitev OCSP predpomnilnika (če je Stapling) InvalidateOcspCache(certificate.SerialNumber); // 5. Pošiljanje obvestil await NotifyStakeholders(record); } private async Task PublishCrl(byte[] crlBytes) { // Lokalno shranjevanje File.WriteAllBytes("current.crl", crlBytes); // Nalaganje 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-pošta imetniku certifikata // E-pošta varnostni ekipi // Ustvarjanje zahtevka Console.WriteLine($"Obvestila poslana za {record.SerialNumber}"); } }
| Koda | Razlog | Kdaj uporabiti | Nujnost |
|---|---|---|---|
| 0 | unspecified | Brez specifičnega razloga | Normalna |
| 1 | keyCompromise | Ključ ogrožen/ukraden | KRITIČNA |
| 2 | cACompromise | CA ogrožena | KRITIČNA |
| 3 | affiliationChanged | Zamenjava organizacije | Normalna |
| 4 | superseded | Izdan nov certifikat | Normalna |
| 5 | cessationOfOperation | Storitev ukinjena | Normalna |
| 6 | certificateHold | Začasno blokirano | Nizka |
| 9 | privilegeWithdrawn | Pooblastilo odvzeto | Normalna |
keyCompromise (1): Potrebni takojšnji ukrepi!
public class CertificateHoldManager { // Začasna blokada 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(); } // Odprava blokade public void RemoveFromHold(string serialNumber, string reason) { var record = _db.GetRevocation(serialNumber); if (record?.Reason != X509RevocationReason.CertificateHold) { throw new InvalidOperationException("Samo blokirani certifikati se lahko sprostijo"); } // V Delta-CRL označiti z RemoveFromCrl _db.MarkAsRemovedFromHold(serialNumber); // Ali odstranitev iz baznega CRL _db.DeleteRevocation(serialNumber); RegenerateCrl(); } }
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() }; // Pisanje v revizijski dnevnik var json = JsonSerializer.Serialize(auditEntry); File.AppendAllText("audit.log", json + Environment.NewLine); // Obveščanje SIEM SendToSiem(auditEntry); } }
| Panoga | Maks. čas širjenja | Štiri-oči | Revizija |
|---|---|---|---|
| WebPKI | 24 ur | Opcijsko | Obvezno |
| Finančni sektor | 4 ure | Obvezno | Obvezno |
| Zdravstvo | 24 ur | Obvezno | 10 let |
| Energetika/SCADA | 7 dni | Obvezno | Obvezno |
| Javni sektor | 24 ur | Obvezno | 30 let |
| Povezava | Scenarij | Opis |
|---|---|---|
| Naslednji korak | 6.1 Ustvarjanje CRL | Posodobitev CRL |
| Naslednji korak | 6.2 OCSP strežnik | Zagotavljanje statusa |
| Povezano | 4.2 Ponovna izdaja ključa | Nov certifikat |
« ← 6.3 Delta-CRL | ↑ Pregled preklica | → Vsi scenariji »
Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional