~~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//