Questa pagina può contenere testo tradotto automaticamente.

Come firmare PDF con token USB e dispositivi HSM in C# e VB.NET

Le autorità di certificazione affidabili non consentono più di esportare le chiavi private per i certificati di firma dei documenti. Le chiavi private devono invece essere archiviate in hardware sicuro come token USB, smart card o HSM basati sul cloud.

Puoi usare la libreria Docotic.Pdf per firmare documenti PDF in .NET usando dispositivi HSM. Questo articolo descrive le integrazioni con Azure Key Vault, AWS KMS e hardware compatibile con PKCS#11.

Puoi ottenere la libreria e una chiave di licenza gratuita a tempo limitato nella pagina Scarica la libreria PDF C# .NET.

Firma PDF esterna

Prerequisiti

Gli esempi di codice in questo articolo usano certificati autofirmati per firmare documenti PDF. Per impostazione predefinita, i visualizzatori PDF non considerano attendibili queste firme. I certificati autofirmati devono essere usati solo per il testing, non in ambienti di produzione. Per generare firme PDF affidabili, usa certificati di firma dei documenti emessi da autorità di certificazione di terze parti.

Get the right certificate

Preferisci certificati di aziende elencate nella Adobe Approved Trust List (AATL). Adobe Acrobat considera attendibili per impostazione predefinita i certificati di queste aziende e non segnalerà l'avviso "Certificate validity is unknown".

Per creare documenti conformi a EU (eIDAS), devi usare Certificati Qualificati emessi da provider elencati nelle European Union Trusted Lists (EUTL).

Learn how to use your certificate in .NET

Quando ordini un certificato di firma dei documenti, in genere ricevi l'accesso a un dispositivo HSM. Può trattarsi di un token USB fisico o di una soluzione HSM basata sul cloud.

Poi devi imparare a firmare i dati con questo HSM. Di solito questa è la parte più complessa, perché tutti i provider crittografici sono diversi. Dovresti seguire la documentazione del tuo token USB o della tua API cloud.

Idealmente, devi trovare un SDK .NET corrispondente. Oppure, almeno, trovare un SDK nativo e usarlo tramite interop in .NET.

Il tuo obiettivo è ottenere codice C# o VB.NET che possa firmare qualsiasi byte usando il tuo certificato.

PDF API for external signing

Una volta che puoi firmare qualsiasi byte con il tuo dispositivo HSM, sei pronto per firmare documenti PDF con Docotic.Pdf. Per farlo, implementa l'interfaccia IPdfSigner e usala per la firma.

Implement IPdfSigner interface

IPdfSigner dichiara due membri. La proprietà SignatureAlgorithm restituisce l'algoritmo usato per la firma. In genere, useresti algoritmi RSA o ECDSA.

Il metodo Sign è la parte chiave del flusso di firma esterna. Docotic.Pdf fornisce a questo metodo il digest dei byte di un documento PDF. Devi firmare questo digest con il tuo dispositivo HSM e restituire i byte di una firma digitale. Nota che qui non devi restituire un oggetto PKCS#7. Genera e restituisci solo la firma crittografica.

Docotic.Pdf chiama il metodo Sign due volte per ogni firma. La prima chiamata serve a calcolare lo spazio necessario per la firma. La seconda chiamata serve a firmare effettivamente il documento.

Create PdfSigningOptions for external signing

Usa il costruttore PdfSigningOptions(IPdfSigner, X509Certificate2[]) per firmare documenti PDF con la tua implementazione di IPdfSigner. Ottieni una catena di certificati e forniscila come secondo argomento. È richiesto almeno un certificato e il certificato di firma deve venire per primo.

L'ultimo tassello del puzzle è la proprietà PdfSigningOptions.DigestAlgorithm. Il valore di questa proprietà deve essere coerente con IPdfSigner.SignatureAlgorithm e con l'implementazione di IPdfSigner.Sign.

Vediamo come firmare PDF con firme esterne nei casi comuni.

Sign PDF documents using PKCS#11 driver in C#

Se il tuo token USB crittografico o la tua smart card include un driver PKCS#11, puoi usare le librerie Pkcs11Interop.X509Store o Pkcs11Interop in .NET. Pkcs11Interop è compatibile con smart card Atos CardOS, YubiKey PIV, SmartCard-HSM, SafeNet ProtectServer HSM e altri HSM.

L'esempio di codice Firma documenti PDF utilizzando i driver PKCS#11 mostra come firmare documenti PDF con un token USB o una smart card. Dovrai personalizzare queste righe:

