Cette page peut contenir du texte traduit automatiquement.
Comment signer des PDF avec des jetons USB et des dispositifs HSM en C# et VB.NET
Les autorités de certification de confiance n’autorisent plus l’exportation des clés privées pour les certificats de signature de documents. À la place, les clés privées doivent être stockées dans du matériel sécurisé tel que des jetons USB, des cartes à puce ou des HSM basés sur le cloud.
Vous pouvez utiliser la bibliothèque Docotic.Pdf pour signer des documents PDF en .NET à l’aide de dispositifs HSM. Cet article décrit des intégrations avec Azure Key Vault, AWS KMS et du matériel compatible PKCS#11.
Vous pouvez obtenir la bibliothèque et une clé de licence gratuite à durée limitée sur la page Télécharger la bibliothèque PDF C# .NET.

Prérequis
Les exemples de code de cet article utilisent des certificats auto-signés pour signer des documents PDF. Par défaut, les visionneuses PDF ne font pas confiance à ces signatures. Les certificats auto-signés doivent être utilisés uniquement pour les tests, et non dans des environnements de production. Pour générer des signatures PDF fiables, utilisez des certificats de signature de documents émis par des autorités de certification tierces.
Obtenez le bon certificat
Privilégiez les certificats provenant d’entreprises figurant dans la Adobe Approved Trust List (AATL). Adobe Acrobat fait confiance par défaut aux certificats de ces entreprises et n’affichera pas l’avertissement « Certificate validity is unknown ».
Pour créer des documents conformes à l’UE (eIDAS), vous devez utiliser des certificats qualifiés émis par des fournisseurs répertoriés dans les European Union Trusted Lists (EUTL).
Apprenez à utiliser votre certificat dans .NET
Lorsque vous commandez un certificat de signature de documents, vous recevez généralement un accès à un dispositif HSM. Il peut s’agir d’un jeton USB physique ou d’une solution HSM basée sur le cloud.
Vous devez ensuite apprendre à signer des données avec ce HSM. C’est généralement la partie la plus délicate, car tous les fournisseurs cryptographiques sont différents. Vous devez suivre la documentation de votre jeton USB ou de votre API cloud.
Idéalement, vous devez trouver un SDK .NET correspondant. Ou, au minimum, trouver un SDK natif et l’utiliser via l’interopérabilité dans .NET.
Votre objectif est d’obtenir du code C# ou VB.NET capable de signer n’importe quels octets à l’aide de votre certificat.
API PDF pour la signature externe
Une fois que vous pouvez signer n’importe quels octets avec votre dispositif HSM, vous êtes prêt à signer des documents PDF avec Docotic.Pdf. Pour cela, implémentez l’interface IPdfSigner et utilisez-la pour la signature.
Implémentez l’interface IPdfSigner
IPdfSigner déclare deux membres. La propriété SignatureAlgorithm renvoie l’algorithme utilisé pour la signature. En général, vous utiliserez les algorithmes RSA ou ECDSA.
La méthode Sign est la partie clé du flux de signature externe. Docotic.Pdf fournit à cette méthode le condensat des octets d’un document PDF. Vous devez signer ce condensat avec votre dispositif HSM et renvoyer les octets d’une signature numérique. Notez que vous ne devez pas renvoyer ici un objet PKCS#7. Générez et renvoyez simplement la signature cryptographique.
Docotic.Pdf appelle la méthode Sign deux fois pour chaque signature. Le premier appel sert à calculer l’espace requis pour la signature. Le second appel sert à signer réellement le document.
Créez PdfSigningOptions pour la signature externe
Utilisez le constructeur PdfSigningOptions(IPdfSigner, X509Certificate2[]) pour signer des documents PDF avec votre implémentation de IPdfSigner. Obtenez une chaîne de certificats et fournissez-la comme second argument. Au moins un certificat est requis, et le certificat de signature doit être en premier.
La dernière pièce du puzzle est la propriété PdfSigningOptions.DigestAlgorithm. La valeur de cette propriété doit être cohérente avec IPdfSigner.SignatureAlgorithm et avec l’implémentation de IPdfSigner.Sign.
Examinons comment signer des PDF avec des signatures externes dans des scénarios courants.
Signez des documents PDF à l’aide d’un pilote PKCS#11 en C#
Si votre jeton USB cryptographique ou votre carte à puce est fourni avec un pilote PKCS#11, vous pouvez utiliser les bibliothèques Pkcs11Interop.X509Store ou Pkcs11Interop dans .NET. Pkcs11Interop est compatible avec les cartes à puce Atos CardOS, YubiKey PIV, SmartCard-HSM, SafeNet ProtectServer HSM et d’autres HSM.
L’exemple de code Signer des documents PDF à l'aide des pilotes PKCS#11 montre comment signer des documents PDF avec un jeton USB ou une carte à puce. Vous devrez personnaliser ces lignes :
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 configuration de notre exemple utilise SoftHSM2 comme émulateur d’un jeton USB. Dans les applications réelles, vous n’avez pas besoin de SoftHSM2. Utilisez plutôt le pilote fourni avec le jeton USB.
Signez des documents PDF à l’aide d’Azure Key Vault
Microsoft Azure Key Vault stocke de manière sécurisée les certificats et les clés. Vous devrez effectuer les préparations suivantes :
- Créez un compte Azure.
- Créez un utilisateur Azure.
- Créez un Key Vault.
- Autorisez l’accès au Key Vault pour l’utilisateur Azure sélectionné.
- Ajoutez un certificat de signature de documents au Key Vault. Vous pouvez importer des certificats depuis des autorités de certification intégrées.
Ensuite, utilisez le package NuGet Azure.Security.KeyVault.Keys pour signer dans .NET. Exemple de code C# pour signer avec une clé d’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;
Une implémentation IPdfSigner associée pourrait ressembler à ceci :
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;
}
}
Enfin, utilisez cette classe AzureSigner pour signer des documents 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, ..);
Consultez l’exemple de code Signer des documents PDF à l'aide d'Azure Key Vault complet sur GitHub.
Signez des documents PDF à l’aide d’AWS KMS
AWS Key Management Service (KMS) est un autre stockage sécurisé pour les clés cryptographiques. La préparation suit les mêmes étapes que pour Azure Key Vault :
- Créez un compte AWS.
- Créez un utilisateur IAM.
- Ajoutez une clé de signature.
- Autorisez l’accès aux clés pour l’utilisateur IAM sélectionné.
Pour AWS, vous devrez utiliser le package NuGet AWSSDK.KeyManagementService dans .NET. L’exemple de code pour la signature PDF est très proche du scénario 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();
}
}
L’exemple de code complet Signer des documents PDF à l'aide d'AWS KMS est également disponible sur GitHub.
Conclusion
Utilisez la bibliothèque Docotic.Pdf pour signer des documents PDF à l’aide de jetons USB, de cartes à puce ou de HSM basés sur le cloud. Pour cela, implémentez l’interface IPdfSigner dans du code C# ou VB.NET.
Téléchargez et essayez des exemples de code pour les signatures numériques dans PDF depuis GitHub. Consultez les articles associés pour plus d’informations :
- Signer des documents PDF en C# et VB.NET
- Vérifier la signature PDF en C# et VB.NET
- Ajouter des informations de validation à long terme (PAdES-LTV) aux signatures PDF en C#
Questions fréquemment posées
Comment signer un PDF à l’aide d’un jeton USB ou d’une carte à puce ?
Utilisez les bibliothèques .NET Docotic.Pdf et Pkcs11Interop pour signer des PDF avec un jeton ou une carte à puce. Reportez-vous à la section Signez des documents PDF à l’aide d’un pilote PKCS#11 en C# pour plus de détails.
Comment utiliser SoftHSM avec mon jeton USB ou ma carte à puce ?
SoftHSM simule un véritable dispositif HSM. Vous n’avez pas besoin de SoftHSM si vous disposez d’un jeton USB ou d’une carte à puce. Utilisez plutôt le pilote PKCS#11 fourni avec votre dispositif HSM.
Comment signer un document PDF avec une signature externe ?
Consultez les sections Signez des documents PDF à l’aide d’Azure Key Vault et Signez des documents PDF à l’aide d’AWS KMS. La signature PDF externe avec d’autres HSM basés sur le cloud suit un processus similaire.
Comment utiliser Azure Key Vault dans .NET ?
Utilisez le package NuGet Azure.Security.KeyVault.Keys. Essayez l’exemple de code Signer des documents PDF à l'aide d'Azure Key Vault sur GitHub.