Skip to main content
The Infisical PKCS#11 module implements the PKCS#11 v2.40 standard, allowing tools like jarsigner, openssl, cosign, osslsigncode, apksigner, and gpg to use Infisical signers without code changes.

Installation

Download the pre-built binary for your platform from the releases page:
PlatformFile
Linux x86_64libinfisical-pkcs11.so
Linux ARM64libinfisical-pkcs11.so
macOS x86_64libinfisical-pkcs11.dylib
macOS ARM64libinfisical-pkcs11.dylib
Windows x86_64libinfisical-pkcs11.dll
Place the binary in a known location, for example /usr/local/lib/:
# Linux
sudo cp libinfisical-pkcs11.so /usr/local/lib/
sudo chmod 755 /usr/local/lib/libinfisical-pkcs11.so

# macOS
sudo cp libinfisical-pkcs11.dylib /usr/local/lib/
sudo chmod 755 /usr/local/lib/libinfisical-pkcs11.dylib

Building from Source

If you prefer to build from source, you need Go 1.24+ and a C compiler:
git clone https://github.com/Infisical/infisical-pkcs-11.git
cd infisical-pkcs-11
make build
The output binary will be in the current directory.

Configuration

Create a JSON configuration file at /etc/infisical/pkcs11.conf (or any path you prefer):
{
  "server_url": "https://app.infisical.com",
  "project_id": "<your-project-id>",
  "log_level": "info"
}
Then set the authentication credentials via environment variables:
export INFISICAL_UNIVERSAL_AUTH_CLIENT_ID="<your-machine-identity-client-id>"
export INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET="<your-machine-identity-client-secret>"
Credentials can also be placed in the config file under auth.client_id and auth.client_secret, but we recommend using environment variables to prevent secrets from being committed to version control or exposed in file system backups.
If using a non-default config path, set:
export INFISICAL_PKCS11_CONFIG=/path/to/your/pkcs11.conf

Configuration Reference

FieldRequiredDefaultDescription
server_urlYesNoneInfisical server URL
project_idYesNoneProject ID containing the signers
auth.methodNouniversal-authAuthentication method
auth.client_idNoNoneMachine identity client ID (prefer env var)
auth.client_secretNoNoneMachine identity client secret (prefer env var)
tls.ca_cert_pathNoNoneCustom CA cert for self-hosted instances
tls.skip_verifyNofalseSkip TLS verification (development only)
cache.token_ttl_secondsNo300Auth token cache duration
cache.cert_ttl_secondsNo3600Certificate data cache duration
cache.signer_ttl_secondsNo300Signer list cache duration
approval.signing_durationNoNoneAuto-request signing access with this time window (e.g. "8h", "30m", "2d"). Range: 1m to 30d
approval.signing_countNoNoneAuto-request signing access for this many signing operations
log_levelNoinfoLog level: trace, debug, info, warn, error
log_fileNostderrPath to log file

Environment Variable Reference

VariableDescription
INFISICAL_UNIVERSAL_AUTH_CLIENT_IDMachine identity client ID
INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRETMachine identity client secret
INFISICAL_PKCS11_SERVER_URLOverride server_url from config
INFISICAL_PKCS11_CONFIGPath to config file (default: /etc/infisical/pkcs11.conf)
Environment variables always take precedence over values in the configuration file.

Verifying the Module

Use pkcs11-tool (from OpenSC) to verify the module is working:
# List available slots (one per signer)
pkcs11-tool --module /usr/local/lib/libinfisical-pkcs11.so --list-slots
The output lists one slot per signer in your project:
Available slots:
Slot 0 (0x0): release-signer
  token label        : release-signer
  token manufacturer : Infisical
  ...
To list the objects (private key, certificate, public key) in a slot:
pkcs11-tool --module /usr/local/lib/libinfisical-pkcs11.so --slot 0 --list-objects

Automatic Signing Access Requests

If a signer has a signing policy attached, the module can automatically create a signing request when a sign operation is denied due to a missing grant. This removes the need to manually create requests via the UI or API before signing. To enable this, add the approval section to your config file with at least one of the following:
{
  "approval": {
    "signing_duration": "8h",
    "signing_count": 10
  }
}
  • signing_duration: Requests a time-window grant of the specified duration (e.g. "30m", "8h", "2d"). Valid range: 1 minute to 30 days.
  • signing_count: Requests a grant for a fixed number of signing operations.
You can set one or both depending on the constraints defined in the signing policy.
The sign operation will fail until an approver approves the request first. Once approved, retrying the sign operation will succeed. The module logs a message indicating that an approval request was created automatically.

Example Workflow

  1. A CI/CD pipeline attempts to sign an artifact
  2. The module detects that no active grant exists for the signer
  3. It automatically creates a signing request with the configured duration/count
  4. An approver reviews and approves the request
  5. The pipeline retries and the sign operation succeeds

Troubleshooting

For any issue, start by enabling debug logging in your config file to get detailed output:
{
  "log_level": "debug",
  "log_file": "/tmp/infisical-pkcs11.log"
}
Verify that your credentials and project_id are correct, and that the machine identity has been added to the project with the appropriate permissions.
This typically means the signing request was denied by the server. Check that you have an active signing grant for the signer. You can verify this in the Infisical UI under Code Signing > Approvals > Grants.