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