⚠️ Implementation status: Some CLI commands referenced in this recipe (e.g.,
threshold refresh,share-export,transparency ots) are not yet implemented. The underlying crate APIs exist; the CLI wrappers are in progress for a future release. Use the Rust API directly or wait for the CLI command.
Drop-in PKCS#11 HSM replacement
Problem: Your application consumes an HSM via PKCS#11. You want the security of threshold signing without rewriting the application.
Solution
confium-pkcs11-server is a drop-in PKCS#11 module that dispatches sign / verify / decrypt calls into a Confium threshold signing cluster. The application sees a normal PKCS#11 token; behind the scenes, every signing op requires T-of-N quorum.
Architecture
┌────────────────────────────────────────────────────────────────────┐
│ Application (e.g., OpenSSL, Java JCE, Thunderbird) │
└────────────────────────────────┬───────────────────────────────────┘
│ PKCS#11 v3.0 API
▼
┌────────────────────────────────────────────────────────────────────┐
│ confium-pkcs11-server │
│ (drop-in module) │
└────────────────────────────────┬───────────────────────────────────┘
│ Internal RPC
▼
┌────────────────────────────────────────────────────────────────────┐
│ Confium coordinator + signerd cluster (2-of-3 CMP20) │
└────────────────────────────────────────────────────────────────────┘
The application never sees Confium directly. It just talks PKCS#11.
Quickstart
1. Stand up the signing cluster
See deploy-signerd-k8s.mdx. You need a working confium-coordinator + N signerd replicas before installing the PKCS#11 server.
2. Install the PKCS#11 module
docker pull ghcr.io/confium/pkcs11-server:latest
# Run as a local daemon; the PKCS#11 module will RPC to it
docker run -d \
--name confium-pkcs11 \
-p 2345:2345 \
-v $(pwd)/pkcs11.toml:/etc/confium/pkcs11.toml \
ghcr.io/confium/pkcs11-server:latest
3. Configure
# pkcs11.toml
[server]
listen = "127.0.0.1:2345"
[token."Production Signing Key"]
label = "Production Signing Key"
threshold_key_id = "production-signing-key"
coordinator_url = "http://confium-coordinator:7000"
[token."Backup Signing Key"]
label = "Backup Signing Key"
threshold_key_id = "backup-signing-key"
coordinator_url = "http://confium-coordinator:7000"
4. Install the client module
The PKCS#11 module is a stub library your application loads. It forwards calls to the local confium-pkcs11-server.
# Linux
sudo cp libconfium_pkcs11.so /usr/lib/pkcs11/
sudo ldconfig
# Configure OpenSSL to use it
sudo tee /etc/openssl-pkcs11.conf <<EOF
[pkcs11]
module = /usr/lib/pkcs11/libconfium_pkcs11.so
init = 1
EOF
5. Use it
Your application’s PKCS#11 calls now dispatch into Confium:
# OpenSSL: use the Confium-backed token
openssl req -engine pkcs11 -keyform engine \
-key 'pkcs11:token=Production Signing Key' \
-new -x509 -days 365 -out cert.pem
# The signing op requires the threshold quorum (2-of-3 signerd
# replicas must respond). OpenSSL sees it as a normal PKCS#11 sign.
What this gives you
- No application rewrite — any PKCS#11 consumer works unchanged.
- Threshold security — no single HSM compromise can forge signatures.
- Audit trail — every signing op goes through the coordinator’s audit log.
- Policy enforcement — attribute-based policies apply to every sign (e.g., “only sign from 9am-5pm ET”).
Limitations
- Latency — every PKCS#11 sign op now requires a threshold ceremony (~200ms-2s depending on scheme + network). Applications that sign thousands of ops per second will be slower.
- Key generation — PKCS#11
C_GenerateKeyPairdoesn’t map cleanly to threshold DKG. Useconfium threshold dkgseparately, then register the resulting key as a token. - Algorithm support — Confium currently supports ECDSA-P256 and Ed25519 via PKCS#11. RSA support follows in a later release.