Skip to content

Certificate Authority

This guide covers Certificate Authority operations: initialization, rotation, and management.

A Certificate Authority (CA) is the trust anchor that signs certificates. QPKI supports root CAs (self-signed) and subordinate CAs (signed by a parent).

TypeDescription
Root CASelf-signed, trust anchor
Subordinate CASigned by parent, issues end-entity certs
Multi-profile CAMultiple algorithms (crypto-agility)
Hybrid CAClassical + PQC (Catalyst or Composite)
ca/
├── ca.meta.json # CA metadata (versions, keys, status)
├── index.txt # OpenSSL-compatible certificate index
├── serial # Current serial number (hex)
├── crlnumber # Current CRL number
├── certs/ # Issued certificates
│ ├── 02.crt
│ └── 03.crt
├── crl/ # Certificate Revocation Lists
│ ├── ca.crl # PEM format
│ └── ca.crl.der # DER format
└── versions/ # CA versions (after rotation)
└── v1/
├── keys/
│ └── ca.ecdsa-p256.key
└── certs/
└── ca.ecdsa-p256.pem

After rotation, CAs have multiple versions with status tracking:

ca/
├── ca.meta.json # Points to active version, stores key refs per version
└── versions/
├── v1/ # archived
│ ├── keys/ca.ecdsa-p256.key # Software keys only
│ └── certs/ca.ecdsa-p256.pem
├── v2/ # active (hybrid)
│ ├── keys/
│ │ ├── ca.ecdsa-p256.key
│ │ └── ca.ml-dsa-65.key
│ └── certs/
│ ├── ca.ecdsa-p256.pem
│ └── ca.ml-dsa-65.pem
└── v3/ # pending
└── ...
StatusDescription
pendingAwaiting activation after rotation
activeCurrently in use for signing
archivedSuperseded by newer version

Key Storage:

  • Each version stores its own key references in ca.meta.json
  • Software keys: stored as files in versions/vN/keys/
  • HSM keys: referenced by label + key_id in metadata (no files)
  • This enables proper key rotation with new keys per version

Initialize a new Certificate Authority.

Terminal window
qpki ca init [flags]

Flags:

FlagShortDefaultDescription
--profile-P""CA profile (repeatable for multi-profile CA)
--var[]Variable value (key=value, repeatable)
--var-file""YAML file with variable values
--ca-dir-d./caCA directory
--passphrase-p""Key passphrase
--parent""Parent CA directory (creates subordinate CA)
--parent-passphrase""Parent CA key passphrase
--hsm-config""HSM configuration file (enables HSM mode)
--key-label""Key label in HSM (required with —hsm-config)
--key-id""Key ID in HSM (hex, optional)
--use-existing-keyfalseUse existing key in HSM instead of generating

Note: Multi-profile subordinate CA is not yet supported. Use a single --profile for subordinate CAs.

HSM Note: See HSM Integration for detailed configuration.

Examples:

Terminal window
# Using a profile (recommended)
qpki ca init --profile ec/root-ca --ca-dir ./myca --var cn="My Root CA"
qpki ca init --profile ec/root-ca --profile ml/root-ca --ca-dir ./multi-ca --var cn="Multi-Algo Root CA"
qpki ca init --profile hybrid/catalyst/root-ca --ca-dir ./catalyst-ca --var cn="Catalyst Root CA"
qpki ca init --profile hybrid/composite/root-ca --ca-dir ./composite-ca --var cn="Composite Root CA"
qpki ca init --profile ec/issuing-ca --ca-dir ./issuing-ca \
--parent ./rootca --var cn="Issuing CA"
qpki ca init --profile ec/root-ca --passphrase "mysecret" --ca-dir ./secure-ca --var cn="Secure CA"
qpki ca init --profile ml/root-ca --ca-dir ./pqc-ca --var cn="PQC Root CA"
qpki ca init --profile ec/root-ca --ca-dir ./myca --var-file ca-vars.yaml
# HSM: generate key in HSM (default behavior)
export HSM_PIN="****"
qpki ca init --profile ec/root-ca --ca-dir ./hsm-ca \
--hsm-config ./hsm.yaml --key-label "root-ca-key" --var cn="HSM Root CA"
# HSM: use existing key
qpki ca init --profile ec/root-ca --ca-dir ./hsm-ca \
--hsm-config ./hsm.yaml --key-label "existing-key" --use-existing-key --var cn="HSM Root CA"

Available CA profiles:

ProfileAlgorithmValidityDescription
ec/root-caEC P-38420 yearsRoot CA with pathLen=1
ec/issuing-caEC P-25610 yearsIssuing CA with pathLen=0
hybrid/catalyst/root-caEC P-384 + ML-DSA-8720 yearsHybrid root CA (ITU-T extensions)
hybrid/catalyst/issuing-caEC P-384 + ML-DSA-6510 yearsHybrid issuing CA (ITU-T)
hybrid/composite/root-caEC P-384 + ML-DSA-8720 yearsComposite root CA (IETF draft)
hybrid/composite/issuing-caEC P-256 + ML-DSA-6510 yearsComposite issuing CA (IETF)
rsa/root-caRSA 409620 yearsRSA root CA
ml/root-caML-DSA-8720 yearsPure PQC root CA

