Files
InkNote/backend
marcandClaude Opus 5 915856e1a4 Encrypt uploaded files at rest, like note bodies already were
Note text was encrypted from the start; the files beside it were not. A
copy of the uploads directory handed over every image in the clear while
the notes referring to them stayed unreadable — half a protection, and
the half that is easiest to walk off with.

Same key and cipher as note content, so a backup is worth exactly as much
as its .env either way, which was already true and is now true uniformly.

Files carry an INKENC01 header and say for themselves whether they are
encrypted. That is what makes the startup sweep idempotent, and it had to
be the file rather than a database row: attachments are shared between
users by content hash, so no single row owns one.

Named by the hash of the plaintext, so identical uploads still collapse
into one copy — a fresh IV per file would have defeated deduplication.
Read whole rather than streamed, because GCM only proves integrity at the
last block. Written through a temporary name and renamed, so a crash
cannot strand a half-encrypted file that would fail its tag forever.

Verified: the one existing attachment went from 78 to 114 bytes with the
header in front, a second start did nothing, and images still load in the
browser after a reload.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 19:11:08 +02:00
..
2026-02-17 19:25:52 +01:00