Credentials
Credentials
Section titled “Credentials”This guide covers credential management - creating, rotating, and revoking certificate bundles with coupled lifecycle management.
1. What is a Credential?
Section titled “1. What is a Credential?”A credential is a managed bundle of private key(s) + certificate(s) with coupled lifecycle management. All certificates in a credential are created, renewed, and revoked together.
Why Credentials?
Section titled “Why Credentials?”Traditional PKI tools manage keys and certificates separately, requiring manual coordination for:
- Key generation → CSR → Certificate issuance → Deployment
- Renewal (repeat the full cycle)
- Revocation (track which certs belong together)
Credentials encapsulate this end-entity workflow:
- Single command to enroll (key + cert created together)
- Atomic rotation (all certs renewed at once)
- Grouped revocation (all certs added to CRL together)
- Multi-algorithm support (classical + PQC in one bundle)
1.1 Credential vs Certificate
Section titled “1.1 Credential vs Certificate”| Aspect | Certificate | Credential |
|---|---|---|
| Scope | Single certificate | Bundle of related certificates |
| Keys | Separate management | Integrated lifecycle |
| Renewal | Manual per-cert | Rotate all at once |
| Revocation | Individual | All certs together |
| Multi-algorithm | One algorithm | Multiple profiles |
1.2 Credential Structure
Section titled “1.2 Credential Structure”Credentials use a versioned structure with separate directories for keys and certificates (matching CA structure):
credentials/<credential-id>/├── credential.meta.json # Metadata (versions, active, etc.)└── versions/ └── v1/ ├── keys/ │ ├── credential.ecdsa-p384.key # Private key (encrypted) │ └── credential.ml-dsa-87.key └── certs/ ├── credential.ecdsa-p384.pem # Certificate └── credential.ml-dsa-87.pem1.3 Versioned Credentials
Section titled “1.3 Versioned Credentials”After rotation, credentials have multiple versions:
credentials/<credential-id>/├── credential.meta.json # Points to active version (status is computed, not stored)└── versions/ ├── v1/ # archived │ ├── keys/ │ │ └── credential.ecdsa-p384.key │ └── certs/ │ └── credential.ecdsa-p384.pem └── v2/ # active ├── keys/ │ ├── credential.ecdsa-p384.key │ └── credential.ml-dsa-87.key └── certs/ ├── credential.ecdsa-p384.pem └── credential.ml-dsa-87.pemVersion Status (computed, not stored):
| Status | Condition |
|---|---|
active | Version ID matches active field in credential.meta.json |
pending | Version exists but not active (no archived_at timestamp) |
archived | Version has archived_at timestamp set |
Status is derived at runtime from:
activefield in credential.meta.json → determines which version is activearchived_attimestamp in version → marks archived versions
1.4 Certificate Roles
Section titled “1.4 Certificate Roles”| Role | Description |
|---|---|
signature | Standard signature certificate |
signature-classical | Classical signature in hybrid-separate mode |
signature-pqc | PQC signature in hybrid-separate mode |
encryption | Standard encryption certificate |
encryption-classical | Classical encryption in hybrid-separate mode |
encryption-pqc | PQC encryption in hybrid-separate mode |
1.5 Credential Status
Section titled “1.5 Credential Status”| Status | Description |
|---|---|
pending | Credential created but not yet active |
valid | Credential is active and usable |
expired | Validity period has ended |
revoked | Credential was revoked (all certs added to CRL) |
1.6 Lifecycle Workflow
Section titled “1.6 Lifecycle Workflow”┌─────────────┐│ ENROLL ││ (pending) │└──────┬──────┘ │ ▼┌─────────────┐ ┌─────────────┐│ VALID │────►│ EXPIRED ││ │ │ (automatic) │└──────┬──────┘ └─────────────┘ │ │ revoke ▼┌─────────────┐│ REVOKED ││ (on CRL) │└─────────────┘2. CLI Commands
Section titled “2. CLI Commands”credential enroll
Section titled “credential enroll”Create a new credential with key(s) and certificate(s).
qpki credential enroll [flags]Flags:
| Flag | Short | Default | Description |
|---|---|---|---|
--profile | -P | required | Profile to use (repeatable for multi-profile) |
--var | Variable value (e.g., cn=example.com). Repeatable. | ||
--var-file | YAML file with variable values | ||
--ca-dir | -d | ./ca | CA directory (for signing) |
--cred-dir | -c | ./credentials | Credentials directory |
--id | auto | Custom credential ID | |
--passphrase | -p | "" | Passphrase for private keys |
Output:
qpki credential enroll --profile ec/tls-client --var cn=Alice
# ├── credential.meta.json # Metadata# └── private-keys.pem # Private key(s)Examples:
# Basic enrollment (single profile)qpki credential enroll --profile ec/tls-client \ --var cn=alice@example.com --var email=alice@example.com
qpki credential enroll --profile ec/client --profile ml/client \ --var cn=alice@example.com
qpki credential enroll --profile hybrid/catalyst/tls-client \ --var cn=alice@example.com --var email=alice@example.com
qpki credential enroll --profile ec/tls-server \ --var cn=server.example.com \ --var dns_names=server.example.com,www.example.com
qpki credential enroll --profile ec/tls-client \ --var cn=alice@example.com --id alice-prod
qpki credential enroll --profile hybrid/catalyst/tls-client \ --var cn=alice@example.com --passphrase "secret"
qpki credential enroll --ca-dir ./myca --cred-dir ./myca/credentials \ --profile ec/tls-server --var cn=server.example.comML-KEM (encryption) profiles:
For ML-KEM profiles, a signature profile must be listed first (RFC 9883 proof of possession):
# Correct: signature profile before KEM profileqpki credential enroll --profile ec/client --profile ml-kem/client \ --var cn=alice@example.com
qpki credential enroll --profile ml-kem/client --var cn=alice@example.comcredential list
Section titled “credential list”List all credentials.
qpki credential list [flags]Flags:
| Flag | Short | Default | Description |
|---|---|---|---|
--cred-dir | -c | ./credentials | Credentials directory |
Example:
qpki credential listqpki credential list --cred-dir ./myca/credentialscredential info
Section titled “credential info”Show details of a specific credential.
qpki credential info <credential-id> [flags]Flags:
| Flag | Short | Default | Description |
|---|---|---|---|
--cred-dir | -c | ./credentials | Credentials directory |
Example:
qpki credential info alice-20250115-abc123credential rotate
Section titled “credential rotate”Rotate a credential with new certificates. Creates a PENDING version that must be activated.
qpki credential rotate <credential-id> [flags]Flags:
| Flag | Short | Default | Description |
|---|---|---|---|
--ca-dir | -d | ./ca | CA directory (for signing) |
--cred-dir | -c | ./credentials | Credentials directory |
--profile | -P | Replace all profiles (overrides add/remove) | |
--add-profile | Add profile(s) to current set | ||
--remove-profile | Remove profile(s) from current set | ||
--keep-keys | false | Reuse existing keys (certificate renewal only) | |
--passphrase | -p | "" | Passphrase for private keys |
--hsm-config | HSM configuration file for key generation | ||
--key-label | HSM key label prefix |
Workflow:
After rotation, the new version must be explicitly activated:
qpki credential rotate <credential-id>
qpki credential activate <credential-id> --version v20260105_abc123This allows:
- Review before activation
- Gradual rollout
- Rollback possibility
Examples:
# Simple rotation (generates new keys)qpki credential rotate alice-xxx# Output: Version v20260105_abc123 (PENDING)
qpki credential rotate alice-xxx --keep-keys
qpki credential rotate alice-xxx --add-profile ml/tls-client
qpki credential rotate alice-xxx --remove-profile ec/tls-client
qpki credential rotate alice-xxx \ --profile ec/tls-client --profile ml/tls-client
qpki credential rotate alice-xxx --ca-dir ./myca --cred-dir ./myca/credentialscredential activate
Section titled “credential activate”Activate a pending or archived credential version. Use this after rotation to make a new version active, or to rollback to a previous version.
qpki credential activate <credential-id> [flags]Flags:
| Flag | Short | Default | Description |
|---|---|---|---|
--cred-dir | -c | ./credentials | Credentials directory |
--version | (required) | Version to activate |
Examples:
# Activate a pending version after rotationqpki credential activate alice-xxx --version v20260105_abc123
# Rollback to a previous (archived) versionqpki credential versions alice-xxx# Shows: v1 (archived), v2 (active)
qpki credential activate alice-xxx --version v1# v1 becomes active, v2 becomes archivedRollback behavior:
- When activating an archived version, its
archived_attimestamp is cleared - The previously active version becomes archived
- All certificates in the reactivated version become usable again
credential versions
Section titled “credential versions”List all versions of a credential.
qpki credential versions <credential-id> [flags]Flags:
| Flag | Short | Default | Description |
|---|---|---|---|
--cred-dir | -c | ./credentials | Credentials directory |
Example:
qpki credential versions alice-xxxOutput:
Credential: alice-xxx
VERSION STATUS PROFILES CREATED------- ------ -------- -------v20260101_abc123 archived ec/tls-client 2026-01-01v20260105_def456 active ec/tls-client, ml/tls-client 2026-01-05credential revoke
Section titled “credential revoke”Revoke all certificates in a credential.
qpki credential revoke <credential-id> [flags]Flags:
| Flag | Short | Default | Description |
|---|---|---|---|
--ca-dir | -d | ./ca | CA directory (for CRL/index update) |
--cred-dir | -c | ./credentials | Credentials directory |
--reason | -r | unspecified | Revocation reason |
Revocation Reasons:
| Reason | Description |
|---|---|
| unspecified | No specific reason |
| keyCompromise | Private key was compromised |
| caCompromise | CA key was compromised |
| affiliationChanged | Subject’s affiliation changed |
| superseded | Replaced by new certificate |
| cessation | Certificate no longer needed |
| hold | Temporary hold |
Example:
qpki credential revoke alice-20250115-abc123 --reason keyCompromisecredential export
Section titled “credential export”Export credential certificates.
qpki credential export <credential-id> [flags]Flags:
| Flag | Short | Default | Description |
|---|---|---|---|
--ca-dir | -d | ./ca | CA directory (for chain bundle) |
--cred-dir | -c | ./credentials | Credentials directory |
--out | -o | stdout | Output file |
--format | -f | pem | Output format: pem, der |
--bundle | -b | cert | Bundle type: cert, chain, all |
--version | -v | Export specific version | |
--all | false | Export all versions |
Bundle types:
| Bundle | Description |
|---|---|
cert | Certificate(s) only (default) |
chain | Certificates + issuing CA chain |
all | All certificates from all algorithm families |
Examples:
# Export active certificates as PEMqpki credential export alice-xxx
qpki credential export alice-xxx --format der --out alice.der
qpki credential export alice-xxx --bundle chain --out alice-chain.pem
qpki credential export alice-xxx --version v20260105_abc123
qpki credential export alice-xxx --all --out alice3. Common Workflows
Section titled “3. Common Workflows”3.1 TLS Server Certificate
Section titled “3.1 TLS Server Certificate”# 1. Enroll server credentialqpki credential enroll --profile ec/tls-server \ --var cn=server.example.com \ --var dns_names=server.example.com,www.example.com
# 2. Export certificate and key for deploymentqpki credential export <id> --out /etc/ssl/server.crt# For the private key, copy from the versioned directory:cp ./credentials/<id>/versions/v1/keys/credential.ecdsa-p384.key /etc/ssl/server.key
# 3. Rotate when neededqpki credential rotate <id>qpki credential activate <id> --version <new-version>3.2 mTLS (Mutual TLS)
Section titled “3.2 mTLS (Mutual TLS)”# 1. Create CAqpki ca init --profile ec/root-ca --ca-dir ./mtls-ca --var cn="mTLS CA"
qpki credential enroll --ca-dir ./mtls-ca --cred-dir ./mtls-ca/credentials \ --profile ec/tls-server \ --var cn=server.local --var dns_names=server.local
qpki credential enroll --ca-dir ./mtls-ca --cred-dir ./mtls-ca/credentials \ --profile ec/tls-client \ --var cn=client-a@example.com --id client-a
qpki credential enroll --ca-dir ./mtls-ca --cred-dir ./mtls-ca/credentials \ --profile ec/tls-client \ --var cn=client-b@example.com --id client-b
# ssl_certificate server.crt;# ssl_client_certificate mtls-ca/ca.crt;3.3 Code Signing
Section titled “3.3 Code Signing”# 1. Enroll code signing credentialqpki credential enroll --profile ec/code-signing \ --var cn="My Company Code Signing" \ --var organization="My Company"
# 2. Sign using qpki cms (recommended)qpki cms sign --data binary.exe --credential <id> --out binary.exe.sig
# Or using openssl with exported files:qpki credential export <id> --out signer.pemopenssl cms -sign -in binary.exe \ -signer signer.pem \ -inkey ./credentials/<id>/versions/v1/keys/credential.ecdsa-p384.key \ -out binary.exe.sig -binary
# 3. Verifyopenssl cms -verify -in binary.exe.sig \ -content binary.exe -CAfile ./ca/ca.crt3.4 Certificate Rotation
Section titled “3.4 Certificate Rotation”# 1. Check credential expirationqpki credential info <credential-id>
qpki credential rotate <credential-id>
qpki credential versions <credential-id>
qpki credential activate <credential-id> --version v20260105_abc123
qpki credential revoke <old-credential-id> --reason superseded3.5 Crypto-Agility Migration
Section titled “3.5 Crypto-Agility Migration”For detailed migration scenarios, see Crypto-Agility.
# Start with classical certificatesqpki credential enroll --profile ec/client --var cn=alice@example.com
qpki credential rotate alice-xxx --add-profile ml/clientqpki credential activate alice-xxx --version <new-version>
qpki credential rotate alice-xxx --remove-profile ec/clientqpki credential activate alice-xxx --version <new-version>4. Integration with CMS, TSA, OCSP
Section titled “4. Integration with CMS, TSA, OCSP”4.1 Signing with Credentials
Section titled “4.1 Signing with Credentials”The --credential flag allows loading certificate and key directly from the credential store:
# CMS signingqpki cms sign --data doc.pdf --credential signer --out doc.p7s
qpki tsa sign --data doc.pdf --credential tsa --out doc.tsr
qpki ocsp sign --serial 0A1B2C --status good --ca ca.crt \ --credential ocsp-responder --out response.ocsp4.2 Server Mode (TSA/OCSP)
Section titled “4.2 Server Mode (TSA/OCSP)”Credentials are particularly well-suited for long-running servers because the rotate → activate workflow enables certificate renewal without service interruption:
# Start server with credentialqpki tsa serve --port 8318 --credential tsa-server# orqpki ocsp serve --port 8080 --ca-dir ./ca --credential ocsp-responder
qpki credential rotate tsa-server
qpki credential versions tsa-serverqpki credential activate tsa-server --version v24.3 Multi-Version Decryption
Section titled “4.3 Multi-Version Decryption”When using --credential with cms decrypt, QPKI automatically searches all versions of the credential to find a matching decryption key. This is essential after key rotation: data encrypted with an old key can still be decrypted.
# Encrypt with current active keyqpki cms encrypt --recipient ./credentials/bob/certificates.pem \ --in secret.txt --out secret.p7m
qpki credential rotate bobqpki credential activate bob --version v2
qpki cms decrypt --credential bob --in secret.p7m --out secret.txtSee Also
Section titled “See Also”- CA - CA initialization and management
- Keys - Key generation and CSR operations
- CLI Reference - Complete command reference
- Profiles - Certificate profile templates
- Crypto-Agility - Algorithm migration guide
- Troubleshooting - Common errors and solutions