secret
An OCaml library for key material. A Secret.t owns a
fixed-length buffer allocated in C memory, so the garbage collector
never copies the payload and never leaves a stale copy behind. The
bytes are zeroized on destroy, when the handle is
collected, and at normal process exit.
- The payload is unreachable through polymorphic
compare,Hashtbl.hashandMarshal; printing is redacted. equalcompares contents in time that depends only on the length.- Zero-copy views hand existing
string- andbytes-based APIs the secret memory itself. - An optional hardened tier adds guard pages, a canary, page locking, and core-dump exclusion, and reports per value what it actually got — or fails closed on request.
| Case | Raw key | Expanded key |
|---|---|---|
Key held only in Secret.t | 0 | 0 |
| Zero-copy view; schedule died young and the minor heap was scrubbed | 0 | 0 |
| Zero-copy view; schedule reached the major heap | 0 | 1 |
| Heap-string baseline; schedule reached the major heap | 1 | 1 |
The scanner walks every writable mapping of the process looking for the
key. Passing a view instead of a string removes the raw-key
copy; it cannot remove a key schedule the receiving library built in the
OCaml heap. Method and full output:
the leak census.
Experimental and unaudited. The API may change before 1.0. This library reduces the number of places a key can be read from; it is not a substitute for an HSM or a KMS when the threat model needs hardware-backed isolation.
| Release | 0.1.0 |
|---|---|
| OCaml | 4.14 and 5.0–5.5 |
| Tested platforms | Linux and macOS on every commit; musl and 32-bit weekly; Windows and solo5 best effort |
| Runtime dependencies | none beyond the standard library |
| License | ISC |
Quick start
opam pin add secret https://github.com/thevilledev/ocaml-secret.git
Depend on the library from dune:
(executable
(name main)
(libraries secret))
Generate a key, use it, and let the scope destroy it:
let aes =
Secret.with_random 32 (fun key ->
Secret.Unsafe.with_string_view key Mirage_crypto.AES.GCM.of_secret)
with_random writes OS entropy straight into the secret
memory — no copy passes through the OCaml heap — and
destroys the secret when the function returns or raises.
with_string_view hands mirage-crypto an ordinary
string whose bytes are that memory, so no copy is
made on the way in either. Nothing here waits for the collector.
Choose a tier
- Default
-
callocmemory, zeroed on release, with unviewed blocks pooled for reuse. About 75 ns to create and destroy. Use it for many small or short-lived keys. - Hardened
-
Secret.create ~hardened:truegives the payload its own mapping with guard pages on both sides, a canary,mlock, and exclusion from core dumps. Costs at least three pages of address space and roughly 1.6 µs per secret. Use it for long-lived root keys.
Hardening is disabled by default, and every hardening feature is best
effort and platform-dependent.
Secret.status reports what a given value actually got, and
Secret.require_hardening turns a missing protection into a
raised exception rather than a silent downgrade. See
what is and is not guaranteed, or start
with usage.