LumoSQL implements a basic libsodium page-level encryption demo, with simple SQLite-style key management. This demonstrates encryption works. Now we need to think about how we use the encryption framework in LMDBv1.0 to do implement comprehensive encryption.
Note that row-level encryption is a completely different concept. It builds on the existing LumoSQL row-level checksums and is not addressed in this document.
What we need to do next:
- Interactive key prompt:
.lumo-keydot-command reading from/dev/ttyvia getpass(3);--key-fd=Nand--key-stdinflags. Production needs this; passphrase on the command line leaks to ps, history, and /proc/PID/cmdline. - Key rotation: a
lumo_rekeyPRAGMA. LMDB has no in-place rekey, so this means a clone-with-new-key pass. - Raw-hex key form
lumo_key="x'..bytes..'"for callers that have already done their own KDF or use a KMS. - Argon2id parameters: expose ops/mem cost as build defines, document the security/UX trade-off, consider SENSITIVE-class as a build option.
- Better error reporting: SQLITE_AUTH currently surfaces as the shell's generic "unable to open database, unknown error". One small shell.c edit gives a useful message.
- Decide what to do about
MDB_WRITEMAP: assert it cannot coexist with encryption, document, possibly disable the option for encrypted builds.
Things to note:
MDB_REMAP_CHUNKS is the main point. LMDB 0.9.x's whole-file mmap means there's no natural "page is read in" event — the kernel page-faults pages of the mmap'd file directly. v1.0 line gives up the single-mmap and pages live in chunk-sized mmap regions that get faulted in via explicit calls. Decryption happens in the chunk caching layer.
The cipher choice is delegated to the app. LMDB provides a callback and apps such as LumoSQL provide OpenSSL, libsodium etc as they wish.
AEAD by default in the reference impl. ChaCha20-Poly1305 is authenticated encryption. This means "did this page get corrupted on disk or attacked?" is answered, together with confidentiality.
Persistent MDB_ENCRYPT flag. The env file remembers whether it was created encrypted, so opening a non-encrypted env with a key (or vice versa) returns MDB_ENV_ENCRYPTION.
Performance implications The MDB_REMAP_CHUNKS mode necessarily costs throughput vs a single-mmap LMDB — every page access goes through a chunk-cache lookup, every dirty page goes through encryption before flush, every read decrypts. The exact cost depends on workload.
This obsoletes much of MDB_WRITEMAP. With chunk-based remapping, the "writable mmap, kernel handles writeback" path can't trivially carry encryption writemap-mode probably becomes incompatible with encryption. We lose the write performance optimisation.
Key management is deliberately not solved That's for LumoSQL to sort out, as is proper.