string pkcsLibraryPath = @"C:\Program Files\SoftHSM2\lib\softhsm2-x64.dll";
ulong slotId = 1743347971;
string alias = "YOUR-ALIAS";
string certLabel = "YOUR-CERTIFICATE";
string pin = "YOUR-PIN";
var digestAlgorithm = PdfDigestAlgorithm.Sha512;

La nostra configurazione di esempio usa SoftHSM2 come emulatore di un token USB. Nelle applicazioni reali, non hai bisogno di SoftHSM2. Usa invece il driver fornito con il token USB.

Sign PDF documents using Azure Key Vault

Microsoft Azure Key Vault archivia in modo sicuro certificati e chiavi. Dovrai eseguire i seguenti preparativi:

  1. Creare un account Azure.
  2. Creare un utente Azure.
  3. Creare un Key Vault.
  4. Consentire l'accesso al Key Vault per l'utente Azure selezionato.
  5. Aggiungere un certificato di firma dei documenti al Key Vault. Puoi importare certificati da Integrated Certificate Authorities.

Poi, usa il pacchetto NuGet Azure.Security.KeyVault.Keys per firmare in .NET. Esempio di codice C# per firmare con una chiave da Azure Key Vault:

var vaultUrl = new Uri("https://YOUR-VAULT.vault.azure.net/");
var credentials = new DefaultAzureCredential();

var keyClient = new KeyClient(vaultUrl, credentials);
KeyVaultKey key = keyClient.GetKey("YOUR-KEY");
var cryptoClient = new CryptographyClient(key.Id, credentials);
byte[] messageToSign = ..;
byte[] signature = cryptoClient.SignData(SignatureAlgorithm.RS512, messageToSign).Signature;

Una possibile implementazione di IPdfSigner potrebbe apparire così:

using AzureSignatureAlgorithm = SignatureAlgorithm;

class AzureSigner : IPdfSigner
{
    private readonly CryptographyClient m_client;
    private readonly AzureSignatureAlgorithm m_signingAlgorithm;

    public AzureSigner(CryptographyClient client, AzureSignatureAlgorithm signingAlgorithm)
    {
        m_client = client;
        m_signingAlgorithm = signingAlgorithm;
    }

    public PdfSignatureAlgorithm SignatureAlgorithm
    {
        get
        {
            if (m_signingAlgorithm == AzureSignatureAlgorithm.RS256 ||
                m_signingAlgorithm == AzureSignatureAlgorithm.RS384 ||
                m_signingAlgorithm == AzureSignatureAlgorithm.RS512)
                return PdfSignatureAlgorithm.Rsa;

            throw new NotSupportedException($"Unsupported {nameof(SignatureAlgorithm)} value: {m_signingAlgorithm}");
        }
    }

    public PdfDigestAlgorithm DigestAlgorithm
    {
        get
        {
            if (m_signingAlgorithm == AzureSignatureAlgorithm.RS256)
                return PdfDigestAlgorithm.Sha256;

            if (m_signingAlgorithm == AzureSignatureAlgorithm.RS384)
                return PdfDigestAlgorithm.Sha384;

            if (m_signingAlgorithm == AzureSignatureAlgorithm.RS512)
                return PdfDigestAlgorithm.Sha512;

            throw new NotSupportedException($"Unsupported {nameof(SignatureAlgorithm)} value: {m_signingAlgorithm}");
        }
    }

    public byte[] Sign(byte[] message)
    {
        return m_client.SignData(m_signingAlgorithm, message).Signature;
    }
}

Infine, usa questa classe AzureSigner per firmare documenti PDF:

CryptographyClient cryptoClient = ..;
using X509Certificate2 cert = ..;
var signer = new AzureSigner(cryptoClient, SignatureAlgorithm.RS512);

using var pdf = new PdfDocument();

PdfPage page = pdf.Pages[0];
PdfSignatureField field = page.AddSignatureField(50, 50, 200, 200);

var options = new PdfSigningOptions(signer, [cert])
{
    DigestAlgorithm = signer.DigestAlgorithm,
    Field = field,
};

pdf.SignAndSave(options, ..);

Esplora il codice di esempio completo Firma documenti PDF utilizzando Azure Key Vault su GitHub.

Sign PDF documents using AWS KMS

AWS Key Management Service (KMS) è un altro archivio sicuro per chiavi crittografiche. La preparazione segue gli stessi passaggi di Azure Key Vault:

  1. Creare un account AWS.
  2. Creare un utente IAM.
  3. Aggiungere una chiave di firma.
  4. Consentire l'accesso alle chiavi per l'utente IAM selezionato.

