- Add hex dependency for --key hex decoding
- Add KeyArgs (--key, --key-file, --password) as clap arg group on top-level CLI
- Replace hardcoded KEY constant with resolve_key() supporting hex and file sources
- Refactor pack/unpack to require key parameter, inspect accepts optional key
- Wire CLI key resolution to archive functions in main.rs
- Inspect works without key (header only) or with key (full TOC listing)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pack changes:
- Split into path-collection (sequential) + crypto-processing (parallel)
- Introduce CollectedEntry enum to separate directory walk from file processing
- process_file() now creates thread-local RNG instead of taking &mut Rng
- File entries processed via rayon into_par_iter(), preserving deterministic order
Unpack changes:
- Phase 1: Sequential read of all ciphertexts from archive (single file handle)
- Phase 2: Create all directories sequentially (parent-before-child ordering)
- Phase 3: Parallel verify/decrypt/decompress/write via rayon par_iter
- Phase 4: Sequential result reporting for deterministic output
- Collect results into Vec<UnpackResult> to avoid interleaved stdout/stderr
- Test 6: nested directory extraction (3+ levels deep, 4 files)
- Test 7: empty directory creation without decryption errors
- Test 8: mixed standalone files + directory pack/unpack
- All 5 original test cases preserved unchanged
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add entryType and permissions fields to TocEntry data class
- Parse entry_type (1 byte) and permissions (2 bytes LE) in parseTocEntry
- Update version check from 1 to 2 for v1.1 format
- Handle directory entries: create dirs without decryption
- Create parent directories for files with relative paths
- Add applyPermissions() using Java File API (owner vs everyone)
- Update entry size formula comment to 104 + name_length
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- test_roundtrip_directory: full directory tree with permissions verification
- test_roundtrip_mixed_files_and_dirs: mixed file + directory pack/unpack
- test_inspect_shows_directory_info: inspect output contains dir/file types and permissions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Bump VERSION constant from 1 to 2
- Add entry_type (u8) and permissions (u16) fields to TocEntry struct
- Update write_toc_entry/read_toc_entry for new field order after name
- Update entry_size formula from 101 to 104 + name_length
- Update all unit tests for v1.1 layout (new fields, version 2, sizes)
- Add placeholder entry_type/permissions to archive.rs ProcessedFile for compilation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add XOR_KEY_HEX constant and hex_to_bin() helper (xxd + od fallback)
- Replace magic check with XOR bootstrapping: read 40 bytes, XOR if mismatch
- Write de-XORed header to temp file for field parsing
- Add TOC decryption via openssl enc when flags bit 1 is set
- Switch TOC parsing loop from $ARCHIVE to $TOC_FILE variable
- Update HMAC verification to construct IV from parsed hex (not archive position)
- All 7 cross-validation tests pass (Rust pack -> Shell decode -> SHA-256 match)
- Add XOR_KEY constant matching FORMAT.md Section 9.1
- Add xorHeader() function with signed byte masking (and 0xFF)
- Update decode() with XOR bootstrapping: check magic, XOR if mismatch
- Update decode() with TOC decryption: decrypt when flags bit 1 is set
- Backward compatible: plain headers and unencrypted TOC still work
- pack(): generate decoy padding (64-4096 random bytes per file)
- pack(): encrypt serialized TOC with AES-256-CBC using random toc_iv
- pack(): XOR header buffer before writing (8-byte cyclic key)
- pack(): set flags bits 1-3 (0x0E) for all obfuscation features
- unpack(): XOR bootstrapping via read_header_auto()
- unpack(): decrypt TOC when flags bit 1 is set
- inspect(): full de-obfuscation via shared read_archive_metadata()
- Factor out read_archive_metadata() helper for unpack/inspect reuse
- All existing tests pass (unit, golden, round-trip integration)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 6 test cases: single text, multiple files, no-compress, empty, large file, Cyrillic filename
- Uses Rust archiver to create archives, sh decode.sh to extract, SHA-256 to verify
- Follows same pattern as kotlin/test_decoder.sh
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>