# NIST SP 800-57 Key Management Alignment NIST SP 800-57 Part 1 Rev 5 (May 2020) is the authoritative US government guidance on cryptographic key management. This document maps certctl's implementation to its recommendations. certctl follows NIST guidance where applicable; this guide documents the alignment and identifies gaps for future roadmap planning. ## Key Generation (Section 6.1) certctl generates certificate keys on agent infrastructure using Go's `crypto/rand` for entropy, backed by `/dev/urandom` on Linux and `CryptGenRandom` on Windows. Key generation happens as follows: **Agent-Side Key Generation (Production Default)** - Agents generate ECDSA P-256 key pairs per certificate using `crypto/ecdsa` + `crypto/elliptic` (Go stdlib) - Key generation triggered by `AwaitingCSR` job state in renewal/issuance workflows - Agent creates Certificate Signing Request (CSR) with `x509.CreateCertificateRequest`, signed with the agent's private key - Only the CSR crosses the network to the control plane; private key material never leaves the agent - Configuration: `CERTCTL_KEYGEN_MODE=agent` (default, production) **Server-Side Key Generation (Demo Only)** - Available for development and testing via `CERTCTL_KEYGEN_MODE=server` - Explicitly logged as a warning at startup: "server-side key generation enabled (CERTCTL_KEYGEN_MODE=server) — private keys touch control plane, demo only" - Docker Compose demo uses server mode for backward compatibility - Not recommended for production; agent mode is the secure default **Entropy Source** - `crypto/rand` provides cryptographically secure random bytes - On Linux: backed by `/dev/urandom` via `getrandom()` syscall - On Windows: backed by `CryptGenRandom()` (now `BCryptGenRandom()`) - Meets NIST SP 800-90B requirements for entropy generation ## Key Storage and Protection (Sections 6.3, 6.4) certctl implements tiered key storage with different protection profiles based on key purpose. **Agent Private Keys** - Stored on agent filesystem at `CERTCTL_KEY_DIR` (default: `/var/lib/certctl/keys`) - File permissions: 0600 (read/write by agent process only, no world/group access) - One PEM file per certificate, organized by certificate ID - Accessible only to the agent process; isolated from other processes - For container deployments: use Docker volumes with restricted permissions (`-v /var/lib/certctl/keys:0600`) **Issuing CA Keys (Local CA Connector)** - Loaded from disk at server startup via `CERTCTL_CA_CERT_PATH` and `CERTCTL_CA_KEY_PATH` env vars - Supports RSA (PKCS#1, PKCS#8) and ECDSA (SEC1, PKCS#8) key formats - Validates certificate constraints before use: - `IsCA=true` flag present - `KeyUsageCertSign` extension set - Valid certificate chain (for sub-CA mode) - Keys held in memory during server runtime (no on-disk caching after load) - Cleared from memory only on server shutdown **Sub-CA Mode (Enterprise Integration)** - CA certificate and key signed by upstream enterprise root (e.g., Active Directory Certificate Services) - Certctl acts as subordinate CA, inheriting issuer DN from upstream CA - All issued certificates chain to enterprise trust anchor - CA key protection inherits upstream root's key management practices - Configured via: `CERTCTL_CA_CERT_PATH=/path/to/ca.crt` and `CERTCTL_CA_KEY_PATH=/path/to/ca.key` **NIST Gap: HSM Storage** NIST SP 800-57 Part 1 recommends Hardware Security Module (HSM) storage for high-value keys (CA signing keys). certctl V2 uses filesystem storage on the server. HSM support is planned for V5 roadmap, enabling integration with: - AWS CloudHSM - Azure Dedicated HSM - Thales Luna, Gemalto SafeNet, YubiHSM (on-premises) - PKCS#11-compatible devices ## Cryptoperiods (Section 5.3, Table 1) NIST recommends cryptoperiods (key validity durations) based on key type and security requirements. certctl enforces cryptoperiods through certificate profiles and renewal policies. **Certificate Profile Enforcement** - Certificate profiles (M11a) define `max_ttl` constraint per enrollment profile - All certificates issued through a profile cannot exceed the profile's max_ttl - Profile configuration example: ```json { "id": "prof-web-prod", "name": "Production Web Certs", "max_ttl_seconds": 31536000, // 1 year max "allowed_key_algorithms": ["ECDSA_P256"], "required_sans": ["example.com"] } ``` **Renewal Thresholds** - Renewal policies with configurable `alert_thresholds_days`: `[30, 14, 7, 0]` (days before expiry) - Background scheduler checks renewal eligibility every 1 hour - Certificates transitioned to `Expiring` status at 30 days, `Expired` at 0 days - Renewal workflow can be triggered manually or automatically **NIST Cryptoperiod Recommendations vs certctl Implementation** | Key Type | NIST Recommendation | certctl Implementation | |----------|---------------------|------------------------| | CA signing key | 3–10 years | Configured via CA certificate not-after date; inheritable from upstream CA in sub-CA mode | | End-entity web server cert | 1–3 years (trending shorter) | Profile `max_ttl` configurable; ACME issuer typically 90 days; SC-081v3 mandating 47 days by 2029 | | Code signing cert | 2–8 years | Profile enforcement via `max_ttl`; not primary certctl use case | | Short-lived credentials | < 1 hour recommended | Profile TTL < 1 hour; exempt from CRL/OCSP (expiry is sufficient revocation); auto-expiry on scheduler tick | | OCSP signing key | 1–2 years | Embedded OCSP responder uses issuing CA key (same period as issuer) or delegated signing cert | | TLS/SSL interoperability cert | 1–2 years | Trending 1 year or less; certctl's ACME/sub-CA/step-ca issuers all support short periods | ## Key States and Transitions (Section 5.2) NIST defines lifecycle states for keys: pre-activation, active, suspended, deactivated, compromised, and destroyed. certctl maps these to certificate and job states: | NIST Key State | certctl Equivalent | Implementation | |---|---|---| | **Pre-activation** | `Pending` job state / `AwaitingCSR` | Job created but key not yet generated; awaiting agent CSR submission (agent-mode) or server keygen (demo mode) | | **Active** | Certificate status `Active` | Cert deployed to targets and in use; within validity period (not before < now < not after) | | **Suspended** | Job state `AwaitingApproval` | Interactive approval holds deployment job pending human review; resumes on approval or cancels on rejection | | **Deactivated** | Certificate status `Expired` | Past not-after date; auto-transitioned by scheduler every 2 minutes; renewal eligible | | **Compromised** | Certificate status `Revoked` | Issued via `POST /api/v1/certificates/{id}/revoke` with RFC 5280 revocation reason | | **Destroyed** | Archived (implementation detail) | Operator responsibility; certctl retains all certs in audit trail for compliance; no destructive deletion API | **State Transition Audit Trail** All transitions logged to immutable `audit_events` table with: - Event type (e.g., `certificate_revoked`, `renewal_job_completed`) - Actor (authenticated user or agent ID) - Timestamp (RFC3339) - Resource (certificate ID) - Reason (revocation reason code, approval reason, etc.) - HTTP method, path, status (for API calls) Example audit entry for revocation: ```json { "id": "ae-2024-0615", "event_type": "certificate_revoked", "actor": "ops-alice@example.com", "timestamp": "2024-06-15T14:23:00Z", "resource_id": "cert-web-prod-2024", "resource_type": "certificate", "description": "Revoked: reason=keyCompromise", "body_hash": "sha256:a1b2c3d..." } ``` ## Algorithm Recommendations (Section 5.1, SP 800-131A) NIST SP 800-131A Rev 2 (January 2024) categorizes cryptographic algorithms as Approved, Conditionally Approved, or Disallowed. certctl implements only NIST-approved algorithms: | Algorithm | NIST Status | certctl Support | Notes | |-----------|-------------|-----------------|-------| | **ECDSA P-256** | Approved (128-bit security strength) | Default for agent-side keygen | Meets NIST curve requirements (FIPS 186-4) | | **ECDSA P-384** | Approved (192-bit security strength) | Supported via profile configuration | Higher security margin; slower than P-256 | | **ECDSA P-521** | Approved (256-bit security strength) | Supported via profile configuration | Rarely needed; overkill for TLS | | **RSA 2048** | Approved minimum (112-bit security, transitioning) | Supported via all issuers | Deprecated path; migrate to 3072+ by 2030 per NIST | | **RSA 3072** | Approved (128-bit security) | Supported via all issuers | Recommended minimum for long-term security | | **RSA 4096** | Approved (192-bit security) | Supported via all issuers | Supported but slower; overkill for most TLS | | **SHA-256** | Approved | Used throughout | CSR signing, certificate fingerprints, audit body hashing, CRL/OCSP signing | | **SHA-384** | Approved (192-bit) | Supported where algorithm selection available | Used in some CA signing scenarios | | **SHA-512** | Approved (256-bit) | Supported where algorithm selection available | Rarely needed; SHA-256 suffices for most use cases | | **SHA-1** | Deprecated | Not used in certctl | Browsers reject SHA-1 certs; certctl never generates them | **Algorithm Enforcement via Profiles** Certificate profiles enforce allowed key algorithms: ```json { "id": "prof-web-prod", "allowed_key_algorithms": ["ECDSA_P256", "ECDSA_P384", "RSA3072"] } ``` **Post-Quantum Cryptography (Tracking)** NIST has finalized PQC standards (FIPS 204, FIPS 205) in August 2024: - **ML-KEM** (Kyber): Approved key encapsulation mechanism - **ML-DSA** (Dilithium): Approved digital signature algorithm - **SLH-DSA** (SPHINCS+): Approved stateless hash-based signature scheme certctl will track NIST's PQC roadmap and plan integration when hybrid PQC+classical certificate formats reach browser/infrastructure support. Currently, pure PQC certificates are not widely interoperable. ## Key Distribution and Transport (Section 6.2) NIST SP 800-57 Part 1 Section 6.2 addresses secure key distribution to minimize exposure during transit. certctl implements a zero-transmission-of-private-keys model: **Private Key Distribution** - Agent-side keygen model: Private keys never leave agent infrastructure - CSR transmitted over HTTPS (TLS 1.2+) with mutual TLS optional - API key authentication via `Authorization: Bearer ` header - All API calls logged to immutable audit trail **Signed Certificate Distribution** - Certificates (public component) distributed via `GET /agents/{id}/work` over HTTPS - Work endpoint enriches deployment jobs with certificate PEM and metadata - Certificate PEM is idempotent (same cert always returns same bytes) **Target Deployment** - Deployment to targets via local filesystem write (NGINX, Apache, HAProxy) - No network transmission of private keys to targets - Agents read local private key from `CERTCTL_KEY_DIR` on deployment - For appliances without agents (F5 BIG-IP, IIS), proxy agent pattern: - Proxy agent runs in same trust zone as appliance - Proxy agent holds target API credentials (iControl, WinRM) - Control plane never communicates with appliance directly - Deployment request includes certificate and proxy agent ID - Proxy agent executes deployment via appliance API **Revocation Distribution** - Certificate Revocation List (CRL) via `GET /api/v1/crl/{issuer_id}` - Returns DER-encoded X.509 CRL signed by issuing CA - 24-hour validity period - Includes all revoked serials, reasons, and revocation timestamps - Subject to URL caching; OCSP preferred for real-time revocation - OCSP via `GET /api/v1/ocsp/{issuer_id}/{serial}` - Returns DER-encoded OCSP response (OCSPResponse ASN.1 structure) - Signed by issuing CA (or delegated OCSP signing cert) - Responds with good/revoked/unknown status - Real-time, more bandwidth-efficient than CRL polling ## Revocation and Compromise (NIST SP 800-57 Part 3) NIST SP 800-57 Part 3 covers revocation (Section 2.5) when keys are suspected compromised or no longer needed. certctl implements comprehensive revocation infrastructure: **Revocation API** - Endpoint: `POST /api/v1/certificates/{id}/revoke` - Request body: ```json { "reason": "keyCompromise", "reason_text": "Private key exposed in log file" } ``` - Supports all 8 RFC 5280 revocation reason codes: - `unspecified` — no specific reason provided - `keyCompromise` — private key suspected compromised - `caCompromise` — issuing CA key compromised - `affiliationChanged` — subject org/affiliation changed - `superseded` — cert superseded by newer cert - `cessationOfOperation` — key no longer in use - `certificateHold` — temporary hold (rarely used) - `privilegeWithdrawn` — subject authorization withdrawn **Revocation Recording** - Certificate status updated to `Revoked` - Entry recorded in `certificate_revocations` table with: - Certificate serial number - Revocation timestamp - Revocation reason code - Issuer ID - Idempotent (revoking an already-revoked cert is safe; returns 200 OK) **Issuer Notification (Best-Effort)** - Control plane calls `issuer.RevokeCertificate(ctx, serial, reason)` on issuing connector - Failure does not block the revocation (async, logged, retried) - Supported issuers: - Local CA: generates new CRL immediately - ACME: submits revocation to ACME server (RFC 8555 Section 7.6) - step-ca: calls `/revoke` API - OpenSSL: executes user-provided revocation script **Revocation Notifications** - Notifiers triggered after revocation recorded: Slack, Teams, PagerDuty, OpsGenie, email, webhook - Message includes certificate common name, issuer, reason, actor, timestamp - Delivery is asynchronous and retried on failure **CRL and OCSP Distribution** - CRL updated on every revocation (or scheduled refresh for non-issued revocations) - OCSP responder queries revocation table in real-time - Short-lived certificate exemption: certs with TTL < 1 hour skip CRL/OCSP (expiry is sufficient revocation) **Revocation Audit Trail** All revocation events logged: - Event type: `certificate_revoked` - Actor: authenticated user or service - Reason code: RFC 5280 enum - Timestamp: RFC3339 - Issuer notification status: success or error reason ## Alignment Summary Table | NIST SP 800-57 Area | Status | Coverage | Notes | |---|---|---|---| | **Key Generation** | ✅ Aligned | 100% | Agent-side ECDSA P-256 using crypto/rand; server mode flagged as demo-only | | **Key Storage** | ⚠️ Partially Aligned | 80% | Filesystem with 0600 perms; HSM support planned V5 | | **Cryptoperiods** | ✅ Aligned | 100% | Profile-enforced max_ttl; threshold-based renewal alerting | | **Key States** | ✅ Aligned | 100% | Full lifecycle tracking with immutable audit trail | | **Algorithms** | ✅ Aligned | 100% | NIST-approved algorithms only; post-quantum tracking in progress | | **Key Distribution** | ✅ Aligned | 100% | Private keys never transmitted; CSR/cert over TLS; agent-local deployment | | **Revocation** | ✅ Aligned | 100% | CRL, OCSP, all RFC 5280 reason codes; real-time updates | ## Gaps and Remediation Roadmap ### V2 (Current) - [x] Agent-side key generation - [x] Profile-enforced cryptoperiods - [x] CRL and OCSP distribution - [x] RFC 5280 revocation support - [x] Immutable audit trail ### V3 (Planned: 2026) - Role-based access control (limit revocation/approval to authorized operators) - Bulk revocation by profile/owner/agent (fleet-level revocation policy) ### V5 (Planned: 2027+) - HSM support for CA key storage - PKCS#11 integration for hardware tokens - FIPS 140-2/3 validated crypto module (BoringCrypto build or external FIPS library) - Key destruction API (explicit secure erasure of agent keys) - Key escrow / recovery mechanism (backup encrypted private keys for disaster recovery) ### Post-Quantum (2027+) - ML-KEM and ML-DSA support when browser/TLS ecosystem supports hybrid certificates - Migration path documentation (how to transition existing RSA certs to PQC) ## References - NIST SP 800-57 Part 1 Rev 5 (May 2020): https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57pt1r5.pdf - NIST SP 800-131A Rev 2 (January 2024): https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf - FIPS 186-4 (Digital Signature Standard): https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - RFC 5280 (X.509 PKI Certificate and CRL Profile): https://tools.ietf.org/html/rfc5280 - RFC 8555 (Automatic Certificate Management Environment): https://tools.ietf.org/html/rfc8555 - NIST FIPS 204 (ML-DSA): https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.204.pdf - NIST FIPS 205 (ML-KEM): https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.205.pdf ## Questions or Corrections? This document reflects certctl's implementation as of March 2026. For the latest code, refer to: - Key generation: `cmd/agent/main.go` (agent keygen) and `internal/service/renewal.go` (server keygen) - Key storage: `internal/config/config.go` (CERTCTL_KEY_DIR, CERTCTL_CA_CERT_PATH) - Revocation: `internal/service/revocation.go` and `internal/api/handler/certificates.go` - Audit trail: `internal/api/middleware/audit.go`