PDF digital signature with PKCS#11 (Cryptoki) device in C# and VB.NET

PKCS#11 is one of the Public-Key Cryptography Standards (PKCS) that defines a platform-independent API (called "Cryptoki") to cryptographic devices, such as hardware security modules (HSM) and smart cards.

With GemBox.Pdf, you can digitally sign PDF files using a PKCS#11/Cryptoki device that conforms to PKCS#11 specification in your C# or VB.NET application.

Before reviewing the output of the following example in your Adobe Acrobat Reader, please read the Digital ID notes.

The following example shows how to digitally sign a PDF file using a PKCS#11/Cryptoki device.

PDF file digitally signed with PKCS#11/Cryptoki device using GemBox.Pdf
Screenshot of PDF file digitally signed with PKCS#11/Cryptoki device using GemBox.Pdf
Upload your file (Drag file here)
using System;
using System.IO;
using System.Linq;
using GemBox.Pdf;
using GemBox.Pdf.Forms;
using GemBox.Pdf.Security;

class Program
{
    static void Main()
    {
        // Extract GemBoxPkcs11SoftwareModule from ZIP archive and setup environment variable with path to configuration file.
        // Required only for SoftHSM device used in this example. Not required for yours PKCS#11/Cryptoki device.
        var pkcs11SoftwareModuleDirectory = "GemBoxPkcs11SoftwareModule";
        System.IO.Compression.ZipFile.ExtractToDirectory("%#GemBoxPkcs11SoftwareModule.zip%", pkcs11SoftwareModuleDirectory);
        Environment.SetEnvironmentVariable("SOFTHSM2_CONF", Path.Combine(pkcs11SoftwareModuleDirectory, "softhsm2.conf"));

        // Specify path to PKCS#11/Cryptoki library, depending on the runtime architecture (64-bit or 32-bit).
        var libraryPath = Path.Combine(pkcs11SoftwareModuleDirectory, IntPtr.Size == 8 ? "softhsm2-x64.dll" : "softhsm2.dll");

        // If using the Professional version, put your serial key below.
        ComponentInfo.SetLicense("FREE-LIMITED-KEY");

        using (var pkcs11Module = new PdfPkcs11Module(libraryPath))
        {
            // Get a token from PKCS#11/Cryptoki device.
            var token = pkcs11Module.Tokens.Single(t => t.TokenLabel == "%InputDigitalId[0]%");

            // Login to the token to get access to protected cryptographic functions.
            token.Login("%InputDigitalId[1]%");

            // Get a digital ID from PKCS#11/Cryptoki device token.
            var digitalId = token.DigitalIds.Single(id => id.Certificate.SubjectCommonName == "%InputDigitalId[2]%");

            using (var document = PdfDocument.Load("%InputFileName%"))
            {
                // Add a visible signature field to the first page of the PDF document.
                var signatureField = document.Form.Fields.AddSignature(document.Pages[0], 300, 500, 250, 50);

                // Create a PDF signer that will create the digital signature.
                var signer = new PdfSigner(digitalId);

                // Adobe Acrobat Reader currently doesn't download certificate chain
                // so we will also embed certificate of intermediate Certificate Authority in the signature.
                // (see https://community.adobe.com/t5/acrobat/signature-validation-using-aia-extension-not-enabled-by-default/td-p/10729647)
                var intermediateCA = token.DigitalIds.Single(id => id.Certificate.SubjectCommonName == "%InputDigitalId[3]%").Certificate;
                signer.ValidationInfo = new PdfSignatureValidationInfo(new PdfCertificate[] { intermediateCA }, null, null);

                // Initiate signing of a PDF file with the specified signer.
                signatureField.Sign(signer);

                // Finish signing of a PDF file.
                document.Save("Digital Signature PKCS#11.pdf");
            }

            token.Logout();
        }
    }
}
Imports System
Imports System.IO
Imports System.Linq
Imports GemBox.Pdf
Imports GemBox.Pdf.Forms
Imports GemBox.Pdf.Security

