Sign a PDF with PKCS#11 in C#
PKCS#11 signing keeps the private key inside a hardware security module, USB token, or smart card. The application sends signing requests to the vendor module instead of loading a P12/PFX file.
Use this workflow when policy requires hardware-backed keys or centralized key custody.
This guide shows how to:
- Load a PDF
- Select a signing key from a PKCS#11 module
- Create a PAdES signature with the selected key
This sample requires a vendor PKCS#11 module, an initialized token, and a signing certificate on that token. Replace the module path, PIN, token label, and key label with values from your environment.
Prepare the project
Register the SDK license before running signing operations. For setup details, refer to the getting started with .NET SDK guide.
using System;using GdPicture14;
void CheckStatus(GdPictureStatus status, string operation){ if (status != GdPictureStatus.OK) { throw new InvalidOperationException($"{operation} failed. Status: {status}"); }}
LicenseManager license = new LicenseManager();license.RegisterKEY(""); // Set your license keyConfigure PKCS#11 access
Set the module path and token selection values for your hardware or software token:
string pkcs11ModulePath = @"/usr/lib/softhsm/libsofthsm2.so";string userPin = "123456";string tokenLabel = "document-signing-token";string keyLabel = "pdf-signing-key";On Windows, the module path usually points to a DLL provided by the token vendor.
Load the PDF document
Load the source PDF document:
using GdPicturePDF pdf = new GdPicturePDF();
CheckStatus(pdf.LoadFromFile(@"input.pdf", false), "LoadFromFile");Select the PKCS#11 signing key
Configure the signing certificate from the token:
CheckStatus(pdf.SetSignatureCertificateFromPKCS11(pkcs11ModulePath, userPin, tokenLabel, keyLabel), "SetSignatureCertificateFromPKCS11");SetSignatureCertificateFromPKCS11 loads the certificate and private-key handle from the PKCS#11 module. The private key remains inside the token.
Configure signature metadata
Set the visible signature metadata and cryptographic options:
CheckStatus(pdf.SetSignatureInfo("Nutrient", "Hardware-backed PDF signature", "Toulouse", "sales@nutrient.io"), "SetSignatureInfo");CheckStatus(pdf.SetSignatureHash(PdfSignatureHash.SHA256), "SetSignatureHash");CheckStatus(pdf.SetSignaturePAdESLevel(PdfSignaturePAdESLevel.PAdESBaselineB), "SetSignaturePAdESLevel");Apply the signature
Create the signed PDF:
CheckStatus(pdf.ApplySignature(@"signed-pkcs11.pdf", PdfSignatureMode.PdfSignatureModeAdobeCADES, true), "ApplySignature");Error handling
Check every GdPictureStatus value. Common PKCS#11 failures include an invalid module path, an incorrect PIN, no present token, a missing key label, and a token certificate that doesn’t permit document signing.
Conclusion
This workflow signs a PDF with a key managed by a PKCS#11 module, keeping the private key outside the application process.