Scenarij 8.1: Potpisivanje dokumenata

Kategorija: Digitalni potpisi
Složenost: ⭐⭐⭐ (Srednja)
Preduvjeti: Certifikat i ključ za potpisivanje
Procijenjeno vrijeme: 15-20 minuta


Opis

Ovaj scenarij opisuje digitalno potpisivanje dokumenata s Post-Quantum-sigurnim algoritmima (ML-DSA). Digitalni potpisi jamče:

  • Autentičnost - Pošiljatelj je verificiran
  • Integritet - Dokument nije izmijenjen
  • Neporecivost - Potpis se ne može poricati

Podržani formati:

  • Detached Signature (zasebna .sig datoteka)
  • CMS/PKCS#7 (ugrađen ili detached)
  • PDF Digital Signature (PAdES)

Tijek rada

flowchart LR DOC[Dokument] --> HASH[SHA-256 Hash] HASH --> SIGN[ML-DSA Potpis] KEY[Privatni ključ] --> SIGN SIGN --> SIG[Potpis] CERT[Certifikat] --> CMS[CMS Container] SIG --> CMS style SIGN fill:#e8f5e9 style CMS fill:#e3f2fd


Primjer koda: Detached Signature

using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ;
using System.Security.Cryptography;
 
using var ctx = PqCryptoContext.Initialize();
 
// Učitavanje ključa za potpisivanje
var signingKey = ctx.LoadPrivateKey("signing.key.pem", "KeyPassword!");
var signingCert = ctx.LoadCertificate("signing.crt.pem");
 
// Učitavanje dokumenta
var document = File.ReadAllBytes("contract.pdf");
 
// Izračun hasha
var hash = SHA256.HashData(document);
 
// Potpisivanje s ML-DSA
var signature = ctx.SignData(
    data: hash,
    privateKey: signingKey,
    hashAlgorithm: HashAlgorithmName.SHA256,
    mode: CryptoMode.Hybrid  // RSA + ML-DSA paralelno
);
 
// Spremanje potpisa
File.WriteAllBytes("contract.pdf.sig", signature);
 
// Metapodaci potpisa
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 potpisan:");
Console.WriteLine($"  Potpisnik: {signingCert.Subject}");
Console.WriteLine($"  Hash: {Convert.ToHexString(hash).Substring(0, 16)}...");
Console.WriteLine($"  Potpis: {signature.Length} bajta");

Primjer koda: CMS/PKCS#7 potpis

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");
 
// Kreiranje CMS ContentInfo
var contentInfo = new ContentInfo(document);
 
// Kreiranje SignedCms
var signedCms = new SignedCms(contentInfo, detached: false);  // Ugrađen
 
// Konfiguracija Signer-Info
var signer = new CmsSigner(signingCert)
{
    DigestAlgorithm = new Oid("2.16.840.1.101.3.4.2.1"),  // SHA-256
    IncludeOption = X509IncludeOption.WholeChain
};
 
// Dodavanje potpisanih atributa
signer.SignedAttributes.Add(new Pkcs9SigningTime(DateTimeOffset.UtcNow));
 
// Potpisivanje s PQ-ekstenzijom (Hybrid)
signedCms.ComputeSignature(signer, mode: CryptoMode.Hybrid);
 
// Izvoz CMS Containera
var signedData = signedCms.Encode();
File.WriteAllBytes("contract.pdf.p7s", signedData);
 
Console.WriteLine($"CMS Potpis kreiran: {signedData.Length} bajta");

Primjer koda: Verifikacija potpisa

using var ctx = PqCryptoContext.Initialize();
 
// Učitavanje dokumenta i potpisa
var document = File.ReadAllBytes("contract.pdf");
var signature = File.ReadAllBytes("contract.pdf.sig");
 
// Učitavanje certifikata potpisnika
var signerCert = ctx.LoadCertificate("signing.crt.pem");
 
// Izračun hasha
var hash = SHA256.HashData(document);
 
// Verifikacija potpisa
bool isValid = ctx.VerifyData(
    data: hash,
    signature: signature,
    certificate: signerCert,
    hashAlgorithm: HashAlgorithmName.SHA256,
    mode: CryptoMode.Hybrid
);
 
Console.WriteLine($"Potpis valjan: {isValid}");
 
if (isValid)
{
    // Validacija lanca certifikata
    var chain = new X509Chain();
    chain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
    bool chainValid = chain.Build(signerCert);
 
    Console.WriteLine($"Certifikat valjan: {chainValid}");
    Console.WriteLine($"  Potpisnik: {signerCert.Subject}");
    Console.WriteLine($"  Vrijedi do: {signerCert.NotAfter:yyyy-MM-dd}");
}

Grupno potpisivanje

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;
    }
}

Formati potpisa

Format Standard Uporaba Ugrađen
Detached Proprietarni Jednostavni slučajevi Ne
PKCS#7/CMS RFC 5652 E-mail, Dokumenti Opcionalno
PAdES ETSI TS 103 172 PDF potpisi Da
XAdES ETSI TS 101 903 XML potpisi Opcionalno
JAdES ETSI TS 119 182 JSON potpisi Opcionalno

Zahtjevi specifični za industriju

Industrija Standard Format Posebnost
eIDAS Kvalificirani potpis PAdES-LTA Dugoročno arhiviranje
Zdravstvo DiGAV CMS Dokumentacija pacijenata
Financije PSD2 JAdES API potpisi
Vlada eGovG XAdES Upravni dokumenti

Povezani scenariji

Povezanost Scenarij Opis
Povezano 8.2 Potpisivanje koda Potpisivanje izvršnih datoteka
Povezano 8.3 Vremenska oznaka Dugoročna valjanost
Sljedeći korak 8.4 Verifikacija potpisa Provjera

« ← Pregled potpisa | ↑ Scenariji | 8.2 Potpisivanje koda → »


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

Zuletzt geändert: 30.01.2026. u 00:33