Keymaker v2.1.0
Keymaker v2.1.0, writing KEYM v3 containers. Those are two
different version numbers and they move independently — see the bottom of these
notes if a file will not open.
What changed
Keymaker v2.1.0 — the KEYM v3 container, and an identity that can be checked
Everything between v1.0.0 and v2.1.0. The v2.0.0 tag was cut mid-stream while
the changelog still said "Unreleased", so there is no separate v2.0.0 section;
the commit range is the authority for that split.
The app writes KEYM v3. v3 authenticates the slot table as a whole, which
v2 does not: a v2 table is authenticated slot by slot, so anyone who could
write the file could delete a slot and the container still opened normally for
everyone else — the owner saw their data and had no way to notice an heir's
recovery path was gone. That attack was reproduced before anything was
designed. The fix is a slot_table_mac over the core header, the slot count and
every slot record, plus a container_id that makes each container's AAD unique.
The other two attacks tried — reordering and transplanting a slot — turned out
to be inert, and the document says so rather than claiming defeated attacks.
KEYM v1 and v2 stay readable, permanently. The version byte dispatches and the
frozen fixtures prove it.
Ways to open a container, beyond a password: Shamir recovery shares for
inheritance, a passkey slot via WebAuthn PRF, a paper vault print kit,
and a self-extracting HTML page that opens a backup with no app at all.
Everything is stated twice and checked against itself. The container format is
specified in docs/ before it is built, then implemented independently in
TypeScript and in a Python reference that cross-tests byte for byte. Builds are
reproducible — twice on one runner, and on runners differing in Node major and
checkout path — and the manifest is Sigstore-signed, so a stranger can rebuild
the deployment and compare rather than trust it.
The interface is "Nightpaper": one warm near-black family, elevation by
hairline rather than shadow, no accent colour, and npm run test:palette holds
every painted colour in the rendered app to the design document.
Known limit: Satoshi heads the text stacks but is not vendored. The ITF Free
Font License forbids redistributing the binary through a repository, so the
display weight falls back to the system UI face. Self-hosting is permitted and
remains open if written permission is obtained.
Full detail in CHANGELOG.md.
Verifying this release
Two checks, and they answer different questions. Neither of them asks you to
trust this project's own tooling.
1. The files are the ones this tag produced.
tar -xzf keymaker-v2.1.0.tar.gz && cd keymaker-v2.1.0
sha256sum -c SHA256SUMSsha256sum is on every Unix machine and has nothing to do with this project,
which is the point.
2. This repository's release workflow is what signed that manifest.
cosign verify-blob \
--bundle SHA256SUMS.sigstore \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-identity 'https://github.com/404SecNotFound/Keymaker-v2/.github/workflows/release.yml@refs/tags/v2.1.0' \
SHA256SUMSKeyless signing: there is no published key to obtain and therefore no key
distribution to get wrong. The check is not "signed by a key we told you about"
— it is "signed by this workflow, in this repository", and
--certificate-identity is the flag that makes it so. Without it,
cosign verify-blob accepts a signature from anybody and says "Verified OK".
Note that the identity above ends in release.yml@refs/tags/v2.1.0, while
docs/VERIFYING.md gives deploy.yml@refs/heads/main for
the live site. Different workflows sign the two things, so they are different
identities and neither will verify the other. That document is where these
commands come from — they are generated from it, not maintained beside it.
What this artifact is
The site as built from this tag, with the Pages base path, so it is directly
comparable to a deployment of the same commit.
Not byte-identical to whatever the live site is serving right now, and it would
be dishonest to imply otherwise: the live site tracks main, so unless the
deployment is of this exact tag it is a different commit. The two are also
labelled differently on purpose — a build from this workflow says
v2.1.0, a rolling deployment says v2.1.0-dev — so that a
version number never names an artifact you are not running. Each is verified
against its own signing identity; neither is offered as a proxy for the other.
It is built with the Pages base path, so it expects to be served from
/Keymaker-v2/. That makes it a verification artifact rather than a drop-in
for hosting elsewhere; to host it at another path, build from source, which
docs/VERIFYING.md also covers.
Container format
This release writes KEYM v3 containers. The format is specified in
docs/FORMAT-V3-DESIGN.md and implemented
independently in reference/keym2.py, which decrypts your
files without this application, this website, or a browser. If this project
disappears, that file and the printed procedure in
docs/RECOVERY.md are enough.
v2.1.0 is the application version. KEYM v3 is the format version. They are
separate numbers on purpose, because they answer different questions: which app
you are running, and which file you are holding. A file that will not open is
almost always a question about the second.