docs: re-lead positioning on the two-factor-KDF thesis; document the key-file second factor
README: open with the two-independent-secrets-into-KDF thesis; reframe the
second factor as pluggable (reference image or key file); keep the stego
deep-dive as a distinctive option; update all scenario tables, recovery section,
env-var hint, and roadmap line to use "second-factor secret" language.
docs/CRYPTO.md: add "Pluggable second-factor containers" subsection explaining
that the 32-byte input to Argon2id is identical regardless of container;
reference-image / key-file / recovery-QR are interchangeable carriers.
Update org-vs-personal comparison table and entropy labels.
docs/FORMATS.md: document the .relkey armor format (relicario-keyfile-v1 +
base64 line) and the params.json second_factor field ("image"|"keyfile",
absent means "image" for back-compat). Cite crates/relicario-core/src/keyfile.rs
keyfile_encode/keyfile_decode with TODO-pin comments. Update KDF input formula
from image_secret to second_factor_secret.
DESIGN.md: split secrets-map "Reference image bytes" row to distinguish image
and key-file containers; add key-file row noting keyfileBase64 in
chrome.storage.local has the same in-the-clear posture as imageBase64.
Update vault-layout note and KDF conventions row.
docs/SECURITY.md: add "Second-factor storage posture" subsection explicitly
stating .relkey and keyfileBase64 are the second factor in the clear — same
posture as the reference JPEG / imageBase64, not weaker, protected by the
passphrase invariant. Add RELICARIO_KEYFILE to the env-var trust surface table.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014THSV6cA4Gxa7bxFfisHBB
This commit is contained in:
@@ -32,11 +32,35 @@ Every encrypted file — `manifest.enc`, `settings.enc`, `items/<id>.enc`, `atta
|
||||
"argon2_m": 65536,
|
||||
"argon2_t": 3,
|
||||
"argon2_p": 4
|
||||
}
|
||||
},
|
||||
"second_factor": "image"
|
||||
}
|
||||
```
|
||||
|
||||
Parsed via `ParamsFile { kdf: KdfParams }` in `session.rs`. The `kdf` nesting is intentional — `format_version`, `aead`, and `salt_path` co-exist for forward-compat probing. Do not flatten. Production defaults: `m=65536` (64 MiB), `t=3`, `p=4`. Tests use `m=256, t=1, p=1`.
|
||||
Parsed via `ParamsFile { kdf: KdfParams }` in `crates/relicario-core/src/crypto.rs`
|
||||
(`ParamsFile` struct; `second_factor` field added by
|
||||
<!-- TODO(dev-e): pin exact line once Dev-D's keyfile.rs lands -->
|
||||
`crates/relicario-core/src/crypto.rs`). The `kdf` nesting is intentional — `format_version`, `aead`, and `salt_path` co-exist for forward-compat probing. Do not flatten. Production defaults: `m=65536` (64 MiB), `t=3`, `p=4`. Tests use `m=256, t=1, p=1`.
|
||||
|
||||
### `second_factor` field
|
||||
|
||||
Top-level field on the `ParamsFile` wrapper. Value: `"image"` or `"keyfile"`. **Absent means `"image"`** — all existing vaults missing this field use the steganographic reference-image path (back-compatible). Clients read this field before the unlock prompt to decide whether to request a JPEG path or a `.relkey` file path.
|
||||
|
||||
## Key-file second factor (`.relkey`)
|
||||
|
||||
When `second_factor` is `"keyfile"`, the user holds a plain armored file instead of a steganographic JPEG. The file format is:
|
||||
|
||||
```
|
||||
relicario-keyfile-v1
|
||||
<base64 of 32 secret bytes>
|
||||
```
|
||||
|
||||
Exactly two lines, each terminated by a newline (`\n`). The first line is the literal ASCII string `relicario-keyfile-v1`. The second line is the standard base64 encoding (RFC 4648) of the 32-byte second-factor secret with no line wrapping.
|
||||
|
||||
- Suggested file extension: `.relkey`
|
||||
- The 32 bytes are the second-factor secret **in the clear** — this file is the "something you have". It is not itself encrypted. See [SECURITY.md](SECURITY.md) for the threat-model implications.
|
||||
- Source: `crates/relicario-core/src/keyfile.rs` — `keyfile_encode` / `keyfile_decode`
|
||||
<!-- TODO(dev-e): pin exact line once Dev-D's keyfile.rs lands -->
|
||||
|
||||
## `.relicario/salt`
|
||||
|
||||
@@ -159,10 +183,10 @@ Full item type inventory: `crates/relicario-core/ARCHITECTURE.md` § "Module map
|
||||
The password fed to Argon2id is length-prefixed to prevent extension attacks:
|
||||
|
||||
```
|
||||
u64_be(len(passphrase)) || passphrase_bytes || u64_be(32) || image_secret
|
||||
u64_be(len(passphrase)) || passphrase_bytes || u64_be(32) || second_factor_secret
|
||||
```
|
||||
|
||||
NFC-normalized before hashing. Covered in `crypto.rs:229-236` and tested in `tests/format_v2.rs:44-54`.
|
||||
`second_factor_secret` is always 32 bytes extracted from whichever container the vault uses (reference image via `imgsecret::extract()` or key file via `keyfile_decode()`). The KDF input is byte-for-byte identical regardless of container. NFC-normalized before hashing. Covered in `crypto.rs:229-236` and tested in `tests/format_v2.rs:44-54`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user