m_security 0.3.5
m_security: ^0.3.5 copied to clipboard
A native Rust cryptographic SDK for Flutter via FFI. AES-256-GCM, ChaCha20-Poly1305, BLAKE3, SHA-3, Argon2id, HKDF, streaming encryption, and encrypted virtual file system.
Changelog #
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
0.3.5 - 2026-04-10 #
Added #
- Per-segment metadata:
vault_write()andvault_write_stream()accept optionalHashMap<String, String>metadata, encrypted within the index block.vault_read()returnsSegmentReadResult { data, metadata }. - Segment rename:
vault_rename_segment(old_name, new_name)updates the index without re-encryption. WAL-protected for crash safety.DuplicateSegmenterror variant added. - Index caching: in-memory dirty flag tracks index mutations. Read-only operations skip redundant index encryption/flush. New
vault_flush()API for explicit durability control. - Parallel reads:
vault_read_parallel(handle, names)decrypts multiple segments concurrently viarayon+ mmap zero-copy. Returns per-segmentSegmentResult { name, data, error }. - Dart
VaultServicewrappers:renameSegment(),flush(),readParallel(). Updatedwrite()/writeStream()to accept optionalmetadataparameter. Updatedread()to returnSegmentReadResult. - 15 Dart integration tests covering metadata (4), rename (4), flush (2), parallel read (3), and combined workflows (2).
- Rust test suite refactored from monolithic
tests.rsinto 13 focused modules. 407 total Rust tests. - Example app: metadata input field, rename dialog, flush button, parallel read all button.
Changed #
VAULT_VERSIONbumped 1 → 2 for backward-compatible metadata deserialization (v1 vaults return empty metadata).ARCHIVE_VERSIONbumped 1 → 2 for metadata preservation in export/import (v1 archives import with empty metadata).vault_write_filenow passes metadata through tovault_write_stream(was hardcoded toNone).vault_close()flushes dirty index before releasing lock, with best-effort WAL checkpoint on error.
Security #
- Metadata encrypted within the index block (AEAD with index key), not in the segment cipher — no plaintext leakage.
- OOM guards:
MAX_METADATA_PAIRS(1024) andMAX_METADATA_BYTES(64 KB) enforced on both read and write paths. - Parallel reads use immutable
&VaultHandle— no shared mutable state between threads. Compile-timeSyncassertion. - Checked offset arithmetic in parallel mmap slicing (
checked_addinstead of bare+). - Plaintext zeroized on all checksum failure paths in parallel reads.
Fixed #
- Async error assertions in Dart rename tests changed from
expect()toawait expectLater(). - Example app
evfs_test.dartupdated forSegmentReadResultreturn type.
0.3.4 - 2026-04-05 #
Added #
- Master key rotation via
vault_rotate_key()— re-encrypts all vault data under a new key using atomic copy-to-new-vault + rename strategy. Crash recovery: stale.rotatingfile cleaned onvault_open(). - Vault export via
vault_export()— produces a self-contained.mvexencrypted archive with BLAKE3 integrity trailer, ephemeral export key AEAD-wrapped with caller's wrapping key, and per-segment re-encryption. - Vault import via
vault_import()— reads.mvexarchive, creates new vault re-encrypted under a local master key. Validates header, unwraps export key, verifies per-segment BLAKE3 checksums and trailer integrity. ImportFailed,ExportFailed, andKeyRotationFailederror variants inCryptoError.- Dart
VaultService.rotateKey(),VaultService.export(), andVaultService.importVault()static methods. - 7 Dart integration tests for key management (rotation roundtrip, old key rejection, export-import roundtrip, wrong wrapping key, 1MB+ segment, multiple rotations, rotate-then-export-import).
- 26 Rust tests for key management (10 rotation + 7 export + 9 import).
- Example app Key Management section with Rotate Key, Export, and Import buttons.
- CI workflow pinned
flutter_rust_bridge_codegento v2.11.1 to match runtime dependency.
Security #
- Old sub-keys zeroized immediately after rotation via
ZeroizeOnDrop. - Export wrapping uses AAD
b"msec-export-key-wrap"for domain separation. - Archive format authenticated: per-segment AAD (segment name) + BLAKE3 trailer covering all preceding bytes.
vault_writeplaintext wrapped inZeroizing<Vec<u8>>— guarantees zeroization on all exit paths includingencrypt_segmentfailure.- Import hardened:
u64tousizesafe cast viatry_from(32-bit overflow protection), OOM guard inu64arithmetic withsaturating_add,.lockfile cleanup in error paths, segment name validation (1-255 bytes),segment_countsanity bound (100K), unknown compression byte rejection. - Atomic rename before lock release in rotation (closes race window).
Fixed #
unwrap()inarchive.rsreplaced withmap_err()for clippy compliance.from_byteserrors remapped toImportFailedat import call sites.- Example app lint: replaced
src/imports with publicm_security.dartre-exports.
0.3.3 - 2026-03-28 #
Added #
- Zero-copy vault reads via
memmap2memory-mapped I/O —vault_readandvault_read_streamnow slice directly into mapped file pages instead of allocating heap buffers withread_exact. VaultMmapwrapper withmlock()on unix to pin ciphertext pages in RAM and prevent swap-to-disk. Graceful fallback to heap reads when mmap fails (32-bit targets, lowmlocklimits).- mmap invalidation/recreation after every vault mutation (write, delete, defrag, resize).
- ELF linker version script (
ffi-exports.map) restricting Android/Linux.sodynamic symbol table to FRB FFI symbols only — hides#[no_mangle]symbols leaked by dependencies. build.rsfor conditional version script application on Android/Linux cdylib builds.
Changed #
- Switched all 50 FRB functions from SSE to CST+DCO codec via
full_dep: true—Vec<u8>returns now useallo-isolateExternalTypedData(pointer transfer, no memcpy) instead of SSE serialization. - Release profile hardened:
lto = "fat",codegen-units = 1,strip = "symbols",opt-level = 3. VaultHandlefield order:mmapbeforefilesomunlock/munmapruns while the fd is still open.
Security #
- Symbol stripping removes internal Rust function names from release binaries —
nm -Dshows only FRB entry points and libc on ELF targets. mlock()prevents OS from swapping mmap'd ciphertext pages to disk swap.- Fewer intermediate
Vec<u8>copies means shorter plaintext residency in memory. - ZeroizeOnDrop behavior preserved — no regression from zero-copy refactoring.
0.3.2 - 2026-03-26 #
Added #
vault_write_stream()for constant-memory chunked segment writes — encrypts data in 64 KB chunks without loading the full segment into RAM.vault_read_stream()for chunked segment reads viaStreamSink— delivers decrypted data as a stream of byte chunks.- Per-chunk AEAD encryption with domain-separated nonce derivation (
0x01prefix, chunk index, generation) — provably disjoint from monolithic nonce space. VaultChunkAadstruct binding generation and chunk position to each chunk's authentication tag (cross-segment splice defense).vault_write_file()FRB-callable wrapper that reads a file in 64 KB chunks and pipes intovault_write_stream.- Dart
VaultService.writeStream()— accepts aStream<Uint8List>, buffers to a temp file, and delegates to Rust for bounded-memory encryption. - Dart
VaultService.readStream()— returns aStream<Uint8List>of decrypted chunks with optionalonProgresscallback. - Streaming interop: segments written via streaming can be read one-shot (and vice versa).
- Integration tests for streaming: 10 MB roundtrip, write/read interop, progress reporting, error handling, and 50 MB memory-bounded validation.
- Example app streaming I/O section in the Vault tab — stream-write and stream-read with configurable size and live progress bar.
Fixed #
- Checked arithmetic in
decrypt_streaming_chunksread path — prevents wrong-region reads from crafted chunk counts. - I/O errors in
vault_write_filenow surface asCryptoError::IoErrorinstead of a misleading "stream underflow" message. total_receivedaccumulation useschecked_addto prevent silent overflow on pathological input.- Per-chunk
fsyncreplaced with a single post-loop durability barrier — reduces streaming write I/O from O(N) fsyncs to O(1). - WAL checkpoint after streaming write commit — prevents unbounded WAL growth.
readStreamcancellation leak —onCancelhandler now cleans up data and progress subscriptions.- Overflow error message now reports exact byte count, chunk size, and offset for easier debugging.
0.3.1 - 2026-03-16 #
Added #
- Vault defragmentation:
vault_defragment()compacts segments toward data region start, coalescing all free space with per-move WAL protection and post-commit secure erase. - Vault resize:
vault_resize()grows or shrinks vault capacity, relocating shadow index and WAL region. - Vault health check:
vault_health()returnsVaultHealthInfowith fragmentation %, free region count, largest contiguous block, and consistency invariant. - Dynamic index sizing:
compute_index_size(capacity)scales segment index proportionally (64 KB per MB, min 64 KB, max 16 MB cap) — replaces fixed 64 KBINDEX_PAD_SIZE. - Dart
VaultService.defragment(),VaultService.resize(), andVaultService.health()wrappers with integration tests. - Example app vault maintenance UI (defrag, resize, health).
Fixed #
- Nonce reuse prevention after WAL recovery by hardening defrag backup path.
- Resize and defrag crash recovery hardening (fsync ordering, OOM guard, bounds check, health invariant overflow-safe check).
- Segment index size now scales with vault capacity — fixes OOM on large vaults with fixed 64 KB index.
- pub.dev score improvements.
Security #
- No new information leaks,
index_sizeremains deterministic from file size. - Enforced index size bounds (64KB-16MB).
- Added safeguards against excessive memory usage.
- Header tampering results in authentication failure (no data exposure).
0.3.0 - 2026-03-07 #
Added #
- Streaming encryption and decryption with chunk-based AES-256-GCM and ChaCha20-Poly1305, including progress callbacks for large file processing.
- Zstd and Brotli compression with configurable levels, integrated into both the streaming pipeline and the EVFS.
- Encrypted Virtual File System (EVFS): a
.vaultcontainer supporting named segments, WAL crash recovery, shadow index, capacity management, and secure deletion. - Full-featured Flutter example app demonstrating all library APIs (hashing, encryption, KDF, streaming, compression, vault).
Fixed #
- Integration test reliability improvements for async race conditions and matcher corrections.
0.1.1 - 2026-03-06 #
Fixed #
- Published package was missing
rust/src/frb_generated.rs, which caused Rust compilation to fail for consumers.
0.1.0 - 2026-03-06 #
Initial release of M-Security, a native Rust cryptographic SDK for Flutter.
Added #
- AES-256-GCM authenticated encryption with 32-byte keys, 12-byte auto-generated nonces, and 16-byte authentication tags.
- ChaCha20-Poly1305 authenticated encryption optimized for mobile processors lacking dedicated AES hardware.
- Unified
CipherHandleinterface for both ciphers (create, encrypt, decrypt, generate key). Output format:nonce || ciphertext || tag. - BLAKE3 hashing with one-shot and streaming APIs via
HasherHandle. - SHA-3-256 (Keccak) hashing with one-shot and streaming APIs.
- Argon2id password hashing with Mobile (64 MiB, t=3, p=4) and Desktop (256 MiB, t=4, p=8) presets, automatic salt generation, and PHC string output.
- HKDF-SHA256 key derivation (RFC 5869) with
derive,extract, andexpandoperations. Output range: 1-8160 bytes. - Secure memory management with
ZeroizeOnDropon all key-holding structs. - Opaque
#[frb(opaque)]handles ensuring raw keys never cross the FFI boundary. - Internal nonce generation via
OsRng; callers never handle nonces. - CI pipeline with Rust linting/testing, Dart analysis, and platform builds (Android, iOS, Linux).
- Integration tests for all cryptographic operations.
- Platform support: Android (ARM64, ARM32), iOS (ARM64, Simulator), macOS (ARM64, Intel), Linux (x86_64), Windows (x86_64).