OpenSSL Signing with EC’s PKCS#11 Wrapper

When it comes to securing digital communications or verifying the integrity of data, OpenSSL is one of the go-to tools for developers and security professionals. Whether you’re signing files, creating certificates, or verifying digital signatures, OpenSSL provides a flexible and powerful command-line interface to handle cryptographic operations.
But there’s a catch—by default, OpenSSL works with software-based keys stored on disk. While that may be fine for development or internal testing, it’s not ideal for production environments where the security of private keys is critical. This is where PKCS#11 steps in.
PKCS#11 is a standard API that lets software interact with cryptographic tokens like smart cards, USB tokens, and HSMs (Hardware Security Modules). These tokens are designed to store keys securely and perform operations like signing or encryption directly within the device—meaning your private key never leaves the hardware.
Now, integrating OpenSSL with a PKCS#11-compatible device isn’t always plug-and-play. That’s why we use a PKCS#11 wrapper, which acts as a bridge between OpenSSL and the hardware-backed cryptographic provider. The wrapper makes it possible to run familiar OpenSSL commands while offloading the actual signing operations to the HSM or token.
In this blog, I’ll walk you through how to perform OpenSSL-based signing using CodeSign Secure and Encryption Consulting’s PKCS#11 wrapper on both Ubuntu and Windows, covering setup, configuration, and execution. Whether you’re working in enterprise environments or building a secure signing process for your app, this setup will help you strengthen your cryptographic hygiene without a steep learning curve.
Step 1: Go to EC CodeSign Secure’s v3.01 Signing Tools section and download the PKCS11 Wrapper for Ubuntu.
Step 2: After that, generate a P12 Authentication certificate from the System Setup > User > Generate Authentication Certificate dropdown.
Step 3: Go to your Ubuntu client system and edit the configuration files (ec_pkcs11client.ini and pkcs11properties.cfg) downloaded in the PKCS11 Wrapper.
Now, let’s install some prerequisites in your client system to run the PKCS11 Wrapper.
Step 1: Install OpenSSL:sudo apt install -y openssl libengine-pkcs11-openssl gnutls-bin xxd
Step 2: Create a config file for PKCS#11
Step 3: Enter the appropriate details in the config file:
openssl_conf = openssl_init
[openssl_init]
engines = engine_section
[engine_section]
pkcs11 = pkcs11_section
[pkcs11_section]
#Path to the OpenSSL PKCS11 Engine
dynamic_path = “<Path to libpkcs11.so>”
MODULE_PATH = “<Path to ec_pkcs11client.so>”
The ec_pkcs11client.so path depends on where you store the file.
The libpkcs11.so path depends on your Linux distribution and version:
Step 4: Set the environment variable for openssl.conf file
export OPENSSL_CONF=<path to openssl.conf>
Now that all the configurations and prerequisites have been installed. Let’s perform the signing operation first.
The signing command will look something like this (ensure you run this command only inside the folder where your PKCS11 Wrapper is installed):
openssl pkeyutl -engine pkcs11 -sign -in <path of the file you want to sign> -inkey “pkcs11:object=<private key alias>;type=private” -keyform engine -out <path of the Signed file>
For Example: openssl pkeyutl -engine pkcs11 -sign -in testfile.txt -inkey “pkcs11:object=CertEnrollTest;type=private” -keyform engine -out readme.sign.sha256
After successfully signing the file, let’s verify it using this command:
openssl pkeyutl -engine pkcs11 -verify -in <path of the file you want to sign> -inkey “pkcs11:object=<private key alias>;type=private” -keyform engine -sigfile <path of the Signed file>
For example: openssl pkeyutl -engine pkcs11 -verify -in testfile.txt -inkey “pkcs11:object=CertEnrollTest;type=private” -keyform engine -sigfile readme.sign.sha256
Step 1: Go to EC CodeSign Secure’s v3.01’s Signing Tools section and download the PKCS11 Wrapper for Windows.
Step 2: After that, generate a P12 Authentication certificate from the System Setup > User > Generate Authentication Certificate dropdown.
Step 3: Go to your Windows client system and edit the configuration files (ec_pkcs11client.ini and pkcs11properties.cfg) downloaded in the PKCS11 Wrapper.
Now, let’s install some prerequisites in your client system to run the PKCS11 Wrapper.
Step 1: Download and install OpenSSL on your system from here.
Step 2: Manually compile the OpenSSL PKCS#11 using these methods
Use this command:
pacman -S git pkg-config libtool autoconf automake make gcc openssl-devel git clone https://github.com/OpenSC/libp11.git cd libp11 autoreconf -fi ./configure –prefix=/usr/local make && make install
Step 3: In the configuration file (openssl.cnf) in the folder C:\Program Files\Common Files\SSL
Add these lines:
openssl_conf = openssl_init
[openssl_init]
engines = engine_section
[engine_section]
pkcs11 = pkcs11_section
[pkcs11_section]
#Path to the Compiled OpenSSL PKCS11 from OpenSC – libp11
dynamic_path = <Path to compiled libp11 pkcs11.dll>MODULE_PATH = <Path to ec_pkcs11client.dll>
Now that all the configurations and prerequisites have been installed. Let’s perform the signing operation first.
The signing command will look something like this (ensure you run this command only inside the folder where your PKCS11 Wrapper is installed):
openssl dgst -engine pkcs11 -keyform engine -sign “pkcs11:object=<private key alias>;type=public” -sha256 -out <path of signed file> <path of file to sign>
For Example:
openssl dgst -engine pkcs11 -keyform engine -sign “pkcs11:object=CertEnrollTest;type=public” -sha256 -out test-signed.bin testfile.txt
After successfully signing the file, let’s verify it using this command:
openssl dgst -engine pkcs11 -keyform engine -verify “pkcs11:object=<private key alias>;type=public” -sha256 -signature <path of signed file> <path of file to sign>
For example:
openssl dgst -engine pkcs11 -keyform engine -verify “pkcs11:object=CertEnrollTest;type=public” -sha256 -signature test-signed.bin testfile.txt
When you’re dealing with cryptographic operations—especially digital signing—the protection of your private keys is absolutely non-negotiable. A leaked or compromised private key is pretty much a worst-case scenario because it opens the door to impersonation, unauthorized access, and a whole lot of trust issues.
So, let’s talk about a few best practices to help keep your keys (and your reputation) safe:
At the end of the day, cryptographic tools are only as secure as the way they’re used. PKCS#11 gives you the power to offload critical operations to hardware—but you’ve still got to respect the basics: protect your keys, limit access, and always think one step ahead of an attacker.
Signing with OpenSSL using PKCS#11 might seem a bit technical at first, but once you’ve set it up—on either Ubuntu or Windows—it’s a smooth and secure workflow. By integrating a PKCS#11 wrapper, you can shift sensitive signing operations away from the software layer and into secure hardware like HSMs or tokens. This not only protects your private keys but also helps you meet compliance standards and security best practices.
If you’re looking for a streamlined way to get started, EC’s PKCS#11 wrapper makes the integration process much simpler. It’s built to be reliable, cross-platform, and compatible with a wide range of HSMs—so you can focus more on securing your operations and less on dealing with low-level plumbing. In today’s threat landscape, protecting your keys is protecting your business. Whether you’re signing code, documents, or certificates, combining OpenSSL with a robust PKCS#11 wrapper like EC’s is a smart, future-proof move.