-
Notifications
You must be signed in to change notification settings - Fork 0
docs: align README Security section with AES-256-GCM-SIV/BE32 #27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -103,7 +103,7 @@ Streaming: | |
|
|
||
| - **Magic**: Literal `b"VAULTX03"` — identifies the streaming format version | ||
| - **Salt**: 128-bit fresh `OsRng`-generated per file | ||
| - **Nonce**: 56-bit fresh `OsRng`-generated per file; `EncryptorBE32` appends an internal 5-byte counter/flag (12 bytes total internally) | ||
| - **Nonce**: 56-bit (7 bytes) fresh `OsRng`-generated per file; `EncryptorBE32` expands this to a 12-byte nonce internally by appending a 5-byte counter + 1-byte flag | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔥 The Roast: Quick math check: 7 bytes + 5 bytes + 1 byte = 13 bytes, not 12. Your calculator needs recalibration. The BE32 construction splits the 12-byte nonce as 7-byte stream_nonce + 4-byte counter + 1-byte flag, not 5-byte counter. 🩹 The Fix: Change '5-byte counter + 1-byte flag' to '4-byte counter + 1-byte flag' to accurately reflect the BE32 nonce expansion. 📏 Severity: suggestion Reply with |
||
| - **Body**: Sequence of AES-256-GCM-SIV encrypted chunks. Intermediate chunks via `encrypt_next`, final chunk via `encrypt_last` to prevent truncation attacks. | ||
|
|
||
| ### Legacy VAULTX02 Format | ||
|
|
@@ -562,23 +562,34 @@ For full setup, JNI architecture details, and building instructions, see the [An | |
|
|
||
| | Layer | Algorithm | Parameters | | ||
| |-------|-----------|------------| | ||
| | Encryption (V3) | XChaCha20-Poly1305 (streaming AEAD) | 192-bit nonce, 128-bit tag, 1 MB chunks | | ||
| | Encryption (V2 legacy) | AES-256-GCM-SIV | 96-bit nonce, 128-bit tag | | ||
| | Key Derivation | Argon2id | m=65536 (64 MB), t=3 iterations, p=1 lane | | ||
| | Encryption (V3) | AES-256-GCM-SIV (BE32 streaming) | 56-bit stream nonce per file, 128-bit auth tag per 1 MB chunk | | ||
| | Encryption (V2 legacy) | AES-256-GCM-SIV | 96-bit nonce, 128-bit auth tag | | ||
| | Key Derivation | Argon2id | m=65536 (64 MB), t=3 iterations, p=4 lanes | | ||
| | Key Expansion | HKDF-SHA512 | Two separate 256-bit subkeys: enc + nonce | | ||
| | Integrity | Poly1305 / GHASH | Per-chunk authentication; any bit-flip fails | | ||
| | Integrity | GHASH (GCM-SIV) | Per-chunk authentication; any bit-flip fails | | ||
| | RNG | OS CSPRNG (`OsRng`) | `getrandom` crate; no `rand` global state | | ||
| | Memory Hygiene | `Zeroizing<T>` | Key material zeroed from RAM on drop | | ||
|
|
||
| ### Key Derivation Details | ||
|
|
||
| ``` | ||
| passphrase + 32-byte OsRng salt | ||
| │ | ||
| Argon2id (64 MB, 3 passes) | ||
| │ | ||
| 64-byte master key | ||
| ├─ HKDF-Extract+Expand → 32-byte encryption key | ||
| └─ HKDF-Extract+Expand → 32-byte nonce seed | ||
| V3 (VAULTX03 streaming): | ||
| passphrase + 16-byte OsRng salt | ||
| │ | ||
| Argon2id (64 MB, 3 passes, 4 lanes) | ||
| │ | ||
| 64-byte master key | ||
| ├─ HKDF-Extract+Expand → 32-byte encryption key | ||
| └─ HKDF-Extract+Expand → 32-byte nonce seed | ||
|
|
||
| V2 (VAULTX02 legacy): | ||
| passphrase + 32-byte OsRng salt | ||
| │ | ||
| Argon2id (64 MB, 3 passes, 4 lanes) | ||
| │ | ||
| 64-byte master key | ||
| ├─ HKDF-Extract+Expand → 32-byte encryption key | ||
| └─ HKDF-Extract+Expand → 32-byte nonce seed | ||
| ``` | ||
|
|
||
| The salt is stored in plaintext in the file header. The master key and all intermediate key material are stored in `Zeroizing<Vec<u8>>` which zeroes memory on drop. | ||
|
|
@@ -587,8 +598,8 @@ The salt is stored in plaintext in the file header. The master key and all inter | |
|
|
||
| **Protected against:** | ||
| - Offline brute-force: Argon2id with 64 MB memory cost makes GPU attacks expensive. | ||
| - Ciphertext tampering: Every 1 MB chunk has an independent Poly1305 authentication tag. Corruption of any byte fails decryption of that chunk. | ||
| - Nonce reuse: Each encryption generates a fresh 24-byte random nonce via `OsRng`. With 192-bit nonces, collision probability is negligible even at billions of files. | ||
| - Ciphertext tampering: Every 1 MB chunk has an independent GCM-SIV authentication tag (GHASH). Corruption of any byte fails decryption of that chunk. | ||
| - Nonce reuse: Each encryption generates a fresh 7-byte (56-bit) random nonce via `OsRng`. `EncryptorBE32` expands it to 12 bytes internally with a per-chunk counter. Fresh nonce per file makes collision probability negligible. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
For high-volume or automated use, this new 56-bit nonce statement overstates the collision margin: with only 7 random bytes and no uniqueness tracking in Useful? React with 👍 / 👎. |
||
| - Sensitive data in memory: Plaintext buffers and keys are wrapped in `Zeroizing<>`, zeroed on drop. Passwords are cleared from UI state immediately after the crypto thread starts. | ||
|
|
||
| **Not protected against:** | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For anyone implementing or verifying VAULTX03 from the README, this describes a 7-byte prefix plus a 5-byte counter plus a 1-byte flag, which totals 13 bytes even though the expanded AEAD nonce is 12 bytes. The implementation documents the internal suffix as 5 bytes total (
4-byte counter + 1-byte flag) inneuron-encrypt/src/crypto.rs:53-54, so this should say4-byte counter + 1-byte flagor5-byte counter/flagto avoid misdocumenting the file format.Useful? React with 👍 / 👎.