diff --git a/README.md b/README.md index da1b5c8..96c170c 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,9 @@ To unlock the vault, you provide your passphrase and point the client at the ref A git repository containing: - `manifest.enc` — opaque binary blob -- `entries/*.enc` — more opaque binary blobs +- `items/*.enc` — more opaque binary blobs +- `attachments//*.enc` — encrypted attachment blobs +- `settings.enc` — encrypted vault settings - `.relicario/salt` — a random 32-byte value (not secret) - `.relicario/params.json` — Argon2id parameters (not secret) - `.relicario/devices.json` — authorized device public keys @@ -114,12 +116,23 @@ relicario/ │ ├── relicario-core/ # Platform-agnostic library (no filesystem, no network) │ │ ├── crypto.rs # Argon2id KDF + XChaCha20-Poly1305 AEAD │ │ ├── imgsecret.rs # DCT steganography: embed/extract 256-bit secrets in JPEGs -│ │ ├── entry.rs # Entry, Manifest data model (serde) -│ │ └── vault.rs # Encrypt/decrypt entries and manifests -│ └── relicario-cli/ # CLI binary: filesystem, git, terminal I/O +│ │ ├── item.rs # Item, Field, Manifest data model (serde) +│ │ ├── item_types/ # Per-type cores (Login, SecureNote, Card, Identity, Key, Document, Totp) +│ │ ├── attachment.rs # Encrypted attachment helpers (content-addressed) +│ │ ├── settings.rs # VaultSettings (retention, generator defaults, caps) +│ │ ├── backup.rs # `.relbak` encrypted-backup envelope +│ │ ├── device.rs # ed25519 device keys + revocation entries +│ │ └── vault.rs # Encrypt/decrypt items, manifest, settings +│ ├── relicario-cli/ # CLI binary: filesystem, git, terminal I/O +│ ├── relicario-wasm/ # Thin wasm-bindgen wrapper for the browser extension +│ └── relicario-server/ # Pre-receive hook: device-signature verification +├── extension/ # Chrome MV3 / Firefox WebExtension (TypeScript) └── docs/ + ├── ARCHITECTURE.md # System overview + flow diagrams + ├── SECURITY.md # Manifest integrity model + threat notes + ├── architecture/ # Cross-codebase + per-codebase architecture docs └── superpowers/ - └── specs/ # Design specification with full threat model + └── specs/ # Design specifications with full threat model ``` `relicario-core` takes bytes and returns bytes. It has no knowledge of filesystems, git, or networks. This makes it portable to WASM (browser extension), Android (JNI), and iOS (Swift bridge). @@ -144,17 +157,22 @@ Every write generates a fresh random nonce. The version byte allows future forma ``` my-vault.git/ -├── manifest.enc # Encrypted entry index (names, URLs, timestamps) -├── entries/ -│ ├── a1b2c3d4.enc # One encrypted entry per file -│ └── e5f6a7b8.enc +├── manifest.enc # Encrypted item index (names, URLs, timestamps) +├── settings.enc # Encrypted vault settings (retention, caps, generator defaults) +├── items/ +│ ├── a1b2c3d4e5f6a7b8.enc # One encrypted item per file +│ └── … +├── attachments/ +│ └── / +│ └── .enc # Content-addressed encrypted attachment blob └── .relicario/ ├── salt # 32-byte random salt (not secret) ├── params.json # KDF parameters - └── devices.json # Authorized device public keys + ├── devices.json # Authorized device public keys + └── revoked.json # Revoked device records (when device auth is enabled) ``` -Entry IDs are random hex strings. Git history is preserved — every add/edit/delete is a commit. "When was this password last rotated?" is answered by `git log`. +Item IDs are random 16-char hex strings (64 bits of entropy). Git history is preserved — every add/edit/delete is a commit. "When was this password last rotated?" is answered by `git log` and by the per-item field history. ## Device management @@ -183,13 +201,17 @@ The binary is at `target/release/relicario`. ## Roadmap -- [ ] WASM build + Chrome browser extension (inline crypto, no native messaging) -- [ ] Secure notes (free-form encrypted text entries) -- [ ] Secure document storage (encrypted file attachments up to 5-10 MB) +- [x] WASM build + Chrome MV3 browser extension (inline crypto, no native messaging) +- [x] Firefox WebExtension build +- [x] Typed items: Login, SecureNote, Identity, Card, Key, Document, TOTP +- [x] Secure document storage (encrypted file attachments) +- [x] Backup & restore (`.relbak` encrypted envelope) +- [x] LastPass CSV import +- [x] Device authentication (ed25519 commit signing + pre-receive hook) +- [ ] Import from Bitwarden / 1Password - [ ] `relicario unlock` daemon (ssh-agent-style, holds master key for a TTL) - [ ] Android/iOS clients (Rust core compiles to ARM) -- [ ] Import from LastPass/Bitwarden/1Password -- [ ] Firefox/Safari extensions +- [ ] Safari extension ## License diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index f415380..02bb07f 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -42,15 +42,19 @@ ┌──────────────────────────────────────────────────────────────────┐ │ GIT SERVER (untrusted) │ │ │ -│ relicario-vault.git/ │ -│ ├── manifest.enc ← opaque ciphertext │ -│ ├── entries/ │ -│ │ ├── a1b2c3d4.enc ← opaque ciphertext │ -│ │ └── e5f6a7b8.enc ← opaque ciphertext │ -│ └── .relicario/ │ +│ relicario-vault.git/ │ +│ ├── manifest.enc ← opaque ciphertext │ +│ ├── settings.enc ← opaque ciphertext │ +│ ├── items/ │ +│ │ ├── a1b2c3d4e5f6a7b8.enc ← opaque ciphertext │ +│ │ └── … │ +│ ├── attachments/ │ +│ │ └── /.enc ← opaque ciphertext │ +│ └── .relicario/ │ │ ├── salt ← 32 bytes (not secret) │ │ ├── params.json ← KDF params (not secret) │ -│ └── devices.json ← device public keys (not secret) │ +│ ├── devices.json ← device public keys (not secret) │ +│ └── revoked.json ← revoked device records (not secret) │ │ │ │ The server sees NOTHING useful. No keys, no plaintext, │ │ no metadata about what's inside. │ @@ -217,21 +221,23 @@ Input JPEG (possibly re-encoded or cropped) │ uses ▼ ┌────────────────────────────────────────────────────────────┐ -│ relicario-core │ +│ relicario-core │ │ Platform-agnostic: bytes in, bytes out │ │ No filesystem, no network, no git │ │ │ -│ ┌──────────┐ ┌──────────┐ ┌─────────┐ ┌────────────┐ │ -│ │ crypto │ │ imgsecret│ │ entry │ │ vault │ │ -│ │ │ │ │ │ │ │ │ │ -│ │ KDF │ │ DCT │ │ Entry │ │ encrypt_ │ │ -│ │ encrypt │ │ embed │ │ Manifest│ │ entry() │ │ -│ │ decrypt │ │ extract │ │ search │ │ decrypt_ │ │ -│ │ │ │ QIM │ │ │ │ manifest() │ │ -│ └──────────┘ └──────────┘ └─────────┘ └────────────┘ │ +│ ┌──────────┐ ┌──────────┐ ┌─────────┐ ┌────────────┐ │ +│ │ crypto │ │ imgsecret│ │ item + │ │ vault │ │ +│ │ │ │ │ │ types │ │ │ │ +│ │ KDF │ │ DCT │ │ Item │ │ encrypt_ │ │ +│ │ encrypt │ │ embed │ │ Manifest│ │ item() │ │ +│ │ decrypt │ │ extract │ │ Settings│ │ decrypt_ │ │ +│ │ │ │ QIM │ │ Backup │ │ manifest() │ │ +│ │ │ │ │ │ Device │ │ ... │ │ +│ └──────────┘ └──────────┘ └─────────┘ └────────────┘ │ │ │ -│ Future: relicario-wasm wraps this for browser extension │ -│ Future: JNI/Swift wrappers for Android/iOS │ +│ Consumed by: relicario-cli, relicario-wasm (extension), │ +│ relicario-server (pre-receive hook). │ +│ Future: JNI/Swift wrappers for Android/iOS. │ └────────────────────────────────────────────────────────────┘ ``` diff --git a/docs/architecture/overview.md b/docs/architecture/overview.md index 0662179..297cf47 100644 --- a/docs/architecture/overview.md +++ b/docs/architecture/overview.md @@ -177,8 +177,8 @@ Core tests use **fast Argon2id params** (m=256, t=1, p=1) so they don't take for |---|---|---| | Master key only in `Zeroizing<[u8;32]>` | core types; CLI follows; extension WASM follows | Drop-on-scope-exit zeroization; never leaves stack | | AEAD ciphertext starts with version byte | `core/crypto.rs` | Format identification; reject v1 blobs cleanly | -| Item IDs are random 8-char hex | `core/ids.rs` | Stable, short, no information leak | -| Attachment IDs are content-addressed (SHA-256) | `core/ids.rs` | Dedup; integrity check | +| Item IDs are random 16-char hex (64 bits) | `core/ids.rs` | Stable, short, no information leak | +| Attachment IDs are content-addressed (first 32 hex chars / 128 bits of SHA-256) | `core/ids.rs` | Dedup; integrity check | | KDF input is length-prefixed | `core/crypto.rs` | Prevents `passphrase || image_secret` collisions | | Git history is preserved as audit log; never squash | CLI commits; SW commits | Per-action history is a feature | | Per-action git commits with structured messages | `cli` (via `commit_paths`); SW (via vault.ts helpers) | Greppable, useful as audit log |