Module Program

    Sub Main()

        ' Extract GemBoxPkcs11SoftwareModule from ZIP archive and setup environment variable with path to configuration file.
        ' Required only for SoftHSM device used in this example. Not required for yours PKCS#11/Cryptoki device.
        Dim pkcs11SoftwareModuleDirectory = "GemBoxPkcs11SoftwareModule"
        System.IO.Compression.ZipFile.ExtractToDirectory("%#GemBoxPkcs11SoftwareModule.zip%", pkcs11SoftwareModuleDirectory)
        Environment.SetEnvironmentVariable("SOFTHSM2_CONF", Path.Combine(pkcs11SoftwareModuleDirectory, "softhsm2.conf"))

        ' Specify path to PKCS#11/Cryptoki library, depending on the runtime architecture (64-bit or 32-bit).
        Dim libraryPath = Path.Combine(pkcs11SoftwareModuleDirectory, If(IntPtr.Size = 8, "softhsm2-x64.dll", "softhsm2.dll"))

        ' If using the Professional version, put your serial key below.
        ComponentInfo.SetLicense("FREE-LIMITED-KEY")

        Using pkcs11Module = New PdfPkcs11Module(libraryPath)

            ' Get a token from PKCS#11/Cryptoki device.
            Dim token = pkcs11Module.Tokens.Single(Function(t) t.TokenLabel = "%InputDigitalId[0]%")

            ' Login to the token to get access to protected cryptographic functions.
            token.Login("%InputDigitalId[1]%")

            ' Get a digital ID from PKCS#11/Cryptoki device token.
            Dim digitalId = token.DigitalIds.Single(Function(id) id.Certificate.SubjectCommonName = "%InputDigitalId[2]%")

            Using document = PdfDocument.Load("%InputFileName%")

                ' Add a visible signature field to the first page of the PDF document.
                Dim signatureField = document.Form.Fields.AddSignature(document.Pages(0), 300, 500, 250, 50)

                ' Create a PDF signer that will create the digital signature.
                Dim signer = New PdfSigner(digitalId)

                ' Adobe Acrobat Reader currently doesn't download certificate chain
                ' so we will also embed certificate of intermediate Certificate Authority in the signature.
                ' (see https://community.adobe.com/t5/acrobat/signature-validation-using-aia-extension-Not-enabled-by-default/td-p/10729647)
                Dim intermediateCA = token.DigitalIds.Single(Function(id) id.Certificate.SubjectCommonName = "%InputDigitalId[3]%").Certificate
                signer.ValidationInfo = New PdfSignatureValidationInfo(New PdfCertificate() {intermediateCA}, Nothing, Nothing)

                ' Initiate signing of a PDF file with the specified signer.
                signatureField.Sign(signer)

                'Finish signing of a PDF file.
                document.Save("Digital Signature PKCS#11.pdf")
            End Using

            token.Logout()
        End Using
    End Sub
End Module

The PKCS#11/Cryptoki device used in the example is SoftHSM (software implementation of a generic cryptographic device with a PKCS#11 interface) configured to contain digital IDs and certificates described in the next subsection.

Digital ID notes

Digital IDs used in the preceding example are part of a simple Public Key Infrastructure (PKI) created just for this demonstration which contains the following hierarchy of certificates:

  • Root Certificate Authority certificate GemBoxCA.crt
    • Intermediate Certificate Authority certificate GemBoxRSA.crt
      • Digital ID GemBoxRSA4096 with 4096-bit RSA private key and certificate GemBoxRSA4096.crt (contained in the token labeled GemBoxRSAToken of GemBoxPkcs11SoftwareModule device)
    • Intermediate Certificate Authority certificate GemBoxECDsa.crt
      • Digital ID GemBoxECDsa521 with 521-bit Elliptic Curve (ECDsa) private key and certificate GemBoxECDsa521.crt (contained in the token labeled GemBoxECDsaToken of GemBoxPkcs11SoftwareModule device)

To get a valid signature in your Adobe Acrobat Reader as seen in the screenshot above, you will have to add GemBoxCA.crt certificate to the list of Trusted Certificates using the following steps:

  1. Download GemBoxCA.crt certificate.
  2. Open Adobe Acrobat Reader, select Edit > Preferences > Signatures. In Identities & Trusted Certificates click More.
  3. Select Trusted Certificates and click Import. Browse to the downloaded GemBoxCA.crt certificate and click Import.
  4. Select the imported GemBoxCA <info@gemboxsofware.com> certificate, click Edit Trust and add a check-mark next to Use this certificate as a trusted root.
  5. You can now delete the downloaded GemBoxCA.crt certificate. You can always later remove GemBoxCA <info@gemboxsofware.com> from Trusted Certificates by selecting it from the list of Trusted Certificates and clicking Remove.

Otherwise, to get a valid signature in any Adobe Acrobat Reader, your digital ID would have to be an AATL-enabled signing credential.

See also


Next steps

GemBox.Pdf is a .NET component that enables developers to read, merge and split PDF files or execute low-level object manipulations from .NET applications in a simple and efficient way.

Download Buy