Display information about a Certificate Authority.

Terminal window
qpki ca info [flags]

Flags:

FlagShortDefaultDescription
--ca-dir-d./caCA directory

Example:

Terminal window
qpki ca info --ca-dir ./myca

Export CA certificates.

Terminal window
qpki ca export [flags]

Flags:

FlagShortDefaultDescription
--ca-dir-d./caCA directory
--bundle-bcaBundle type: ca, chain, root
--out-ostdoutOutput file

Examples:

Terminal window
# Export CA certificate
qpki ca export --ca-dir ./myca --out ca.crt
qpki ca export --ca-dir ./issuing-ca --bundle chain --out chain.pem
qpki ca export --ca-dir ./issuing-ca --bundle root --out root.crt

List Certificate Authorities in a directory.

Terminal window
qpki ca list [flags]

Flags:

FlagShortDefaultDescription
--dir-d.Directory to scan

Example:

Terminal window
qpki ca list --dir /var/lib/pki

Rotate a CA with new keys and algorithm.

Terminal window
qpki ca rotate [flags]

Flags:

FlagShortDefaultDescription
--ca-dir-d./caCA directory
--profile-PNew profile for rotation (repeatable for multi-profile)
--passphrase-p""Passphrase for new key
--cross-signfalseCross-sign new CA with previous CA (see Crypto-Agility)
--dry-runfalsePreview rotation plan without executing
--hsm-config""HSM configuration file (for HSM-based CAs)
--key-label""Key label for new HSM keys

Examples:

Terminal window
# Preview rotation plan (dry-run)
qpki ca rotate --ca-dir ./myca --dry-run
qpki ca rotate --ca-dir ./myca --profile hybrid/catalyst/root-ca
qpki ca rotate --ca-dir ./myca --profile ec/root-ca --profile ml/root-ca
qpki ca rotate --ca-dir ./myca --profile ml/root-ca --cross-sign
# HSM rotation: generates new keys in HSM with versioned key_id
export HSM_PIN="****"
qpki ca rotate --ca-dir ./hsm-ca --profile hybrid/catalyst/root-ca \
--hsm-config ./hsm.yaml --key-label "my-ca"

HSM Rotation Notes:

  • Each rotation generates new keys in the HSM
  • Keys are distinguished by key_id (not label) in ca.meta.json
  • The metadata file tracks which HSM key belongs to which version

Activate a pending CA version after rotation.

Terminal window
qpki ca activate [flags]

Flags:

FlagShortDefaultDescription
--ca-dir-d./caCA directory
--version-vVersion to activate

Example:

Terminal window
qpki ca activate --ca-dir ./myca --version 2

List all versions of a CA.

Terminal window
qpki ca versions [flags]

Flags:

FlagShortDefaultDescription
--ca-dir-d./caCA directory

Example:

Terminal window
qpki ca versions --ca-dir ./myca

Terminal window
# 1. Create root CA (keep offline)
qpki ca init --profile ec/root-ca --ca-dir ./root-ca \
--var cn="Root CA" --var organization="My Company"
qpki ca init --profile ec/issuing-ca --ca-dir ./issuing-ca \
--parent ./root-ca --var cn="Issuing CA"
qpki credential enroll --ca-dir ./issuing-ca --cred-dir ./issuing-ca/credentials \
--profile ec/tls-server \
--var cn=www.example.com \
--var dns_names=www.example.com,example.com
openssl verify -CAfile ./root-ca/ca.crt ./issuing-ca/ca.crt

The --parent flag automatically:

  • Generates a new key for the subordinate CA
  • Issues a CA certificate signed by the parent
  • Creates the full CA directory structure
  • Generates chain.crt with the certificate chain
Terminal window
# 1. Preview the rotation plan
qpki ca rotate --ca-dir ./myca --profile hybrid/catalyst/root-ca --dry-run
qpki ca rotate --ca-dir ./myca --profile hybrid/catalyst/root-ca
qpki ca versions --ca-dir ./myca
qpki ca activate --ca-dir ./myca --version 2

Q: How do I create a CA with a custom validity period?

Section titled “Q: How do I create a CA with a custom validity period?”

Use the --validity flag (in years):

Terminal window
qpki ca init --profile ec/root-ca --ca-dir ./ca --var cn="Long-lived CA" --validity 30

Copy the entire CA directory:

Terminal window
tar -czf ca-backup-$(date +%Y%m%d).tar.gz ./myca

Q: Is the PQC extension compatible with browsers?

Section titled “Q: Is the PQC extension compatible with browsers?”

The PQC extension is non-critical and will be ignored by browsers. The classical signature is used for TLS. The PQC material is for future use or application-level verification.