docs: add README with security model and CLAUDE.md project context
This commit is contained in:
73
CLAUDE.md
Normal file
73
CLAUDE.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# CLAUDE.md — idfoto
|
||||
|
||||
## What is this
|
||||
|
||||
idfoto is a git-backed, self-hostable password manager with a Rust core. Two-factor vault decryption: passphrase + a reference JPEG carrying a 256-bit secret embedded via DCT steganography. The server only ever sees opaque ciphertext.
|
||||
|
||||
## Build and test
|
||||
|
||||
```bash
|
||||
cargo build # build everything
|
||||
cargo test # run all tests (unit + integration)
|
||||
cargo test -p idfoto-core # core library tests only
|
||||
cargo run -- --help # CLI help
|
||||
cargo run -- generate -l 32 # quick smoke test
|
||||
```
|
||||
|
||||
## Project structure
|
||||
|
||||
```
|
||||
crates/
|
||||
├── idfoto-core/ # Platform-agnostic library (no filesystem, no git, no network)
|
||||
│ ├── src/
|
||||
│ │ ├── lib.rs # Re-exports public API
|
||||
│ │ ├── error.rs # IdfotoError enum (thiserror)
|
||||
│ │ ├── crypto.rs # Argon2id KDF + XChaCha20-Poly1305 encrypt/decrypt
|
||||
│ │ ├── entry.rs # Entry, ManifestEntry, Manifest structs (serde)
|
||||
│ │ ├── vault.rs # encrypt_entry, decrypt_entry, encrypt_manifest, decrypt_manifest
|
||||
│ │ └── imgsecret.rs # DCT-based 256-bit secret embedding in JPEGs
|
||||
│ └── tests/
|
||||
│ └── integration.rs # Full-workflow and two-factor independence tests
|
||||
└── idfoto-cli/ # CLI binary
|
||||
└── src/
|
||||
└── main.rs # clap CLI: init, add, get, list, edit, rm, sync, generate, device
|
||||
```
|
||||
|
||||
## Key design decisions
|
||||
|
||||
- **idfoto-core is bytes-in/bytes-out.** No filesystem, no network, no git operations. Makes it portable to WASM, Android, iOS.
|
||||
- **XChaCha20-Poly1305** over AES-GCM — 192-bit nonce eliminates collision risk, fast in WASM/ARM without AES-NI.
|
||||
- **Single master_key** (no per-entry subkeys) — simpler, sufficient for family vault sizes.
|
||||
- **imgsecret uses central-embed DCT** — embeds only in the middle 70% of the image (15% crumple zone for crop tolerance), with majority voting across 5-50 redundant copies.
|
||||
- **QUANT_STEP = 50.0** — higher than typical (25) to survive JPEG recompression down to Q85.
|
||||
- **Device ed25519 keys are separate from the KDF.** Revoking a device doesn't require rotating the passphrase or reference image.
|
||||
|
||||
## Crypto pipeline
|
||||
|
||||
```
|
||||
passphrase (UTF-8 bytes) || image_secret (32 bytes from reference JPEG)
|
||||
→ Argon2id(salt=vault_salt, m=64MiB, t=3, p=4)
|
||||
→ master_key (32 bytes)
|
||||
→ XChaCha20-Poly1305(nonce=random 24 bytes)
|
||||
→ encrypted entry/manifest
|
||||
```
|
||||
|
||||
## Conventions
|
||||
|
||||
- Tests use fast Argon2id params (m=256, t=1, p=1) so they don't take forever.
|
||||
- Test JPEGs are generated synthetically via `make_test_jpeg()` — no binary test fixtures.
|
||||
- Entry IDs are random 8-char hex strings.
|
||||
- Git history is preserved as an audit log — no squashing.
|
||||
- The CLI shells out to `git` for sync — no libgit2/gitoxide dependency.
|
||||
|
||||
## Remote
|
||||
|
||||
Source code: `ssh://git@git.adlee.work:2222/alee/idfoto.git`
|
||||
|
||||
## Design spec
|
||||
|
||||
Full threat model, entropy analysis, and architecture: `docs/superpowers/specs/2026-04-11-idfoto-design.md`
|
||||
|
||||
## Roadmap
|
||||
|
||||
Next: WASM build + Chrome MV3 browser extension (Plan 2). Then mobile (Rust core compiles to ARM).
|
||||
Reference in New Issue
Block a user