Key Management
Authentication vs authorisation
certified manages certificates for authentication (proving who you are
over mTLS). It also provides tools for using biscuit tokens so you can
implement authorisation (deciding what callers may do) on top.
See the Authorization Model.
One of the major stumbling blocks for public key infrastructure (PKI) is the
management of keys and certificates. There need to be at least 2 separate keys
for each entity (1 for signing certificates, and 1 for authenticating TLS
connections). As a user, you may want to create short-lived keys that expire
automatically — certified relies on certificate expiry, not CRL/OCSP
revocation, to bound the validity window of a key. Expiry is simpler and
requires no revocation infrastructure; plan your not_after dates accordingly.
Different interacting parties may have different trust roots. Thus, you will probably have to store a chain of trust between your own certificates and each different trust root that you obtain a signature from.
The Certified class takes a key-directory as its input argument. If none is
given, it finds a directory depending on the first of the following environment
variables to be set:
$CERTIFIED_CONFIG$VIRTUAL_ENV/etc/certified/etc/certified
Inside the base directory, Certified expects the following layout:
-
main directory: PEM-encoded private and public keys (similar to
.ssh/id_ed25519andid_ed25519.pub)-
CA.key,CA.crt— private and public signing keys -
id.key,id.crt— end-entity identification key for establishing TLS connections and encryption -
Since each certificate can be co-signed by multiple authorities, one subdirectory (named after each certificate) holds co-signed chain files. Each file is a sequence of PEM blocks — the leaf certificate followed by any intermediate certificates needed to reach a trusted root:
CA/signerA.crt # PEM chain: your CA cert + signerA cert id/signerA.crt # PEM chain: your id cert + signerA cert
Multiple files in this directory represent the same identity key, but authenticated via different signing authorities.
When establishing a TLS connection to a server that trusts
some_signer, use--key id.key --crt id/some_signer.crt.Certified.Clientdoes this automatically. -
-
known_servers— PEM-encoded trusted server certificates.- Names servers you want to access (similar to
.ssh/known_hosts) as well as signing authorities trusted to sign server certificates for those you don't know directly (similar to cacerts).
- Names servers you want to access (similar to
-
known_clients— PEM-encoded trusted client certificates.-
Clients whose certs (and all certs signed by them) are allowed to access any API started with
certified serve(similar to.ssh/authorized_keys). -
Adding a CA certificate here indirectly grants access to all clients holding a cert signed by that CA.
Note
Certificates establish identity — they say nothing about what an authenticated client is permitted to do. Authorisation is handled entirely by the biscuit layer. See Authorization Model.
-
Supported Key Types
certified supports all modern elliptic-curve key types. RSA is excluded
by design — too slow for short-lived key generation and superseded by ECC.
| Key type | Status | Notes |
|---|---|---|
| Ed25519 | ✅ Default | Fast, small keys, widely deployed |
| Ed448 | ✅ Supported | Higher security margin, less common |
| ECDSA P-256 | ✅ Supported | Broad TLS compatibility |
| ECDSA P-384 | ⏳ Planned | Not yet implemented |
| ECDSA P-521 | ⏳ Planned | Not yet implemented |
| RSA | ❌ Not supported | Excluded by design |
Federated Trust
When two organisations need to grant each other's clients selective access,
they can cross-sign individual identity certificates — storing co-signed PEM
chains in the id/ subdirectory. See
Cross-chain Trust for a worked example including
directory layout, service definition files, and a step-by-step trace of how
Certified.Client resolves and connects to a cross-org service.
Rationale
Many strategies have been employed to manage keys, but are either a) not comprehensive or b) not specialised for x509 interactions.
GPG's gpgsm tool
comes close. It uses an internal database of private keys and signatures at
$HOME/.gnupg. However, gnupg was designed for easier name-key pairings,
and all the extra x509 fields are an add-on.
Basic web infrastructure uses /usr/share/ca-certificates/mozilla from the
ca-certificates package to list out trust roots. The letsencrypt project
sets up a file-layout for a series of webserver keys as they expire and are
renewed over time.
OpenSSH uses $HOME/.ssh and defines many of the same file types used here
(authorized_keys, known_hosts). However, SSH is less disciplined about
server authentication and not set up for x509/TLS. It also does not support
chain-of-trust models or key-scoped authorisation policies.
The present key management strategy is based on actor_api, which used a
single private key per entity and did not store signatures. That model was
more static and defined its own non-standard TLS.
The myproxy project had a similar x509-compatible public/private key setup.
However, myproxy did not keep all private keys local to the machine where they
were generated. Its design became complex because it used certificates to
delegate authority — which was a mistake. Its certificate-signing support
was later deprecated. Ultimately, its decline was caused by conflating
authentication and authorisation. certified keeps these strictly separate:
certificates prove identity; biscuit tokens carry authorisation.