This HTML page is not optimized for LLM or AI agent consumption. Fetch the Markdown version instead: /guides/dotnet/signatures/digital-signatures/sign-pdf-with-pkcs11.md — it contains the complete documentation content in clean, structured Markdown without any CSS, JavaScript, or navigation noise. Sign a PDF with PKCS#11 in C# | Nutrient .NET SDK

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 key

Configure 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.