OCSP responder
A pre-signed, replayable, multi-CA OCSP responder with keyless edge serving and post-quantum ML-DSA support. Built in Rust.
hoike (Hawaiian) — to show, to exhibit, to testify. An OCSP responder does exactly one thing: it testifies to the status of someone else's certificate.
Signer/edge split architecture. The machine that signs status and the machine that serves it are never the same machine.
Responses are batch-signed by the signer tier and sealed into ahu bundles. Edge nodes serve stored bytes verbatim — no keys, no signing, no HSM access on the hot path.
Edge nodes hold no signing keys. An edge compromise cannot produce a
false good — only denial of service or stale replay
within nextUpdate.
One responder instance serves many CAs. Routing uses the
issuerKeyHash multimap from each OCSP request's
CertID, handling re-keyed and cross-signed CAs correctly.
ML-DSA-44, ML-DSA-65, and ML-DSA-87 signing as first-class configurations, not patches. Batching amortizes post-quantum signature size across certificate buckets.
Self-describing containers with CBOR manifest, CMS SignedData
seal, and a sorted index for O(log n) binary search. Seal verified
on load against configured trust anchors.
OCSP responses signed via hardware security modules through
cryptoki. Tested with Kryoptic; documented paths for
Thales Luna, Entrust nShield, Utimaco, and FutureX. Interactive PIN
prompt for production.
Bundles are sealed files that cross air gaps on removable media. Enclave mode uses byte-identical code paths — only acquisition differs. No gossip, no upstream, full functionality.
Epoch chain with persisted high-water marks prevents replay of older
generations. Fork detection catches duplicate signers immediately.
Stale-generation alerts before nextUpdate expires.
Edge fleet coordination via the SWIM protocol (foca). Generation announcements, membership tracking, and urgent revocation notices. Gossip is never authoritative for status.
Monitors OCSP signing certificate expiry. Warns before deadline,
executes a configurable rotation_command for CA-specific
renewal. Delegated certs embedded per RFC 9919 §3.2.2.
Per-CA nonce handling: ignore for pre-signed,
forward to proxy upstream, live for
on-demand signing with the client's nonce on signer nodes.
Configuring live on an edge is a startup error.
One BasicOCSPResponse carries both SHA-1 and SHA-256
CertID entries per RFC 9919. One signature, one payload,
two index records. Log SHA-1 usage to track migration.
RFC 4533 Content Synchronization source for Dogtag certificate databases.
Persistent sync cookie across signer cycles. Provides positive issuance
data for authoritative-complete bundles.
One bundle carries both ECDSA and ML-DSA responses. Clients select via
RFC 6960 §4.4.7.1 PreferredSignatureAlgorithms. No flag
day needed for PQC migration.
MmapBundle uses MAP_PRIVATE for large-scale edge serving.
At 100M entries (~45 GB): ~200 MB RSS, sub-100ms startup. Binary search
directly on the mmap'd index — no heap allocation per lookup.
REST admin API with RBAC (Administrator / Operator / Viewer). React +
PatternFly 6 dashboard for bundle management, CA status, signing, and
OCSP query. Embeddable in the binary via --features embed-webui.
Sign a bundle, inspect it, start the responder.
$ hoike sign --ca enterprise-ca --crl revoked.crl --demo-key -o bundle.ahu
INFO hoike::sign: reading CRL from 'revoked.crl' (42 entries)
INFO hoike::sign: signing with ecdsa-p256, epoch 1
INFO hoike::sign: wrote bundle.ahu (42 good, 3 revoked, 84 index entries)
$ ahu inspect bundle.ahu
format : ahu v1
producer : hoike 0.2.0
epoch : 1
scope : enterprise-ca (partial)
algorithm : ecdsa-p256
entries : 84 (42 good, 3 revoked, dual CertID)
size : 48.2 KB (zstd compressed)
$ hoike serve --config hoike.toml
INFO hoike: loading config from 'hoike.toml'
INFO hoike::core: loaded CA 'enterprise-ca' (45 entries, epoch 1)
INFO hoike::server: OCSP responder listening on 0.0.0.0:2560
$ hoike query --url http://localhost:2560 --serial 0A1B2C \
--issuer-name-b64 ... --issuer-key-b64 ...
INFO hoike::query: status=good, sig=ecdsa-p256, nextUpdate=2026-09-01RFCs and standards. 131 tests. 20 conformance assertions.
Full OCSP protocol with pre-signed response production, HTTP caching profile, nonce handling rules, and AIA discovery. Every protocol claim validated by wire-format conformance tests against OpenSSL and Go clients.
Container
# Pull pre-built image (x86_64 + arm64)
podman pull ghcr.io/czinda/hoike:0.2.0
podman run --rm \
-v ./hoike.toml:/etc/hoike/hoike.toml:ro \
-v ./bundles:/var/lib/hoike/bundles:ro \
-p 2560:2560 \
ghcr.io/czinda/hoike:0.2.0
Build from source
git clone https://github.com/czinda/hoike
cd hoike
cargo build --release
# Two binaries: hoike (~8 MB) and ahu (~1 MB)
cargo run --release -p hoike-cli -- \
serve --config hoike.toml
A Cargo workspace with six crates. The signer holds keys; the edge serves bytes.
Six crates with clean dependency boundaries.
Bundle format: read, write, verify, CMS seal, mmap zero-copy. Apache-2.0 OR MIT. No server dependencies.
CertID routing, request parsing, config, anti-rollback state store, seal verification on load.
CRL + syncrepl adapters, OCSP response & CMS seal creation, PKCS#11, ML-DSA bridge, live nonce signing, key rotation.
HTTP handlers via axum. Nonce policy dispatch, live signing, forward proxy. Admin API with RBAC auth. React webui (PatternFly 6).
SWIM membership and generation announcements via foca.
hoike + ahu binaries. The operator-facing surface.