Scenario 8.1: Firmare documento

Categoria: Firme digitali
Complessità: Media
Prerequisiti: Certificato e chiave di firma
Tempo stimato: 15-20 minuti


Descrizione

Questo scenario descrive la firma digitale di documenti con algoritmi sicuri Post-Quantum (ML-DSA). Le firme digitali garantiscono:

Formati supportati:


Workflow

flowchart LR DOC[Documento] --> HASH[Hash SHA-256] HASH --> SIGN[Firma ML-DSA] KEY[Chiave privata] --> SIGN SIGN --> SIG[Firma] CERT[Certificato] --> CMS[Container CMS] SIG --> CMS style SIGN fill:#e8f5e9 style CMS fill:#e3f2fd


Esempio codice: Detached Signature

using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ;
using System.Security.Cryptography;
 
using var ctx = PqCryptoContext.Initialize();
 
// Caricare chiave di firma
var signingKey = ctx.LoadPrivateKey("signing.key.pem", "KeyPassword!");
var signingCert = ctx.LoadCertificate("signing.crt.pem");
 
// Caricare documento
var document = File.ReadAllBytes("contract.pdf");
 
// Calcolare hash
var hash = SHA256.HashData(document);
 
// Firmare con ML-DSA
var signature = ctx.SignData(
    data: hash,
    privateKey: signingKey,
    hashAlgorithm: HashAlgorithmName.SHA256,
    mode: CryptoMode.Hybrid  // RSA + ML-DSA in parallelo
);
 
// Salvare firma
File.WriteAllBytes("contract.pdf.sig", signature);
 
// Metadati firma
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($"Documento firmato:");
Console.WriteLine($"  Firmatario: {signingCert.Subject}");
Console.WriteLine($"  Hash: {Convert.ToHexString(hash).Substring(0, 16)}...");
Console.WriteLine($"  Firma: {signature.Length} Bytes");

Esempio codice: Firma CMS/PKCS#7

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!");
 
// Documento
var document = File.ReadAllBytes("contract.pdf");
 
// Creare CMS ContentInfo
var contentInfo = new ContentInfo(document);
 
// Creare SignedCms
var signedCms = new SignedCms(contentInfo, detached: false);  // Incorporato
 
// Configurare Signer-Info
var signer = new CmsSigner(signingCert)
{
    DigestAlgorithm = new Oid("2.16.840.1.101.3.4.2.1"),  // SHA-256
    IncludeOption = X509IncludeOption.WholeChain
};
 
// Aggiungere attributi firmati
signer.SignedAttributes.Add(new Pkcs9SigningTime(DateTimeOffset.UtcNow));
 
// Firmare con estensione PQ (Ibrido)
signedCms.ComputeSignature(signer, mode: CryptoMode.Hybrid);
 
// Esportare container CMS
var signedData = signedCms.Encode();
File.WriteAllBytes("contract.pdf.p7s", signedData);
 
Console.WriteLine($"Firma CMS creata: {signedData.Length} Bytes");

Esempio codice: Verificare firma

using var ctx = PqCryptoContext.Initialize();
 
// Caricare documento e firma
var document = File.ReadAllBytes("contract.pdf");
var signature = File.ReadAllBytes("contract.pdf.sig");
 
// Caricare certificato firmatario
var signerCert = ctx.LoadCertificate("signing.crt.pem");
 
// Calcolare hash
var hash = SHA256.HashData(document);
 
// Verificare firma
bool isValid = ctx.VerifyData(
    data: hash,
    signature: signature,
    certificate: signerCert,
    hashAlgorithm: HashAlgorithmName.SHA256,
    mode: CryptoMode.Hybrid
);
 
Console.WriteLine($"Firma valida: {isValid}");
 
if (isValid)
{
    // Validare catena certificati
    var chain = new X509Chain();
    chain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
    bool chainValid = chain.Build(signerCert);
 
    Console.WriteLine($"Certificato valido: {chainValid}");
    Console.WriteLine($"  Firmatario: {signerCert.Subject}");
    Console.WriteLine($"  Valido fino a: {signerCert.NotAfter:yyyy-MM-dd}");
}

Firma batch

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 di firma

Formato Standard Utilizzo Incorporato
Detached Proprietario Casi semplici No
PKCS#7/CMS RFC 5652 E-mail, documenti Opzionale
PAdES ETSI TS 103 172 Firme PDF Si
XAdES ETSI TS 101 903 Firme XML Opzionale
JAdES ETSI TS 119 182 Firme JSON Opzionale

Requisiti specifici per settore

Settore Standard Formato Particolarità
eIDAS Firma qualificata PAdES-LTA Archiviazione a lungo termine
Sanità DiGAV CMS Documentazione pazienti
Finanza PSD2 JAdES Firme API
Pubblica Amministrazione eGovG XAdES Documenti amministrativi

Scenari correlati

Relazione Scenario Descrizione
Correlato 8.2 Firmare codice Firmare executable
Correlato 8.3 Timestamp Validità a lungo termine
Passo successivo 8.4 Verificare firma Verifica

« ← Panoramica firme | ↑ Scenari | 8.2 Firmare codice → »


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