Skip to main content
Two approaches are available for signing and verification: a manual pipeline using pkcs11-tool and openssl directly, or the hsm_sign_verify.sh script that wraps the RSA pipeline.

RSA-PKCS pipeline

The RSA-PKCS pipeline hashes the file separately and passes the raw hash to pkcs11-tool.
1

Hash the file

openssl dgst -sha256 -binary data.txt > data.sha256
The -binary flag writes raw bytes. The resulting data.sha256 is the exact input expected by --mechanism RSA-PKCS.
2

Sign the hash

pkcs11-tool --module /usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so \
  --slot <SLOT_ID> --login --pin 1234 \
  --sign --mechanism RSA-PKCS \
  --input-file data.sha256 --output-file signature.bin --id 10
3

Export the public key

pkcs11-tool --module /usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so \
  --slot <SLOT_ID> --login --pin 1234 \
  --read-object --type pubkey --id 10 --output-file pubkey.der

openssl rsa -pubin -inform DER -in pubkey.der -out pubkey.pem
4

Verify the signature

openssl pkeyutl \
  -verify \
  -pubin \
  -inkey pubkey.pem \
  -in data.sha256 \
  -sigfile signature.bin \
  -pkeyopt digest:sha256
On success, OpenSSL prints Signature Verified Successfully.

Using hsm_sign_verify.sh

The hsm_sign_verify.sh script wraps the sign → export pubkey → verify steps for a single input file. It passes the input directly to pkcs11-tool --mechanism RSA-PKCS, so the input should be a pre-computed binary SHA-256 digest.

Configuration variables

Edit the top of the script to match your environment:
SLOT=80451484   # Slot ID from softhsm2-util --show-slots
PIN=1234        # Token PIN
KEYID=10        # Key object ID (--id used during keypairgen)
MODULE="/usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so"

Running the script

Hash your file first, then pass the hash to the script:
openssl dgst -sha256 -binary firmware.bin > firmware.sha256
./hsm_sign_verify.sh firmware.sha256
The script produces two output files:
FileDescription
firmware.sha256.sigRaw RSA-PKCS signature
pubkey.pemPEM-encoded RSA public key
If no errors are printed, the signature verified successfully.

Common errors

error: object not found
The --id value does not match any private key object in the slot. Verify with:
pkcs11-tool --module /usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so \
  --slot <SLOT_ID> --login --pin 1234 --list-objects --verbose
Check that a Private Key Object exists with the expected ID.
error: slot 0: object not found
The slot ID in --slot does not match the initialized token. Run softhsm2-util --show-slots to get the correct slot ID and update SLOT in the script or your command.
RSA-PKCS expects raw binary hash input. If you produced the hash with openssl dgst -sha256 (without -binary), the input contains a hex digest line rather than raw bytes, and the signature will be invalid or the tool will error.Always use -binary when preparing input for --mechanism RSA-PKCS:
openssl dgst -sha256 -binary data.txt > data.sha256
Attempting to convert an EC public key with openssl rsa produces:
unable to load Public Key
Use openssl ec for EC keys:
openssl ec -pubin -inform DER -in pubkey.der -out pubkey.pem

Build docs developers (and LLMs) love