~~NOTOC~~
====== Szenario 8.4: Signatur verifizieren ======
**Kategorie:** [[.:start|Digitale Signaturen]] \\
**Komplexität:** ⭐⭐⭐ (Mittel) \\
**Voraussetzungen:** Signierte Daten, Signaturzertifikat \\
**Geschätzte Zeit:** 10-15 Minuten
----
===== Beschreibung =====
Dieses Szenario beschreibt die **vollständige Verifikation digitaler Signaturen**. Eine korrekte Verifikation umfasst:
* **Signaturprüfung** - Kryptographische Validierung
* **Zertifikatsprüfung** - Chain, Revocation, Gültigkeit
* **Timestamp-Prüfung** - Falls vorhanden
* **Policy-Prüfung** - Verwendungszweck
----
===== Workflow =====
flowchart TD
SIG[Signatur] --> CRYPTO[Krypto-Prüfung]
CRYPTO --> CERT[Zertifikat prüfen]
CERT --> CHAIN[Chain Building]
CHAIN --> REV[Revocation Check]
REV --> TIME[Zeitprüfung]
TIME --> TS{Timestamp?}
TS -->|Ja| TS_CHECK[Timestamp prüfen]
TS -->|Nein| POLICY[Policy prüfen]
TS_CHECK --> POLICY
POLICY --> RESULT{Alles OK?}
RESULT -->|Ja| VALID[Signatur GÜLTIG]
RESULT -->|Nein| INVALID[Signatur UNGÜLTIG]
style VALID fill:#e8f5e9
style INVALID fill:#ffebee
----
===== Code-Beispiel: Vollständige Verifikation =====
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. Kryptographische Signaturprüfung
result.SignatureValid = ctx.VerifyData(
data: data,
signature: signature,
certificate: signerCert,
hashAlgorithm: options.HashAlgorithm,
mode: options.CryptoMode
);
if (!result.SignatureValid)
{
result.Error = "Kryptographische Signatur ungültig";
return result;
}
// 2. Zertifikatskette validieren
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 = $"Zertifikat ungültig: {string.Join(", ", result.ChainStatus)}";
return result;
}
// 3. Extended Key Usage prüfen
if (options.RequiredEku != null)
{
result.EkuValid = HasExtendedKeyUsage(signerCert, options.RequiredEku);
if (!result.EkuValid)
{
result.Error = $"Erforderliche EKU ({options.RequiredEku}) fehlt";
return result;
}
}
// 4. Signaturzeitpunkt prüfen
var signatureTime = options.SignatureTime ?? DateTimeOffset.UtcNow;
result.TimeValid = signatureTime >= signerCert.NotBefore &&
signatureTime <= signerCert.NotAfter;
if (!result.TimeValid)
{
result.Error = "Zertifikat war zum Signaturzeitpunkt nicht gültig";
return result;
}
result.IsValid = true;
result.SignerSubject = signerCert.Subject;
result.SignatureTime = signatureTime;
}
catch (Exception ex)
{
result.IsValid = false;
result.Error = ex.Message;
}
return result;
}
}
----
===== Code-Beispiel: CMS/PKCS#7 Signatur verifizieren =====
public VerificationResult VerifyCms(byte[] signedData, byte[]? originalContent = null)
{
var result = new VerificationResult();
try
{
// CMS parsen
var signedCms = new SignedCms();
if (originalContent != null)
{
// Detached signature
var contentInfo = new ContentInfo(originalContent);
signedCms = new SignedCms(contentInfo, true);
}
signedCms.Decode(signedData);
// Jede Signatur prüfen
foreach (var signerInfo in signedCms.SignerInfos)
{
// Kryptographische Prüfung
signerInfo.CheckSignature(verifySignatureOnly: false);
// Signer-Zertifikat
var cert = signerInfo.Certificate;
result.SignerSubject = cert?.Subject;
// Timestamp prüfen (falls vorhanden)
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;
// Timestamp validieren
var signatureBytes = signerInfo.GetSignature();
var signatureHash = SHA256.HashData(signatureBytes);
result.TimestampValid = tsToken.VerifySignatureForHash(
signatureHash,
HashAlgorithmName.SHA256,
out _,
extraCandidates: null
);
}
// Signing Time Attribut
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;
}
----
===== Verifikationsergebnis =====
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($"Signatur gültig: {IsValid}");
sb.AppendLine($" Krypto-Prüfung: {SignatureValid}");
sb.AppendLine($" Zertifikat: {CertificateValid}");
sb.AppendLine($" Zeitprüfung: {TimeValid}");
if (SignerSubject != null)
sb.AppendLine($" Signer: {SignerSubject}");
if (SignatureTime.HasValue)
sb.AppendLine($" Signaturzeit: {SignatureTime:yyyy-MM-dd HH:mm:ss}");
if (TimestampPresent)
{
sb.AppendLine($" Timestamp: {(TimestampValid ? "gültig" : "ungültig")}");
if (TimestampTime.HasValue)
sb.AppendLine($" Timestamp-Zeit: {TimestampTime:yyyy-MM-dd HH:mm:ss}");
}
if (Error != null)
sb.AppendLine($" FEHLER: {Error}");
return sb.ToString();
}
}
----
===== Batch-Verifikation =====
public class BatchVerifier
{
public async Task> VerifyDirectory(
string directory,
X509Certificate2Collection trustedCerts)
{
var results = new Dictionary();
var verifier = new SignatureVerifier();
// Alle .sig Dateien finden
var sigFiles = Directory.GetFiles(directory, "*.sig", SearchOption.AllDirectories);
foreach (var sigFile in sigFiles)
{
// Originaldatei finden
var originalFile = sigFile.Replace(".sig", "");
if (!File.Exists(originalFile))
{
results[sigFile] = new VerificationResult
{
IsValid = false,
Error = "Originaldatei nicht gefunden"
};
continue;
}
// Zertifikat finden
var certFile = sigFile.Replace(".sig", ".crt");
X509Certificate2 signerCert;
if (File.Exists(certFile))
{
signerCert = new X509Certificate2(certFile);
}
else
{
// Aus Trusted Certs suchen (vereinfacht)
signerCert = trustedCerts[0];
}
// Verifizieren
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;
}
}
----
===== Fehlercodes und Behebung =====
^ Fehler ^ Ursache ^ Lösung ^
| **SignatureInvalid** | Daten oder Signatur manipuliert | Originale prüfen |
| **CertificateExpired** | Zertifikat abgelaufen | Timestamp nutzen |
| **CertificateRevoked** | Zertifikat widerrufen | Neues Zertifikat |
| **UntrustedRoot** | Root nicht vertrauenswürdig | Trust Store prüfen |
| **ChainIncomplete** | Intermediate fehlt | Chain vervollständigen |
| **TimestampInvalid** | Timestamp-Signatur ungültig | TSA-Zertifikat prüfen |
----
===== Verwandte Szenarien =====
^ Beziehung ^ Szenario ^ Beschreibung ^
| **Voraussetzung** | [[.:dokument_signieren|8.1 Dokument signieren]] | Signatur erstellen |
| **Voraussetzung** | [[.:timestamp|8.3 Zeitstempel]] | Timestamp hinzufügen |
| **Verwandt** | [[de:int:pqcrypt:szenarien:validierung:chain_validation|5.2 Chain Validation]] | Zertifikatsprüfung |
----
<< [[.:timestamp|← 8.3 Zeitstempel]] | [[.:start|↑ Signaturen-Übersicht]] | [[de:int:pqcrypt:szenarien:start|→ Alle Szenarien]] >>
{{tag>szenario signatur verifizierung validierung cms}}
----
//Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional//