> ## Documentation Index
> Fetch the complete documentation index at: https://infisical.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Sign with OpenSSL

> Use the Infisical PKCS#11 module with OpenSSL's pkcs11 engine for general-purpose signing.

> [!NOTE]
>
> This guide assumes your Product Admin has already created a [Signer](https://infisical.com/docs/documentation/platform/pki/code-signing/signers) and assigned you to it. If the signer has an approval policy, you'll also need [active access](https://infisical.com/docs/documentation/platform/pki/code-signing/approvals.md#access-lifecycle) before signing.

Use OpenSSL with the Infisical PKCS#11 module via the `libp11` engine for general-purpose signing. OpenSSL is a versatile foundation for signing any file format, useful when you need raw signatures, custom signing pipelines, or integration with tools that wrap OpenSSL.

## Prerequisites

* A [Signer](https://infisical.com/docs/documentation/platform/pki/code-signing/signers) created by your Product Admin
* [Active signing access](https://infisical.com/docs/documentation/platform/pki/code-signing/approvals.md#access-lifecycle) (if an approval policy is attached)
* A [machine identity](https://infisical.com/docs/documentation/platform/identities/machine-identities.md) added to the Signer
* The Infisical [PKCS#11 module](https://infisical.com/docs/documentation/platform/pki/code-signing/pkcs11-module.md) installed and configured
* OpenSSL 1.1.1 or later
* `libp11` (OpenSSL PKCS#11 engine)

## Step 1: Set up authentication

Configure the Infisical PKCS#11 module with your machine identity credentials. Without this, the signing commands below fail with an auth error.

Create `/etc/infisical/pkcs11.conf` (or set `INFISICAL_CONFIG` to point elsewhere):

```yaml theme={"dark"}
auth:
  method: universal-auth
  universal_auth:
    client_id: "<machine-identity-client-id>"
    client_secret: "<machine-identity-client-secret>"

signer:
  id: "<signer-id>"
```

You can also pass the credentials via environment variables:

```bash theme={"dark"}
export INFISICAL_UNIVERSAL_AUTH_CLIENT_ID="<machine-identity-client-id>"
export INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET="<machine-identity-client-secret>"
```

> [!NOTE]
>
> Environment variables override values from the config file.

For the full set of options, see the [PKCS#11 module configuration reference](https://infisical.com/docs/documentation/platform/pki/code-signing/pkcs11-module.md#configuration).

## Step 2: Install the PKCS#11 engine

> [tab] Ubuntu / Debian
>
> ```bash theme={"dark"}
> sudo apt-get update
> sudo apt-get install -y opensc libengine-pkcs11-openssl
> ```

> [tab] macOS (Homebrew)
>
> ```bash theme={"dark"}
> brew install opensc libp11
> ```

> [tab] RHEL / Fedora
>
> ```bash theme={"dark"}
> sudo dnf install opensc p11-kit engine-pkcs11
> ```

Verify the engine is available:

```bash theme={"dark"}
openssl engine pkcs11 -t
```

The output confirms the engine is loaded:

```
(pkcs11) pkcs11 engine
     [ available ]
```

## Step 3: Create an OpenSSL configuration

Create an OpenSSL config file `infisical-openssl.cnf` to set up the PKCS#11 engine:

```ini theme={"dark"}
openssl_conf = openssl_init

[openssl_init]
engines = engine_section

[engine_section]
pkcs11 = pkcs11_section

[pkcs11_section]
engine_id = pkcs11
MODULE_PATH = /usr/local/lib/libinfisical-pkcs11.so
init = 0
```

Set this as the active OpenSSL config:

```bash theme={"dark"}
export OPENSSL_CONF=/path/to/infisical-openssl.cnf
```

## Step 4: Sign a file

Sign a file using the PKCS#11 key. The same command works for both RSA and ECDSA keys. OpenSSL automatically selects the correct algorithm based on the key type:

```bash theme={"dark"}
openssl dgst -sha256 \
  -engine pkcs11 \
  -keyform engine \
  -sign "pkcs11:object=release-signer;type=private" \
  -out document.sig \
  document.txt
```

> [!NOTE]
>
> * The `object` in the PKCS#11 URI must match your signer name exactly.
> * The output is a raw signature file (PKCS#1 for RSA, DER-encoded for ECDSA).

### Sign with RSA-PSS padding

For RSA keys, you can use PSS padding instead of the default PKCS#1 v1.5:

```bash theme={"dark"}
openssl dgst -sha256 \
  -engine pkcs11 \
  -keyform engine \
  -sign "pkcs11:object=release-signer;type=private" \
  -sigopt rsa_padding_mode:pss \
  -sigopt rsa_pss_saltlen:32 \
  -out document.sig \
  document.txt
```

> [!NOTE]
>
> RSA-PSS requires the signer's key to support the `RSASSA_PSS` mechanism. This is only available with RSA keys.

## Step 5: Verify the signature

Extract the public key or certificate from PKCS#11, then verify:

```bash theme={"dark"}
# Extract the certificate and public key
pkcs11-tool --module /usr/local/lib/libinfisical-pkcs11.so \
  --slot 0 --read-object --type cert --label release-signer \
  --output-file cert.der
openssl x509 -inform DER -in cert.der -pubkey -noout > pubkey.pem

# Verify the signature
openssl dgst -sha256 \
  -verify pubkey.pem \
  -signature document.sig \
  document.txt
```

The output confirms the signature is valid:

```
Verified OK
```

## Common use cases

### Sign a checksum manifest

```bash theme={"dark"}
# Generate checksums
sha256sum *.tar.gz > SHA256SUMS

# Sign the manifest
openssl dgst -sha256 \
  -engine pkcs11 \
  -keyform engine \
  -sign "pkcs11:object=release-signer;type=private" \
  -out SHA256SUMS.sig \
  SHA256SUMS
```

### Create a detached S/MIME signature

```bash theme={"dark"}
openssl cms -sign \
  -engine pkcs11 \
  -keyform engine \
  -inkey "pkcs11:object=release-signer;type=private" \
  -signer signer-cert.pem \
  -in document.pdf \
  -out document.pdf.p7s \
  -outform DER \
  -binary
```

## CI/CD integration

```bash theme={"dark"}
export INFISICAL_UNIVERSAL_AUTH_CLIENT_ID="${INFISICAL_CLIENT_ID}"
export INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET="${INFISICAL_CLIENT_SECRET}"
export INFISICAL_CONFIG="/path/to/pkcs11.conf"
export OPENSSL_CONF="/path/to/infisical-openssl.cnf"

# Sign release artifacts
for file in dist/*.tar.gz; do
  openssl dgst -sha256 \
    -engine pkcs11 \
    -keyform engine \
    -sign "pkcs11:object=release-signer;type=private" \
    -out "${file}.sig" \
    "${file}"
done
```

## Troubleshooting

For any issue, enable debug logging in your config file (`"log_level": "debug"`, `"log_file": "/tmp/infisical-pkcs11.log"`) to get detailed output.

> [accordion] Engine 'pkcs11' not found or key errors
>
> Ensure `libp11` is installed and the object name in the PKCS#11 URI matches your signer name exactly. Check the engine is registered with `openssl engine -t pkcs11`.

> [accordion] OpenSSL 3.0+ deprecation warnings
>
> OpenSSL 3.0 deprecated engines in favor of providers. The `libp11` engine still works but may show warnings. For a provider-based approach, use [`pkcs11-provider`](https://github.com/latchset/pkcs11-provider) instead.

## What's next?

> [card] [Sign Windows Binaries](https://infisical.com/docs/documentation/platform/pki/guides/code-signing/osslsigncode.md)
>
> Sign Windows executables with osslsigncode

> [card] [Sign Containers](https://infisical.com/docs/documentation/platform/pki/guides/code-signing/cosign.md)
>
> Sign container images with Cosign


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.