Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Architecture Overview

hoike is built around a single architectural bet: separate signing from serving. The OCSP signing key never touches a machine that handles client traffic. An edge node compromise cannot produce a false “good” response because edge nodes have no signing material – they serve only pre-signed bytes delivered through a verified bundle chain.

The signer/edge split

Traditional OCSP responders combine signing and serving in one process. Every node that handles client requests holds the signing key, which makes each node a high-value target. hoike eliminates this by splitting the work into two roles:

graph LR
    subgraph Signer["Signer (HSM / enclave)"]
        CRL[CRL + serial list] --> Sign[Batch sign]
        Sign --> Bundle[ahu bundle]
    end
    subgraph Distribution
        Bundle -->|gossip / push / sneakernet| Edge1[Edge 1]
        Bundle -->|gossip / push / sneakernet| Edge2[Edge 2]
        Bundle -->|gossip / push / sneakernet| EdgeN[Edge N]
    end
    subgraph Clients
        C1[OCSP client] -->|HTTP| Edge1
        C2[OCSP client] -->|HTTP| Edge2
    end
ConcernSignerEdge
Signing key accessYes (HSM or file)Never
Client trafficNeverYes
Network exposureMinimal or air-gappedInternet-facing
Cryptographic work at request timeN/AZero
Scaling modelSingle or active-passive pairHorizontal, stateless

Trust boundary

The fundamental invariant:

An edge node compromise must not produce a false “good” response.

Edge nodes are keyless replay engines. They memory-map a verified ahu bundle and return pre-signed bytes verbatim. Without the signing key, a compromised edge can only:

  • Serve stale responses (mitigated by anti-rollback epoch checks)
  • Refuse to serve (denial of service, not a trust violation)
  • Serve the wrong response for a serial (mitigated by the sealed index)

It cannot forge a “good” response for a revoked certificate.

Three operating modes

hoike runs as a single binary (hoike) in one of three modes:

Signer mode

The signer reads CA material (issuer certificate, signing key, CRLs, good serial lists), batch-produces pre-signed OCSP responses, and packages them into ahu bundles. It can optionally push bundles to edge nodes via gossip.

hoike sign \
  --ca my-issuing-ca \
  --issuer-cert ca.crt \
  --signer-cert ocsp.crt \
  --signer-key ocsp.key \
  --crl ca.crl \
  --good-serials serials.txt \
  --sig-alg ecdsa-p256 \
  --epoch 42 \
  --output my-ca.ahu

The signer is the only component that touches private keys.

Edge mode

The edge serves HTTP OCSP responses from one or more loaded ahu bundles. It performs no cryptographic operations at request time – responses are returned as raw bytes from memory-mapped bundle files.

hoike serve \
  --config /etc/hoike/hoike.toml \
  --bundle-dir /var/lib/hoike/bundles

Combined mode

For smaller deployments, hoike can run signing and serving in a single process. The trust boundary still exists logically: signing happens on a timer (batch interval) and the edge path reads from the resulting bundle.

This mode is convenient for development and single-machine deployments but sacrifices the physical isolation that makes the signer/edge split valuable.

Tier responsibilities

Each tier manages distinct state:

TierStateful componentsPersistence
Source (CA)Certificate database, CRLs, revocation recordsAuthoritative – hoike reads but does not modify
SignerBatch position, current epoch, HSM session, signing keyDurable – epoch must advance monotonically
EdgeLoaded working set (mmap’d bundles), epoch marks per CAEphemeral – reconstructible from latest bundle

State flow

graph TD
    Source["Source (CA)"] -->|CRL + serial list| Signer
    Signer -->|ahu bundle| Edge
    Edge -->|pre-signed bytes| Client

State flows strictly downward. The edge never writes back to the signer, and the signer never writes back to the source CA.

Workspace crate map

hoike is a Cargo workspace with six crates. The dependency graph enforces architectural boundaries:

graph TD
    CLI[hoike-cli] --> Server[hoike-server]
    CLI --> Sign[hoike-sign]
    Server --> Core[hoike-core]
    Sign --> Core
    Server --> Gossip[hoike-gossip]
    Core --> Ahu[ahu]
    Sign --> Ahu
CratePurposeLicenseKey deps
ahuBundle format read/write/verifyApache-2.0 OR MITder, ciborium, memmap2, zstd
hoike-coreCertID routing, request parsing, config, stateGPL-3.0+ahu, x509-ocsp, der
hoike-signResponse production, CRL parsing, batch signingGPL-3.0+ahu, hoike-core, ml-dsa
hoike-serveraxum HTTP handlers, RFC 9919 headersGPL-3.0+hoike-core, axum, tokio
hoike-gossipSWIM membership + generation announcementsGPL-3.0+foca
hoike-cliBinary entry points for hoike and ahuGPL-3.0+all above

The ahu crate is dual-licensed so that other projects can consume the bundle format without GPL obligations. It must never depend on tokio, hyper, axum, or PKCS#11 – it is a pure data-format library.