Software signer backed by a PKCS#8 PEM private key plus a separate certificate (PEM, single or chained).
Different shape from SoftSigner.PKCS12: PKCS#12 bundles carry
the cert with the key, so cert-chain extraction is automatic.
PKCS#8 is just the key, so the caller supplies the cert
separately. This split is common in cloud deployments where
TLS-style key + cert files live next to each other on disk.
Supports both encrypted (-----BEGIN ENCRYPTED PRIVATE KEY-----)
and unencrypted PKCS#8, plus the older PKCS#1
-----BEGIN RSA PRIVATE KEY----- format.
Threat model — key material is BEAM-resident
Same threat model as SoftSigner.PKCS12 — the decoded RSA private
key lives in BEAM heap memory for the lifetime of any reference to
the struct. The BEAM cannot zeroize managed terms; the GC may
retain freed copies. The key is readable by anyone with BEAM-process
memory access (debuggers, /proc/<pid>/mem, core dumps, swapped
pages, hibernation snapshots).
Use pkcs11ex instead for threat models that require the key to
stay on hardware. The package boundary between :soft_signer and
:pkcs11ex is intentional: omitting :soft_signer from
mix.lock prevents software signing by deployment topology, not
just by configuration.
Usage
# From file paths:
{:ok, signer} =
SoftSigner.PKCS8.load(
key_path: "/keys/legal-proxy.key.pem",
cert_path: "/keys/legal-proxy.cert.pem",
password: "secret" # only needed if the key is encrypted
)
# From in-memory PEM strings (the same opts but suffix `_pem`):
{:ok, signer} =
SoftSigner.PKCS8.load(
key_pem: File.read!("/keys/legal-proxy.key.pem"),
cert_pem: File.read!("/keys/legal-proxy.cert.pem")
)
{:ok, signed_pdf} =
SignCore.PDF.sign(pdf,
signer: signer,
alg: :PS256,
x5c: SoftSigner.PKCS8.cert_chain(signer)
)Options
Required (key — pick one):
:key_path— filesystem path to a PEM file.:key_pem— PEM bytes already in memory.
Required (cert — pick one):
:cert_path— filesystem path to a PEM file. May contain a single cert or a chain (leaf first, then intermediates).:cert_pem— PEM bytes already in memory.
Optional:
:password— required only if the key PEM is encrypted. Surfaces{:error, :wrong_password}on a mismatch.
Summary
Functions
Returns the cert chain as [leaf_der | intermediates_der] —
drop into any format adapter's :x5c opt.
Load a PKCS#8 key + cert chain. See moduledoc for opts.