~~NOTOC~~ ====== Scenarij 5.3: Preverjanje preklica ====== **Kategorija:** [[.:start|Validacija in zaupanje]] \\ **Kompleksnost:** ⭐⭐⭐ (Srednja) \\ **Predpogoji:** Certifikat s CDP/OCSP \\ **Predviden čas:** 10-15 minut ---- ===== Opis ===== Ta scenarij opisuje **preverjanje statusa preklica** certifikata s pomočjo CRL (Certificate Revocation List) ali OCSP (Online Certificate Status Protocol). **Metode:** ^ Metoda ^ Prednosti ^ Slabosti ^ | **CRL** | Možno brez povezave, paketno | Velike datoteke, zakasnitev | | **OCSP** | V realnem času, majhni odgovori | Odvisnost od povezave | | **OCSP Stapling** | Zasebnost, zmogljivost | Konfiguracija strežnika | ---- ===== Potek dela ===== flowchart TD CERT[Preverjanje certifikata] --> HAS_OCSP{OCSP URL?} HAS_OCSP -->|Da| OCSP[OCSP zahteva] HAS_OCSP -->|Ne| CRL[Prenos CRL] OCSP --> OCSP_CHECK{Status?} CRL --> CRL_CHECK{V CRL?} OCSP_CHECK -->|good| OK[Ni preklican] OCSP_CHECK -->|revoked| REVOKED[Preklican] OCSP_CHECK -->|unknown| CRL CRL_CHECK -->|Ne| OK CRL_CHECK -->|Da| REVOKED style OK fill:#e8f5e9 style REVOKED fill:#ffebee ---- ===== Primer kode: OCSP preverjanje ===== using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ; using System.Security.Cryptography.X509Certificates; using var ctx = PqCryptoContext.Initialize(); // Nalaganje certifikata var cert = ctx.LoadCertificate("server.crt.pem"); var issuer = ctx.LoadCertificate("intermediate-ca.crt.pem"); // Ekstrakcija OCSP URL iz certifikata var ocspUrl = ctx.GetOcspUrl(cert); if (!string.IsNullOrEmpty(ocspUrl)) { // Ustvarjanje OCSP zahteve var ocspRequest = ctx.CreateOcspRequest(cert, issuer); // Pošiljanje OCSP zahteve using var http = new HttpClient(); http.DefaultRequestHeaders.Add("Content-Type", "application/ocsp-request"); var response = await http.PostAsync(ocspUrl, new ByteArrayContent(ocspRequest)); var ocspResponseBytes = await response.Content.ReadAsByteArrayAsync(); // Razčlenjevanje OCSP odgovora var status = ctx.ParseOcspResponse(ocspResponseBytes, cert, issuer); Console.WriteLine($"OCSP status: {status.Status}"); Console.WriteLine($" Ustvarjeno: {status.ProducedAt}"); Console.WriteLine($" Veljavno do: {status.NextUpdate}"); if (status.Status == OcspStatus.Revoked) { Console.WriteLine($" Preklicano: {status.RevocationTime}"); Console.WriteLine($" Razlog: {status.RevocationReason}"); } } ---- ===== Primer kode: CRL preverjanje ===== public class CrlChecker { private readonly Dictionary _crlCache = new(); public async Task CheckCrl(X509Certificate2 cert, X509Certificate2 issuer) { using var ctx = PqCryptoContext.Initialize(); // Ekstrakcija CDP URL iz certifikata var cdpUrl = ctx.GetCrlDistributionPoint(cert); if (string.IsNullOrEmpty(cdpUrl)) { return new RevocationStatus { Status = RevocationStatusCode.Unknown }; } // CRL iz predpomnilnika ali prenos var crl = await GetOrDownloadCrl(cdpUrl, issuer); // Iskanje serijske številke v CRL var serialNumber = cert.SerialNumber; var entry = crl.Entries.FirstOrDefault(e => e.SerialNumber.Equals(serialNumber, StringComparison.OrdinalIgnoreCase)); if (entry != null) { return new RevocationStatus { Status = RevocationStatusCode.Revoked, RevocationTime = entry.RevocationDate, Reason = entry.Reason }; } return new RevocationStatus { Status = RevocationStatusCode.Good, NextUpdate = crl.NextUpdate }; } private async Task GetOrDownloadCrl(string cdpUrl, X509Certificate2 issuer) { // Preverjanje predpomnilnika if (_crlCache.TryGetValue(cdpUrl, out var cached)) { if (cached.NextUpdate > DateTime.UtcNow) { return cached.Crl; } } // Prenos CRL using var http = new HttpClient(); var crlBytes = await http.GetByteArrayAsync(cdpUrl); // Razčlenjevanje in verifikacija CRL using var ctx = PqCryptoContext.Initialize(); var crl = ctx.ParseCrl(crlBytes); // Preverjanje podpisa if (!ctx.VerifyCrlSignature(crl, issuer)) { throw new CryptographicException("CRL podpis neveljaven"); } // Posodobitev predpomnilnika _crlCache[cdpUrl] = new CrlCache { Crl = crl, NextUpdate = crl.NextUpdate }; return crl; } } ---- ===== OCSP Stapling ===== public class OcspStapling { // Strežniška stran: Vnaprejšnje pridobivanje OCSP odgovora public async Task GetStapledOcspResponse( X509Certificate2 serverCert, X509Certificate2 issuer) { using var ctx = PqCryptoContext.Initialize(); var ocspUrl = ctx.GetOcspUrl(serverCert); var request = ctx.CreateOcspRequest(serverCert, issuer); using var http = new HttpClient(); var response = await http.PostAsync(ocspUrl, new ByteArrayContent(request)); return await response.Content.ReadAsByteArrayAsync(); } // Odjemalčeva stran: Preverjanje pripetega odgovora public OcspStatus ValidateStapledResponse( byte[] stapledResponse, X509Certificate2 serverCert, X509Certificate2 issuer) { using var ctx = PqCryptoContext.Initialize(); var status = ctx.ParseOcspResponse(stapledResponse, serverCert, issuer); // Preverjanje svežine if (status.ProducedAt < DateTime.UtcNow.AddHours(-24)) { throw new CryptographicException("OCSP odgovor prestar"); } return status; } } ---- ===== Preverjanje preklica na podlagi .NET verige ===== // Najenostavnejša metoda: Uporaba X509Chain var chain = new X509Chain(); chain.ChainPolicy.RevocationMode = X509RevocationMode.Online; chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain; chain.ChainPolicy.UrlRetrievalTimeout = TimeSpan.FromSeconds(15); // Opcijsko: Samo CRL ali samo OCSP // chain.ChainPolicy.RevocationMode = X509RevocationMode.Offline; // Samo predpomnjeni CRL-ji bool isValid = chain.Build(cert); // Ekstrakcija statusa preklica iz verige var revocationErrors = chain.ChainElements .SelectMany(e => e.ChainElementStatus) .Where(s => s.Status.HasFlag(X509ChainStatusFlags.Revoked) || s.Status.HasFlag(X509ChainStatusFlags.RevocationStatusUnknown)) .ToList(); if (revocationErrors.Any()) { foreach (var error in revocationErrors) { Console.WriteLine($"Težava s preklicom: {error.StatusInformation}"); } } ---- ===== Panožne zahteve ===== ^ Panoga ^ Metoda ^ Največja zakasnitev ^ Nadomestek ^ | **WebPKI** | OCSP Must-Staple | V realnem času | Soft-Fail | | **Finančni sektor** | OCSP + CRL | 4 ure | Hard-Fail | | **Zdravstvo** | CRL | 24 ur | Soft-Fail | | **Energetika/SCADA** | CRL (brez povezave) | 7 dni | Hard-Fail | **Soft-Fail proti Hard-Fail:** * **Soft-Fail:** Pri nedosegljivosti → sprejem certifikata * **Hard-Fail:** Pri nedosegljivosti → zavrnitev certifikata ---- ===== Povezani scenariji ===== ^ Povezava ^ Scenarij ^ Opis ^ | **Predpogoj** | [[.:chain_validation|5.2 Validacija verige]] | Gradnja verige | | **Povezano** | [[sl:int:pqcrypt:szenarien:widerruf:crl_erstellen|6.1 Ustvarjanje CRL]] | Generiranje CRL | | **Povezano** | [[sl:int:pqcrypt:szenarien:widerruf:ocsp_responder|6.2 OCSP Responder]] | Upravljanje OCSP | ---- << [[.:chain_validation|← 5.2 Validacija verige]] | [[.:start|↑ Pregled validacije]] | [[.:policy_validation|5.4 Validacija politik →]] >> {{tag>scenarij validacija preklic crl ocsp}} ---- //Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional//