Szenario 8.1: Dokument signieren

Kategorie: Digitale Signaturen
Komplexität: ⭐⭐⭐ (Mittel)
Voraussetzungen: Signaturzertifikat und -schlüssel
Geschätzte Zeit: 15-20 Minuten


Beschreibung

Dieses Szenario beschreibt das digitale Signieren von Dokumenten mit Post-Quantum-sicheren Algorithmen (ML-DSA). Digitale Signaturen gewährleisten:

  • Authentizität - Absender ist verifiziert
  • Integrität - Dokument wurde nicht verändert
  • Nicht-Abstreitbarkeit - Signatur kann nicht geleugnet werden

Unterstützte Formate:

  • Detached Signature (separate .sig Datei)
  • CMS/PKCS#7 (eingebettet oder detached)
  • PDF Digital Signature (PAdES)

Workflow

flowchart LR DOC[Dokument] --> HASH[SHA-256 Hash] HASH --> SIGN[ML-DSA Signatur] KEY[Private Key] --> SIGN SIGN --> SIG[Signatur] CERT[Zertifikat] --> CMS[CMS Container] SIG --> CMS style SIGN fill:#e8f5e9 style CMS fill:#e3f2fd


Code-Beispiel: Detached Signature

using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ;
using System.Security.Cryptography;
 
using var ctx = PqCryptoContext.Initialize();
 
// Signaturschlüssel laden
var signingKey = ctx.LoadPrivateKey("signing.key.pem", "KeyPassword!");
var signingCert = ctx.LoadCertificate("signing.crt.pem");
 
// Dokument laden
var document = File.ReadAllBytes("contract.pdf");
 
// Hash berechnen
var hash = SHA256.HashData(document);
 
// Mit ML-DSA signieren
var signature = ctx.SignData(
    data: hash,
    privateKey: signingKey,
    hashAlgorithm: HashAlgorithmName.SHA256,
    mode: CryptoMode.Hybrid  // RSA + ML-DSA parallel
);
 
// Signatur speichern
File.WriteAllBytes("contract.pdf.sig", signature);
 
// Signatur-Metadaten
var sigInfo = new SignatureInfo
{
    Algorithm = "ML-DSA-65 + RSA-PSS (Hybrid)",
    SignedAt = DateTimeOffset.UtcNow,
    Signer = signingCert.Subject,
    DocumentHash = Convert.ToHexString(hash),
    SignatureFile = "contract.pdf.sig"
};
 
File.WriteAllText("contract.pdf.sig.json",
    JsonSerializer.Serialize(sigInfo, new JsonSerializerOptions { WriteIndented = true }));
 
Console.WriteLine($"Dokument signiert:");
Console.WriteLine($"  Signer: {signingCert.Subject}");
Console.WriteLine($"  Hash: {Convert.ToHexString(hash).Substring(0, 16)}...");
Console.WriteLine($"  Signatur: {signature.Length} Bytes");

Code-Beispiel: CMS/PKCS#7 Signature

using System.Security.Cryptography.Pkcs;
 
using var ctx = PqCryptoContext.Initialize();
 
var signingCert = ctx.LoadCertificate("signing.crt.pem");
var signingKey = ctx.LoadPrivateKey("signing.key.pem", "KeyPassword!");
 
// Dokument
var document = File.ReadAllBytes("contract.pdf");
 
// CMS ContentInfo erstellen
var contentInfo = new ContentInfo(document);
 
// SignedCms erstellen
var signedCms = new SignedCms(contentInfo, detached: false);  // Eingebettet
 
// Signer-Info konfigurieren
var signer = new CmsSigner(signingCert)
{
    DigestAlgorithm = new Oid("2.16.840.1.101.3.4.2.1"),  // SHA-256
    IncludeOption = X509IncludeOption.WholeChain
};
 
// Signierte Attribute hinzufügen
signer.SignedAttributes.Add(new Pkcs9SigningTime(DateTimeOffset.UtcNow));
 
// Mit PQ-Erweiterung signieren (Hybrid)
signedCms.ComputeSignature(signer, mode: CryptoMode.Hybrid);
 
// CMS Container exportieren
var signedData = signedCms.Encode();
File.WriteAllBytes("contract.pdf.p7s", signedData);
 
Console.WriteLine($"CMS Signatur erstellt: {signedData.Length} Bytes");

Code-Beispiel: Signatur verifizieren

using var ctx = PqCryptoContext.Initialize();
 
// Dokument und Signatur laden
var document = File.ReadAllBytes("contract.pdf");
var signature = File.ReadAllBytes("contract.pdf.sig");
 
// Signaturzertifikat laden
var signerCert = ctx.LoadCertificate("signing.crt.pem");
 
// Hash berechnen
var hash = SHA256.HashData(document);
 
// Signatur verifizieren
bool isValid = ctx.VerifyData(
    data: hash,
    signature: signature,
    certificate: signerCert,
    hashAlgorithm: HashAlgorithmName.SHA256,
    mode: CryptoMode.Hybrid
);
 
Console.WriteLine($"Signatur gültig: {isValid}");
 
if (isValid)
{
    // Zertifikatskette validieren
    var chain = new X509Chain();
    chain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
    bool chainValid = chain.Build(signerCert);
 
    Console.WriteLine($"Zertifikat gültig: {chainValid}");
    Console.WriteLine($"  Signer: {signerCert.Subject}");
    Console.WriteLine($"  Gültig bis: {signerCert.NotAfter:yyyy-MM-dd}");
}

Batch-Signierung

public class BatchSigner
{
    private readonly AsymmetricAlgorithm _signingKey;
    private readonly X509Certificate2 _signingCert;
    private readonly PqCryptoContext _ctx;
 
    public BatchSigner(string certPath, string keyPath, string password)
    {
        _ctx = PqCryptoContext.Initialize();
        _signingCert = _ctx.LoadCertificate(certPath);
        _signingKey = _ctx.LoadPrivateKey(keyPath, password);
    }
 
    public async Task<IEnumerable<SignatureResult>> SignBatch(IEnumerable<string> filePaths)
    {
        var results = new List<SignatureResult>();
 
        foreach (var filePath in filePaths)
        {
            try
            {
                var document = await File.ReadAllBytesAsync(filePath);
                var hash = SHA256.HashData(document);
 
                var signature = _ctx.SignData(
                    hash,
                    _signingKey,
                    HashAlgorithmName.SHA256,
                    CryptoMode.Hybrid
                );
 
                var sigPath = filePath + ".sig";
                await File.WriteAllBytesAsync(sigPath, signature);
 
                results.Add(new SignatureResult
                {
                    FilePath = filePath,
                    SignaturePath = sigPath,
                    Success = true,
                    SignedAt = DateTimeOffset.UtcNow
                });
            }
            catch (Exception ex)
            {
                results.Add(new SignatureResult
                {
                    FilePath = filePath,
                    Success = false,
                    Error = ex.Message
                });
            }
        }
 
        return results;
    }
}

Signatur-Formate

Format Standard Verwendung Eingebettet
Detached Proprietär Einfache Fälle Nein
PKCS#7/CMS RFC 5652 E-Mail, Dokumente Optional
PAdES ETSI TS 103 172 PDF-Signaturen Ja
XAdES ETSI TS 101 903 XML-Signaturen Optional
JAdES ETSI TS 119 182 JSON-Signaturen Optional

Branchenspezifische Anforderungen

Branche Standard Format Besonderheit
eIDAS Qualifizierte Signatur PAdES-LTA Langzeit-Archivierung
Healthcare DiGAV CMS Patientendokumentation
Finanz PSD2 JAdES API-Signaturen
Government eGovG XAdES Verwaltungsdokumente

Verwandte Szenarien

Beziehung Szenario Beschreibung
Verwandt 8.2 Code signieren Executable signieren
Verwandt 8.3 Zeitstempel Langzeit-Gültigkeit
Nächster Schritt 8.4 Signatur verifizieren Prüfung

« ← Signaturen-Übersicht | ↑ Szenarien | 8.2 Code signieren → »


Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional

Zuletzt geändert: den 29.01.2026 um 15:13