Per AWS, dovrai usare il pacchetto NuGet AWSSDK.KeyManagementService in .NET. Il codice di esempio per la firma PDF è molto vicino allo scenario Azure:

using var pdf = new PdfDocument();

PdfPage page = pdf.Pages[0];
PdfSignatureField field = page.AddSignatureField(50, 50, 200, 200);

var signingAlgorithm = SigningAlgorithmSpec.RSASSA_PSS_SHA_512;
var signer = new AwsSigner("arn:aws:kms:YOUR-id", signingAlgorithm);
var options = new PdfSigningOptions(signer, [cert])
{
    DigestAlgorithm = signer.DigestAlgorithm,
    Field = field,
};

pdf.SignAndSave(options, ..);


class AwsSigner : IPdfSigner
{
    private readonly string m_keyId;
    private readonly SigningAlgorithmSpec m_signingAlgorithm;

    public AwsSigner(string keyId, SigningAlgorithmSpec signingAlgorithm)
    {
        m_keyId = keyId;
        m_signingAlgorithm = signingAlgorithm;
    }

    public PdfSignatureAlgorithm SignatureAlgorithm
    {
        get
        {
            if (m_signingAlgorithm == SigningAlgorithmSpec.RSASSA_PKCS1_V1_5_SHA_256 ||
                m_signingAlgorithm == SigningAlgorithmSpec.RSASSA_PKCS1_V1_5_SHA_384 ||
                m_signingAlgorithm == SigningAlgorithmSpec.RSASSA_PKCS1_V1_5_SHA_512)
                return PdfSignatureAlgorithm.Rsa;

            throw new NotSupportedException($"Unsupported {nameof(SigningAlgorithmSpec)} value: {m_signingAlgorithm}");
        }
    }

    public PdfDigestAlgorithm DigestAlgorithm
    {
        get
        {
            string alg = m_signingAlgorithm.Value;
            if (alg.EndsWith("256"))
                return PdfDigestAlgorithm.Sha256;

            if (alg.EndsWith("384"))
                return PdfDigestAlgorithm.Sha384;

            if (alg.EndsWith("512"))
                return PdfDigestAlgorithm.Sha512;

            throw new NotSupportedException($"Unsupported {nameof(SigningAlgorithmSpec)} value: {m_signingAlgorithm}");
        }
    }

    public byte[] Sign(byte[] message)
    {
        using var kmsClient = new AmazonKeyManagementServiceClient();
        using var stream = new MemoryStream(message);
        var signRequest = new SignRequest()
        {
            SigningAlgorithm = m_signingAlgorithm,
            KeyId = m_keyId,
            MessageType = MessageType.RAW,
            Message = stream,
        };
        SignResponse signResponse = kmsClient.SignAsync(signRequest).GetAwaiter().GetResult();
        return signResponse.Signature.ToArray();
    }
}

Il codice di esempio completo Firma documenti PDF utilizzando AWS KMS è disponibile anche su GitHub.

Conclusione

Sfrutta la libreria Docotic.Pdf per firmare documenti PDF usando token USB, smart card o HSM basati sul cloud. Per farlo, implementa l'interfaccia IPdfSigner in codice C# o VB.NET.

Scarica e prova gli esempi di codice per le firme digitali nei PDF da GitHub. Consulta gli articoli correlati per ulteriori informazioni:

Domande frequenti

Come firmo un PDF usando un token USB o una smart card?

Usa le librerie Docotic.Pdf e Pkcs11Interop .NET per firmare PDF con un token o una smart card. Consulta la sezione Firma documenti PDF usando il driver PKCS#11 in C# per maggiori dettagli.

Come uso SoftHSM con il mio token USB o la mia smart card?

SoftHSM simula un vero dispositivo HSM. Non ti serve SoftHSM se hai un token USB o una smart card. Usa invece il driver PKCS#11 fornito con il tuo dispositivo HSM.

Come firmo un documento PDF con una firma esterna?

Consulta le sezioni Firma documenti PDF usando Azure Key Vault e Firma documenti PDF usando AWS KMS. La firma PDF esterna con altri HSM basati sul cloud segue un processo simile.

Come uso Azure Key Vault in .NET?

Usa il pacchetto NuGet Azure.Security.KeyVault.Keys. Prova l'esempio di codice Firma documenti PDF utilizzando Azure Key Vault da GitHub.