Code Signing Reading Time: 7 Min

OpenSSL Signing with EC’s PKCS#11 Wrapper

Introduction

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.

OpenSSL PKCS11 – Ubuntu

Installation on Client System

Step 1: Go to EC CodeSign Secure’s v3.01 Signing Tools section and download the PKCS11 Wrapper for Ubuntu.

Signing Tools

Step 2: After that, generate a P12 Authentication certificate from the System Setup > User > Generate Authentication Certificate dropdown.

P12 Certificate

Step 3: Go to your Ubuntu client system and edit the configuration files (ec_pkcs11client.ini and pkcs11properties.cfg) downloaded in the PKCS11 Wrapper.

edit config files

Prerequisites for Ubuntu System

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

install OpenSSL

Step 2: Create a config file for PKCS#11

create Config file

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>”

appropriate details

The ec_pkcs11client.so path depends on where you store the file.

The libpkcs11.so path depends on your Linux distribution and version:

  • Ubuntu 18.04: /usr/lib/x86_64-linux-gnu/engines-1.1/libpkcs11.so
  • Ubuntu 20.04: /usr/lib/x86_64-linux-gnu/engines-1.1/libpkcs11.so
  • Ubuntu 22.04: /usr/lib/x86_64-linux-gnu/engines-3/libpkcs11.so

Step 4: Set the environment variable for openssl.conf file

export OPENSSL_CONF=<path to openssl.conf>

Set the environment variable

Perform Signing and Verification using PKCS11 Wrapper

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

Signing and Verification

OpenSSL PKCS11 – Windows

Installation on Client System

Step 1: Go to EC CodeSign Secure’s v3.01’s Signing Tools section and download the PKCS11 Wrapper for Windows.

Signing Tools section

Step 2: After that, generate a P12 Authentication certificate from the System Setup > User > Generate Authentication Certificate dropdown.

P12 Authentication certificate

Step 3: Go to your Windows client system and edit the configuration files (ec_pkcs11client.ini and pkcs11properties.cfg) downloaded in the PKCS11 Wrapper.

edit the configuration files

edit the configuration files

edit the configuration files

Prerequisites for Windows System

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.

 Download and install OpenSSL

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>

configuration file
configuration file

Perform Signing and Verification using PKCS11 Wrapper

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

Signing and Verification

Security Considerations

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:

  • Never store private keys in plain files: It might be convenient, but storing private keys as flat files on disk (even with file system permissions) is risky. All it takes is a misconfigured backup system or a curious admin to accidentally expose them. Instead, use secure key storage mechanisms—preferably hardware-backed.
  • Use HSMs or secure tokens whenever possible: Hardware Security Modules (HSMs) and smart cards are built specifically for secure key storage. They don’t just store keys—they perform operations (like signing or decryption) inside the device, so the private key never actually leaves. This adds a strong layer of protection, especially against malware or insider threats.
  • Lock down access to your PKCS#11 modules: Make sure only authorized users or services can talk to the PKCS#11 interface. Use PINs, role-based access, and proper auditing to prevent abuse. If your wrapper or HSM vendor supports logging, enable it—you’ll want a clear trail of who accessed what and when.
  • Avoid leaving tokens unlocked: It’s tempting to script things and leave tokens unlocked to “keep things running,” but that’s risky. Instead, look into automated unlock mechanisms that still respect session isolation or tools that securely cache credentials for short durations with tight access controls.
  • Validate what you’re signing: It sounds obvious, but make sure you’re not signing random or malicious files by accident. Build in sanity checks or use pre-signing verification steps to ensure only approved content goes through your signing flow.

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.

Conclusion

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.

Free Downloads

Datasheet of Code Signing Solution

Code signing is a process to confirm the authenticity and originality of digital information such as a piece of software code.

Download

About the Author

Subhayu Roy's profile picture

Subhayu is a cybersecurity consultant specializing in Public Key Infrastructure (PKI) and Hardware Security Modules (HSMs) and is the lead developer for CodeSign Secure. At CodeSign Secure, his enthusiasm for coding meets his commitment to cybersecurity, with a fresh perspective and a drive to learn and grow in every project and work as a consultant for high-profile clients.

Explore the full range of services offered by Encryption Consulting.

Feel free to schedule a demo to gain a comprehensive understanding of all the services Encryption Consulting provides.

Request a demo