- 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>
- Checks prerequisites (kotlinc, java, cargo) with install instructions
- Test 1: single text file round-trip (Rust pack -> Kotlin decode)
- Test 2: multiple files with mixed content (text + 10KB binary)
- Test 3: no-compress mode for pre-compressed files
- Test 4: empty file edge case
- Test 5: large file (100 KB random data)
- SHA-256 comparison of original vs extracted for each test
- Colored output, temp directory cleanup via trap, non-zero exit on failure
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 7 deterministic tests: AES-256-CBC encrypt/decrypt, empty, HMAC-SHA256, HMAC verify, SHA-256 x2
- Fixed IV vectors for reproducible results (no randomness)
- HMAC golden value cross-verified with openssl (file input) and Python hmac module
- SHA-256 values match FORMAT.md Section 12.3 known vectors
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- SUMMARY.md with 19 unit tests across crypto/compression/format modules
- STATE.md updated to Phase 3 Plan 1/2, 43% progress
- ROADMAP.md marks 03-01-PLAN.md complete
- REQUIREMENTS.md marks TST-03 complete
- Create src/lib.rs re-exporting all modules as public
- Update main.rs to use encrypted_archive:: imports instead of local mod declarations
- Add dev-dependencies: tempfile, assert_cmd, hex-literal, predicates
- Worked example: 2-file archive (hello.txt + data.bin) with 323 bytes total
- Real SHA-256 hashes computed for both files
- Full annotated hex dump with byte-by-byte field annotations
- Step-by-step shell decode walkthrough with dd/xxd commands
- Shell reference functions: read_le_u16, read_le_u32, verify_hmac, decrypt_file
- Kotlin reference: decrypt, HMAC verify, gzip decompress, SHA-256 verify
- Busybox compatibility notes with od fallback for xxd
- All offsets verified internally consistent via automated check
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Archive header definition (40 bytes) with complete field table
- File table entry definition (11 fields, variable-length per entry)
- AES-256-CBC + HMAC-SHA-256 encryption pipeline with encrypt-then-MAC
- PKCS7 padding formula with 8 worked examples
- Gzip compression details with per-file flag
- Obfuscation features: XOR header, encrypted TOC, decoy padding
- Decode order of operations (full step-by-step)
- Version compatibility rules
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>