~~NOTOC~~ ====== Scenarij 8.4: Verifikacija podpisa ====== **Kategorija:** [[.:start|Digitalni podpisi]] \\ **Kompleksnost:** ⭐⭐⭐ (Srednja) \\ **Predpogoji:** Podpisani podatki, certifikat podpisnika \\ **Predviden čas:** 10-15 minut ---- ===== Opis ===== Ta scenarij opisuje **popolno verifikacijo digitalnih podpisov**. Pravilna verifikacija vključuje: * **Preverjanje podpisa** - Kriptografska validacija * **Preverjanje certifikata** - Veriga, preklic, veljavnost * **Preverjanje časovnega žiga** - Če je prisoten * **Preverjanje politike** - Namen uporabe ---- ===== Potek dela ===== flowchart TD SIG[Podpis] --> CRYPTO[Kriptografsko preverjanje] CRYPTO --> CERT[Preverjanje certifikata] CERT --> CHAIN[Gradnja verige] CHAIN --> REV[Preverjanje preklica] REV --> TIME[Časovno preverjanje] TIME --> TS{Časovni žig?} TS -->|Da| TS_CHECK[Preverjanje časovnega žiga] TS -->|Ne| POLICY[Preverjanje politike] TS_CHECK --> POLICY POLICY --> RESULT{Vse v redu?} RESULT -->|Da| VALID[Podpis VELJAVEN] RESULT -->|Ne| INVALID[Podpis NEVELJAVEN] style VALID fill:#e8f5e9 style INVALID fill:#ffebee ---- ===== Primer kode: Popolna verifikacija ===== using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ; using System.Security.Cryptography; using System.Security.Cryptography.Pkcs; using var ctx = PqCryptoContext.Initialize(); public class SignatureVerifier { public VerificationResult Verify( byte[] data, byte[] signature, X509Certificate2 signerCert, VerificationOptions options) { var result = new VerificationResult(); try { // 1. Kriptografsko preverjanje podpisa result.SignatureValid = ctx.VerifyData( data: data, signature: signature, certificate: signerCert, hashAlgorithm: options.HashAlgorithm, mode: options.CryptoMode ); if (!result.SignatureValid) { result.Error = "Kriptografski podpis neveljaven"; return result; } // 2. Validacija verige certifikatov var chain = new X509Chain(); ConfigureChainPolicy(chain.ChainPolicy, options); result.CertificateValid = chain.Build(signerCert); result.ChainStatus = chain.ChainStatus .Select(s => s.Status.ToString()) .ToList(); if (!result.CertificateValid) { result.Error = $"Certifikat neveljaven: {string.Join(", ", result.ChainStatus)}"; return result; } // 3. Preverjanje razširjene uporabe ključa if (options.RequiredEku != null) { result.EkuValid = HasExtendedKeyUsage(signerCert, options.RequiredEku); if (!result.EkuValid) { result.Error = $"Zahtevana EKU ({options.RequiredEku}) manjka"; return result; } } // 4. Preverjanje časa podpisa var signatureTime = options.SignatureTime ?? DateTimeOffset.UtcNow; result.TimeValid = signatureTime >= signerCert.NotBefore && signatureTime <= signerCert.NotAfter; if (!result.TimeValid) { result.Error = "Certifikat ob času podpisa ni bil veljaven"; return result; } result.IsValid = true; result.SignerSubject = signerCert.Subject; result.SignatureTime = signatureTime; } catch (Exception ex) { result.IsValid = false; result.Error = ex.Message; } return result; } } ---- ===== Primer kode: Verifikacija CMS/PKCS#7 podpisa ===== public VerificationResult VerifyCms(byte[] signedData, byte[]? originalContent = null) { var result = new VerificationResult(); try { // Razčlenjevanje CMS var signedCms = new SignedCms(); if (originalContent != null) { // Ločen podpis var contentInfo = new ContentInfo(originalContent); signedCms = new SignedCms(contentInfo, true); } signedCms.Decode(signedData); // Preverjanje vsakega podpisa foreach (var signerInfo in signedCms.SignerInfos) { // Kriptografsko preverjanje signerInfo.CheckSignature(verifySignatureOnly: false); // Certifikat podpisnika var cert = signerInfo.Certificate; result.SignerSubject = cert?.Subject; // Preverjanje časovnega žiga (če obstaja) var timestampAttr = signerInfo.UnsignedAttributes .Cast() .FirstOrDefault(a => a.Oid.Value == "1.2.840.113549.1.9.16.2.14"); if (timestampAttr != null) { var tsToken = Rfc3161TimestampToken.Decode( timestampAttr.Values[0].RawData, out _); result.TimestampPresent = true; result.TimestampTime = tsToken.TokenInfo.Timestamp; // Validacija časovnega žiga var signatureBytes = signerInfo.GetSignature(); var signatureHash = SHA256.HashData(signatureBytes); result.TimestampValid = tsToken.VerifySignatureForHash( signatureHash, HashAlgorithmName.SHA256, out _, extraCandidates: null ); } // Atribut časa podpisa var signingTimeAttr = signerInfo.SignedAttributes .Cast() .FirstOrDefault(a => a.Oid.Value == "1.2.840.113549.1.9.5"); if (signingTimeAttr != null) { var pkcs9Time = new Pkcs9SigningTime(signingTimeAttr.Values[0].RawData); result.SignatureTime = pkcs9Time.SigningTime; } } result.IsValid = true; result.SignatureValid = true; result.CertificateValid = true; } catch (CryptographicException ex) { result.IsValid = false; result.Error = ex.Message; } return result; } ---- ===== Rezultat verifikacije ===== public class VerificationResult { public bool IsValid { get; set; } public bool SignatureValid { get; set; } public bool CertificateValid { get; set; } public bool TimeValid { get; set; } public bool EkuValid { get; set; } = true; public bool TimestampPresent { get; set; } public bool TimestampValid { get; set; } public string? SignerSubject { get; set; } public DateTimeOffset? SignatureTime { get; set; } public DateTimeOffset? TimestampTime { get; set; } public List ChainStatus { get; set; } = new(); public string? Error { get; set; } public override string ToString() { var sb = new StringBuilder(); sb.AppendLine($"Podpis veljaven: {IsValid}"); sb.AppendLine($" Kriptografsko preverjanje: {SignatureValid}"); sb.AppendLine($" Certifikat: {CertificateValid}"); sb.AppendLine($" Časovno preverjanje: {TimeValid}"); if (SignerSubject != null) sb.AppendLine($" Podpisnik: {SignerSubject}"); if (SignatureTime.HasValue) sb.AppendLine($" Čas podpisa: {SignatureTime:yyyy-MM-dd HH:mm:ss}"); if (TimestampPresent) { sb.AppendLine($" Časovni žig: {(TimestampValid ? "veljaven" : "neveljaven")}"); if (TimestampTime.HasValue) sb.AppendLine($" Čas časovnega žiga: {TimestampTime:yyyy-MM-dd HH:mm:ss}"); } if (Error != null) sb.AppendLine($" NAPAKA: {Error}"); return sb.ToString(); } } ---- ===== Paketna verifikacija ===== public class BatchVerifier { public async Task> VerifyDirectory( string directory, X509Certificate2Collection trustedCerts) { var results = new Dictionary(); var verifier = new SignatureVerifier(); // Iskanje vseh .sig datotek var sigFiles = Directory.GetFiles(directory, "*.sig", SearchOption.AllDirectories); foreach (var sigFile in sigFiles) { // Iskanje izvorne datoteke var originalFile = sigFile.Replace(".sig", ""); if (!File.Exists(originalFile)) { results[sigFile] = new VerificationResult { IsValid = false, Error = "Izvorna datoteka ni najdena" }; continue; } // Iskanje certifikata var certFile = sigFile.Replace(".sig", ".crt"); X509Certificate2 signerCert; if (File.Exists(certFile)) { signerCert = new X509Certificate2(certFile); } else { // Iskanje med zaupanja vrednimi certifikati (poenostavljeno) signerCert = trustedCerts[0]; } // Verifikacija var data = await File.ReadAllBytesAsync(originalFile); var signature = await File.ReadAllBytesAsync(sigFile); results[sigFile] = verifier.Verify( data, signature, signerCert, new VerificationOptions { HashAlgorithm = HashAlgorithmName.SHA256, CryptoMode = CryptoMode.Hybrid } ); } return results; } } ---- ===== Kode napak in odprava ===== ^ Napaka ^ Vzrok ^ Rešitev ^ | **SignatureInvalid** | Podatki ali podpis spremenjen | Preverjanje izvirnikov | | **CertificateExpired** | Certifikat potekel | Uporaba časovnega žiga | | **CertificateRevoked** | Certifikat preklican | Nov certifikat | | **UntrustedRoot** | Korenski certifikat ni zaupanja vreden | Preverjanje shrambe zaupanja | | **ChainIncomplete** | Vmesni certifikat manjka | Dopolnitev verige | | **TimestampInvalid** | Podpis časovnega žiga neveljaven | Preverjanje TSA certifikata | ---- ===== Povezani scenariji ===== ^ Povezava ^ Scenarij ^ Opis ^ | **Predpogoj** | [[.:dokument_signieren|8.1 Podpisovanje dokumentov]] | Ustvarjanje podpisa | | **Predpogoj** | [[.:timestamp|8.3 Časovni žig]] | Dodajanje časovnega žiga | | **Povezano** | [[sl:int:pqcrypt:szenarien:validierung:chain_validation|5.2 Validacija verige]] | Preverjanje certifikatov | ---- << [[.:timestamp|← 8.3 Časovni žig]] | [[.:start|↑ Pregled podpisov]] | [[sl:int:pqcrypt:szenarien:start|→ Vsi scenariji]] >> {{tag>scenarij podpis verifikacija validacija cms}} ---- //Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional//