ShrouDB
Reference

Security model

How ShrouDB protects data at rest, in memory, and in transit.

Principles

  • Fail closed. Without a valid token, a request is refused. With no tokens configured, every request is refused. If stored data fails an integrity check, the server stops instead of serving it.
  • No plaintext at rest. There is no unencrypted storage mode.
  • Short exposure in memory. Keys and decrypted values are held in containers that wipe their memory when released.

Data at rest

Encryption

Every record is encrypted with AES-256-GCM before it's written to the write-ahead log or a snapshot.

Master key

Moat needs a 256-bit master key, from SHROUDB_MASTER_KEY (64 hex characters) or a file named by SHROUDB_MASTER_KEY_FILE. Storage keys are derived from it with HKDF, separately for each namespace, so engines can't read each other's data. In production, keep the master key in a KMS, HSM, or secrets manager and inject it when the process starts.

Data in memory

  • Key material and decrypted values are wiped from memory when released.
  • Core dumps are disabled at startup on Linux and macOS, so a crash can't write keys to disk.
  • Courier decrypts a recipient only for the moment of delivery.

End-to-end mode

For searchable fields (Veil) and user fields (Sigil), clients can compute blind tokens themselves and send only those. The server indexes and matches the tokens without ever seeing the underlying value.

Data in transit

Moat serves TLS 1.3 using rustls. Client certificate authentication (mTLS) is not supported yet.

moat.toml
[server.tls]
cert = "/etc/moat/tls/cert.pem"
key  = "/etc/moat/tls/key.pem"

Access control

Every command is checked against the caller's token before it runs. Scopes take the form engine:namespace/access, where access is READ, WRITE, or *.

examples
*:*/*                 # everything (admin only)
cipher:customers/*    # one keyring
keep:*/READ           # read secrets, never write them
chronicle:*/READ      # query the audit log

Token comparison is constant-time, so response timing doesn't reveal which tokens exist.

Audit

Engines record their operations to Chronicle, and Moat writes an audit file to <data_dir>/audit.log. Chronicle's events are hash-chained, and VERIFY reports any event that was changed or removed.

Production checklist

  • Generate the master key with a CSPRNG (for example openssl rand -hex 32) and store it in a KMS or secrets manager.
  • Back up the master key separately from the data directory. Without it the data can't be recovered.
  • Enable TLS, or keep Moat on a private network reachable only by your services.
  • Give each service its own token with the narrowest scopes it needs. Keep *:*/* for operators.
  • Generate tokens with a CSPRNG and keep them out of source control.
  • Enable Chronicle and run VERIFY on a schedule.
  • Set rotation periods on Cipher keyrings.
  • Keep Sigil access tokens short-lived (access_ttl_secs).