~~NOTOC~~
====== Scenarij 6.4: Preklic certifikata ======
**Kategorija:** [[.:start|Preklic (Revocation)]] \\
**Kompleksnost:** Srednja \\
**Predpogoji:** Certifikat in dostop do CA \\
**Ocenjeni čas:** 10-15 minut
----
===== Opis =====
Ta scenarij opisuje **popoln postopek preklica certifikata**. Preklic je potreben pri:
* **Ogroženost ključa** - Ključ ukraden/izgubljen
* **Zamenjava** - Izdan nov certifikat
* **Ukinitev delovanja** - Storitev ni več aktivna
* **Sprememba pripadnosti** - Sodelavec zapusti organizacijo
* **Kršitev politike** - Certifikat ne ustreza več smernicam
----
===== Potek dela =====
flowchart TD
REQUEST[Zahteva za preklic] --> VERIFY[Preverjanje pooblastila]
VERIFY --> REASON[Dokumentiranje razloga]
REASON --> DB[Vnos v bazo preklicov]
DB --> CRL[Posodobitev CRL]
DB --> OCSP[Posodobitev OCSP]
CRL --> PUBLISH[Objava]
OCSP --> PUBLISH
PUBLISH --> NOTIFY[Obveščanje deležnikov]
NOTIFY --> ARCHIVE[Arhiviranje dokumentacije]
style REQUEST fill:#ffebee
style PUBLISH fill:#e8f5e9
----
===== Primer kode (C#) =====
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");
----
===== Posodabljanje CRL in 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. 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}");
}
}
----
===== Razlogi za preklic in uporaba =====
^ 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!
* Takojšnja posodobitev CRL
* Obveščanje vseh prizadetih sistemov
* Izdaja novega certifikata
* Začetek forenzične analize
----
===== Certificate Hold in odprava =====
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();
}
}
----
===== Revizijska sled =====
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);
}
}
----
===== Panožne zahteve za preklic =====
^ 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 |
----
===== Povezani scenariji =====
^ Povezava ^ Scenarij ^ Opis ^
| **Naslednji korak** | [[.:crl_erstellen|6.1 Ustvarjanje CRL]] | Posodobitev CRL |
| **Naslednji korak** | [[.:ocsp_responder|6.2 OCSP strežnik]] | Zagotavljanje statusa |
| **Povezano** | [[sl:int:pqcrypt:szenarien:verwaltung:rekey|4.2 Ponovna izdaja ključa]] | Nov certifikat |
----
<< [[.:delta_crl|← 6.3 Delta-CRL]] | [[.:start|↑ Pregled preklica]] | [[sl:int:pqcrypt:szenarien:start|→ Vsi scenariji]] >>
{{tag>szenario widerruf revocation prozess audit}}
----
//Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional//