Skip to content

feat(evfs): add per-segment encryption, checksums, and secure deletion#63

Closed
Adel-Ayoub wants to merge 51 commits into
mainfrom
adelayoub/evfs-segment-encryption
Closed

feat(evfs): add per-segment encryption, checksums, and secure deletion#63
Adel-Ayoub wants to merge 51 commits into
mainfrom
adelayoub/evfs-segment-encryption

Conversation

@Adel-Ayoub

Copy link
Copy Markdown
Collaborator

Summary

  • Add HKDF-SHA256 domain-separated sub-key derivation (cipher_key, nonce_key, index_key) from a single master key
  • Implement compress-then-encrypt / decrypt-then-decompress pipeline with MIME-aware compression skip
  • Generation-aware nonce derivation for both segments and index, preventing nonce reuse on overwrite
  • BLAKE3 integrity checksums on original plaintext (pre-compression) with constant-time verification (subtle)
  • CSPRNG pre-allocation in 64KB chunks for traffic analysis resistance
  • Secure deletion: overwrite regions with CSPRNG random bytes + fsync

Security hardening

  • Empty master key rejected with InvalidKeyLength
  • Index nonce includes generation counter (prevents catastrophic nonce reuse across saves)
  • Intermediate compressed buffers zeroized before returning
  • Constant-time nonce comparison on decrypt (timing side-channel protection)
  • Minimum ciphertext length validation before parsing

Files changed

File Change
rust/Cargo.toml Add subtle = "2.6" for constant-time comparison
rust/src/api/evfs/segment.rs New — full implementation (873 lines, 26 tests)

Test plan

  • cargo test evfs::segment --features compression — 26/26 passing
  • cargo test --features compression — full suite passing
  • cargo clippy --features compression — zero warnings

Adel-Ayoub and others added 30 commits February 26, 2026 13:46
…6B): magic/version/algorithm/reserved

  - ChunkAad (9B): index(u64 LE) + is_final(u8) for truncation protection                                          - ChunkReader: fill-in-place zero-alloc read_chunk(&mut chunk)
  - ChunkWriter: internal buffer for single-syscall writes
  - Last-chunk padding with zero-byte validation
  - EncryptedChunk pre-allocation + Default
  - StreamAlgorithm <-> Algorithm conversion bridge
  - Generic finish() + finish_file() for fsync
  - 22 unit tests covering all acceptance criteria
feat(streaming): add low-level streaming primitives                  …
  - encrypt_file_impl / decrypt_file_impl: 64KB AEAD chunk streaming
  - Per-chunk AAD (index + is_final) prevents reorder/truncation/append
  - Last-chunk padding to uniform ENCRYPTED_CHUNK_SIZE
  - Atomic temp-file-then-rename: failed ops leave no partial output
  - Algorithm cross-check between header and CipherHandle
  - Progress callbacks (0.0..1.0) via closure, FRB StreamSink wrappers
  - CipherHandle: add pub(crate) encrypt_raw/decrypt_raw/algorithm_id
  - 16 tests: roundtrip, tamper detection, progress, cleanup guarantees
  - Remove needless borrows in fs::write test calls
  - Replace unwrap_err() with expect_err() to satisfy deny(clippy::unwrap_used)
…pt-decrypt

feat(streaming): add high-level streaming encrypt/decrypt API
…noop.dart referenced core/traits.dart which is not generated (#[frb(ignore)] on Encryption trait).NoopEncryption itself does not need FRB scanning only create_noop_encryption() returning CipherHandle is the public API.
  - hash_file_impl reads file in 64KB chunks, feeds raw bytes to hasher
  - No encryption padding digest matches one-shot blake3_hash/sha3_hash
  - stream_hash_file FRB wrapper with StreamSink<f64> progress
  - pub(crate) update_raw/finalize_raw/reset_raw on HasherHandle
  - New tests: BLAKE3, SHA-3, empty file, 1MB+ file, exact boundary
…noop.dart referenced core/traits.dart which is not generated (#[frb(ignore)] on Encryption trait).NoopEncryption itself does not need FRB scanning only create_noop_encryption() returning CipherHandle is the public API.
feat(streaming): add streaming file hash with BLAKE3/SHA-3
…ity FRB drops the Vec<u8> return when a function also has StreamSink. Stream_hash_file now only feeds data Dart calls hasherFinalize() to obtain the digest.
- Add StreamingService with encryptFile, decryptFile, hashFile
- Add 8 integration tests (6/8 pass)
- Export StreamingService from lib/m_security.dart
… unawaited(executeNormal) for stream functions, so Rust errors arrive as zone errors after the progress stream closes. _guardedStream uses runZonedGuarded + deferred close to forward these to the stream.

  All 8 integration tests pass on macOS, Android, and iOS.
feat(streaming): add Dart StreamingService wrapper and integration tests
Add streaming encrypt decrypt and hash pipeline
feat(compression): add Zstd/Brotli core with algorithm enum and MIME-aware skip
  Rewrites the compress-encrypt pipeline to feed input through a streaming
  compressor and chunk the compressed output, instead of compressing each
  64KB chunk independently. A file that compresses 50% now produces half
  as many encrypted chunks on disk.
Adel-Ayoub and others added 21 commits March 2, 2026 17:23
…ssion

feat(dart): Compression service wrapper + integration tests
Compression pipeline (Zstd, Brotli, MIME-aware skip)
  VaultFull, VaultLocked, SegmentNotFound, VaultCorrupted.
  Module root with format, segment, and wal submodules.
  VaultHeader (32B), SegmentEntry with generation counters and
  per-segment compression, SegmentIndex with best-fit allocator,
  free-region merging, padded serialization (64KB), layout constants,
  and 27 unit tests.
feat(evfs): vault format structures and segment index
  HKDF domain-separated sub-keys (cipher/nonce/index), generation-aware
  nonce derivation, compress-then-encrypt pipeline with MIME-aware skip,
  BLAKE3 checksums with constant-time verification (subtle), CSPRNG
  pre-allocation in 64KB chunks, secure erase with fsync. 23 tests.
  HKDF domain-separated sub-keys (cipher/nonce/index), generation-aware
  nonce derivation for both segments and index, compress-then-encrypt
  pipeline with MIME-aware skip, BLAKE3 checksums with constant-time
  verification (subtle), CSPRNG pre-allocation in 64KB chunks, secure
  erase with fsync, intermediate buffer zeroization. 26 tests.
@Adel-Ayoub Adel-Ayoub linked an issue Mar 5, 2026 that may be closed by this pull request
@Adel-Ayoub Adel-Ayoub closed this Mar 5, 2026
@Adel-Ayoub Adel-Ayoub deleted the adelayoub/evfs-segment-encryption branch March 5, 2026 10:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[EVFS] Per-segment encryption, integrity, and secure deletion

4 participants