Repository navigation
LockHTML v2.0.0
LockHTML v2.0.0
A hidden volume, a KDF that tunes itself to the machine, and launcher scripts that just run.
Highlights
- 🕳️ Hidden volume — a locked file can carry a second (or third…) payload behind its own PIN. The cover PIN opens the cover document; the hidden PIN opens entirely different bytes. The same idea as the duress PIN, generalised.
- 🎛️ Auto-calibrated KDF —
lockhtml calibratetimes one Argon2id pass on this machine and picks the strongest time cost that still unlocks in about half a second.--auto-kdfstores those parameters in the file, so it always opens at the cost it was made with. - 🎭 Streaming decoy — the duress PIN now works on streaming containers: it renders a small embedded page instead of ever decrypting the sidecar (whose MAC covers that page, so swapping it is detected).
- 🐢 Constant-memory save — the viewer can decrypt a streaming container straight to disk, chunk by chunk, via the File System Access API (Chromium). Other browsers keep the Blob download.
- 📁 Folders —
lock --recursive DIRon the CLI, and a folder picker plus directory drag-and-drop in the GUI. - 🚀 Launcher scripts —
lockhtml.sh/lockhtml.batandgui.sh/gui.batrun the CLI straight from a checkout, find Python 3.9+, prefer a local.venv, and tell you exactly what is missing. - 📦 PyPI-ready — a trusted-publishing
publish.ymlworkflow is included.
Usage
./lockhtml.sh calibrate # what can this machine afford?
./lockhtml.sh lock cover.html --pin 4821 --hidden-pin 0000 --hidden-file real.html --auto-kdf
./lockhtml.sh unlock cover.locked.html --pin 0000 # the hidden content
./lockhtml.sh lock ./contracts --recursive --pin 4821 --outdir ./lockedLive GUI
👉 https://drsamonline.github.io/lockhtml/
Verification
86 unit tests, a 35-check headless-Chrome run covering embedded, streaming, recipient, shares, hidden-volume and streaming-decoy paths, and 9 cross-implementation checks where the browser locks files the Python core then opens. All of it runs in CI.
What is not in this release, and why
ageinterop is deferred. It is a separate file format with its own chunked-ChaCha20-Poly1305 STREAM construction;cryptography's ChaCha20-Poly1305 has no Web Crypto equivalent, so it would be CLI-only, and it needs validating against the official age test vectors before it can be trusted. Shipping unverified crypto interop would be worse than not shipping it — it stays the top roadmap item.- PyPI publication needs one thing on your side: a trusted publisher configured for this repo. The workflow is ready; the account access is not something CI has.
Security note
A hidden volume is plausible deniability, not proof of absence — the extra slots are visible in the file's JSON to anyone who looks, they simply cannot be read without their PIN. See SECURITY.md and the self-audit in docs/AUDIT.md.