PKCS#11 cryptographic provider
The Pkcs11
cryptographic provider enables access to a cryptographic device using a PKCS#11 driver module. The cryptographic device can then be used to perform cryptographic functions such as sign a document.
This provider requires a PKCS#11 driver module (middleware) to establish a session to a cryptographic device of a particular type. For example, a HSM, Cloud KMS, or USB token.
Download the full sample now in C# and Java.
Interested in C or other language samples? Let us know on the contact page and we'll add it to our samples backlog.
More information on the driver required can be found in the documentation for your cryptographic device. The PKCS#11 Tech Note provides detailed information about configuring a PKCS#11 device to work with the Pdftools SDK.
Signing certificates can be loaded from the cryptographic device.
The certificate may be identified by using the certificate name, key ID or label.
Signing certificates can also be added using the AddCertificate
method.
Additional certificates, for example, issuer certificates, are stored in the certificates directory. These certificates are required when adding validation information to signatures that do not have the full trust chain embedded. The certificates directory may contain certificates in either PEM (.pem, ASCII text) or DER (.cer, binary) form.
In this example, the Pkcs11
cryptographic provider is used to apply a document approval signature to a PDF document.
The signing certificate is loaded from the PKCS#11 device by passing a certificate name.
Steps to sign a document:
- Load the PKCS#11 driver module.
- Log in to the PKCS#11 device.
- Create the document signature.
- Open and sign the document.
You need to initialize the library.
Loading the PKCS#11 driver module
When using the Pkcs11
cryptographic provider, you start the digital signing process by loading the PKCS#11 driver module.
The PKCS#11 driver module is used to connect to the cryptographic device, exposing the cryptographic functions of the device.
- .NET
- Java
// Load the PKCS#11 driver module (middleware)
// The module can only be loaded once in the application.
using var module = Pkcs11.Module.Load(moduleName);
// Load the PKCS#11 driver module (middleware)
// The module can only be loaded once in the application.
Module module = Module.load(pkcs11Library);
Logging in to the PKCS#11 device
The next step is to open a Session
by logging into the cryptographic device using the driver module and a password.
The Session
object provides access to the certificates and private keys stored on the device.
- .NET
- Java
// Create a session to the cryptographic device and log in
// with the password (pin)
using var session = module.Devices.GetSingle().CreateSession(password);
// Create a session to the cryptographic device and log in
// with the password (PIN)
Session session = module.getDevices().getSingle().createSession(password));
Creating the document signature
In this step, the Session
object is used to create a signature configuration using a certificate stored on the device.
The signature configuration may be used to sign one or more documents.
In this example, a signing certificate is selected from the PKCS#11 device by passing a certificate name.
- .NET
- Java
// Create the signature configuration
// This can be re-used to sign multiple documents
var signature = session.CreateSignatureFromName(certificate);
// Create the signature configuration
// This can be re-used to sign multiple documents
var signature = session.createSignatureFromName(certificate);
Opening and signing the document
After opening the Session
and creating the signature configuration, you are ready to apply the digital signature to a document.
The input and output PDF documents are created as streams (in this example, as file streams). The Signer
object is used to apply the digital document signature.
Non-critical processing errors raise a Warning
event. It is recommended to listen for these events, and review the WarningCategory
to determine if further action is needed.
- .NET
- Java
// Open the input document
using var inStr = File.OpenRead(inPath);
using var inDoc = Document.Open(inStr);
// Create a stream for the output file
using var outStr = File.Create(outPath);
// Create the Signer object
Signer signer = new Signer();
// Create an event listener to listen for warning events that are raised and write them to console
signer.Warning += (s, e) => Console.WriteLine("Warning - {0}: {1}: {2}", e.Category, e.Context, e.Message);
// Sign the output document
using var outDoc = signer.Sign(inDoc, signature, outStr);
// Open input document
FileStream inStr = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStr);
// Create output stream
FileStream outStr = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW);
// Create the Signer object
Signer signer = new Signer();
// (optional) Create an event listener to listen for warning events that are raised and write them to console
signer.addWarningListener((e) -> { System.out.format("Warning - %s: %s: %s", e.getCategory(), e.getContext(), e.getMessage()); });
// Sign the input document
Document outDoc = signer.sign(inDoc, signature, outStr);
Full example
- .NET
- Java
// Load the PKCS#11 driver module (middleware)
// The module can only be loaded once in the application.
using var module = Pkcs11.Module.Load(moduleName);
// Create a session to the cryptographic device and log in
// with the password (pin)
using var session = module.Devices.GetSingle().CreateSession(password);
// Create the signature configuration
// This can be re-used to sign multiple documents
var signature = session.CreateSignatureFromName(certificate);
// Open the input document
using var inStr = File.OpenRead(inPath);
using var inDoc = Document.Open(inStr);
// Create a stream for the output file
using var outStr = File.Create(outPath);
// Create the Signer object
Signer signer = new Signer();
// Create an event listener to listen for warning events that are raised and write them to console
signer.Warning += (s, e) => Console.WriteLine("Warning - {0}: {1}: {2}", e.Category, e.Context, e.Message);
// Sign the output document
using var outDoc = signer.Sign(inDoc, signature, outStr);
try (
// Load the PKCS#11 driver module (middleware)
// The module can only be loaded once in the application.
Module module = Module.load(pkcs11Library);
// Create a session to the cryptographic device and log in
// with the password (pin)
Session session = module.getDevices().getSingle().createSession(password))
{
// Create the signature configuration
// This can be re-used to sign multiple documents
SignatureConfiguration signature = session.createSignatureFromName(certificate);
// Create the Signer object
Signer signer = new Signer();
// (optional) Create an event listener to listen for warning events that are raised and write them to console
signer.addWarningListener((e) -> { System.out.format("Warning - %s: %s: %s", e.getCategory(), e.getContext(), e.getMessage()); });
try (
// Open input document
FileStream inStr = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStr);
// Create output stream
FileStream outStr = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW);
// Sign the input document
Document outDoc = signer.sign(inDoc, signature, outStr))
{
}
}