# encrypted_archive [Русская версия (README_ru.md)](README_ru.md) Custom encrypted archive format designed to be **unrecognizable** by standard analysis tools (`file`, `binwalk`, `strings`, hex editors). ## Features - **AES-256-CBC** encryption with per-file random IVs - **HMAC-SHA-256** authentication (IV || ciphertext) - **GZIP compression** with smart detection (skips already-compressed formats) - **XOR-obfuscated headers** — no recognizable magic bytes - **Encrypted file table** — metadata invisible in hex dumps - **Decoy padding** — random 64–4096 bytes between data blocks - **Three decoders**: Rust (native CLI), Kotlin (JVM/Android), Shell (POSIX) ## Quick Start ```bash # Build cargo build --release # Pack files into an archive ./target/release/encrypted_archive pack file1.txt photo.jpg -o archive.bin # Inspect metadata (without extracting) ./target/release/encrypted_archive inspect archive.bin # Extract files ./target/release/encrypted_archive unpack archive.bin -o ./output/ ``` ## CLI Reference ### `pack` — Create an encrypted archive ``` encrypted_archive pack ... -o [--no-compress ...] ``` | Argument | Description | |----------|-------------| | `...` | One or more files to archive | | `-o, --output` | Output archive path | | `--no-compress` | Skip compression for matching filenames (suffix or exact match) | Compression is automatic for most files. Already-compressed formats (`.zip`, `.gz`, `.jpg`, `.png`, `.mp3`, `.mp4`, `.apk`, etc.) are stored without recompression. ```bash # Pack with selective compression control encrypted_archive pack app.apk config.json -o bundle.bin --no-compress "app.apk" ``` ### `unpack` — Extract files ``` encrypted_archive unpack [-o ] ``` | Argument | Description | |----------|-------------| | `` | Archive file to extract | | `-o, --output-dir` | Output directory (default: `.`) | ### `inspect` — View metadata ``` encrypted_archive inspect ``` Displays header fields, file count, per-file sizes, compression status, and integrity hashes without extracting content. ## Decoders The archive can be decoded by three independent implementations. All produce **byte-identical output** from the same archive. ### Rust (native CLI) The primary implementation. Used via `unpack` subcommand (see above). ### Kotlin (JVM / Android) Single-file decoder for JVM environments. No external dependencies — uses `javax.crypto` and `java.util.zip` from the standard library. **Standalone usage:** ```bash # Compile kotlinc kotlin/ArchiveDecoder.kt -include-runtime -d ArchiveDecoder.jar # Decode java -jar ArchiveDecoder.jar archive.bin ./output/ ``` **As a library in an Android project:** Copy `kotlin/ArchiveDecoder.kt` into your project source tree. All crypto and compression APIs (`javax.crypto.Cipher`, `javax.crypto.Mac`, `java.util.zip.GZIPInputStream`) are available in the Android SDK. To use as a library, call the decoding logic directly instead of `main()`: ```kotlin // Example: decode from a file val archive = File("/path/to/archive.bin") val outputDir = File("/path/to/output") decode(archive, outputDir) // The decode() function handles: // 1. XOR header de-obfuscation // 2. TOC decryption // 3. Per-file AES decryption + HMAC verification // 4. GZIP decompression (if compressed) // 5. SHA-256 integrity check ``` No native `.so` required — pure Kotlin/JVM running on ART. ### Shell (POSIX) Emergency decoder for POSIX systems **with OpenSSL installed**. ```bash sh shell/decode.sh archive.bin ./output/ ``` **Requirements:** `dd`, `openssl`, `sha256sum`, `gunzip`, and either `xxd` or `od`. > **Note:** This decoder requires `openssl` for AES and HMAC operations. It will **not** work on minimal environments like BusyBox that lack OpenSSL. For constrained environments, use the Rust or Kotlin decoder instead. ## Format Specification Full binary format specification: **[docs/FORMAT.md](docs/FORMAT.md)** ### Archive Layout (summary) ``` ┌──────────────────────────┐ offset 0 │ Header (40 bytes, XOR) │ magic, version, flags, toc_offset, toc_size, toc_iv, file_count ├──────────────────────────┤ offset 40 │ TOC (encrypted AES-CBC) │ file entries: name, sizes, offsets, IV, HMAC, SHA-256 ├──────────────────────────┤ │ Data Block 0 │ AES-256-CBC(GZIP(plaintext)) │ Decoy Padding (random) │ 64–4096 random bytes ├──────────────────────────┤ │ Data Block 1 │ │ Decoy Padding (random) │ ├──────────────────────────┤ │ ... │ └──────────────────────────┘ ``` ### Flags Byte | Bit | Mask | Feature | |-----|------|---------| | 0 | `0x01` | At least one file is GZIP-compressed | | 1 | `0x02` | TOC is AES-256-CBC encrypted | | 2 | `0x04` | Header is XOR-obfuscated | | 3 | `0x08` | Decoy padding between data blocks | Standard archives with all features: flags = `0x0F`. ## Security Model **What this provides:** - Confidentiality — AES-256-CBC encryption per file - Integrity — HMAC-SHA-256 per file (encrypt-then-MAC) - Content verification — SHA-256 hash of original plaintext - Anti-analysis — no recognizable patterns for `file`, `binwalk`, `strings` **What this does NOT provide:** - Key management — v1 uses a hardcoded key (v2 will use HKDF-derived subkeys) - Forward secrecy - Protection against targeted cryptanalysis (the XOR key is fixed and public) The obfuscation layer is designed to resist **casual analysis**, not a determined adversary with knowledge of the format. ## Building from Source ```bash # Debug build cargo build # Release build (optimized) cargo build --release # Run all tests (unit + integration + golden vectors) cargo test ``` ### Running Cross-Validation Tests ```bash # Kotlin decoder tests (requires kotlinc + java) bash kotlin/test_decoder.sh # Shell decoder tests (requires openssl + sha256sum) bash shell/test_decoder.sh ``` ## Project Structure ``` encrypted_archive/ ├── src/ │ ├── main.rs # CLI entry point │ ├── cli.rs # Clap argument definitions │ ├── archive.rs # Pack / unpack / inspect │ ├── format.rs # Binary format serialization │ ├── crypto.rs # AES-256-CBC, HMAC-SHA-256, SHA-256 │ ├── compression.rs # GZIP + smart format detection │ └── key.rs # Cryptographic key ├── kotlin/ │ └── ArchiveDecoder.kt # JVM/Android decoder (single file) ├── shell/ │ └── decode.sh # POSIX shell decoder ├── docs/ │ └── FORMAT.md # Binary format specification (normative) └── tests/ └── golden_vectors.rs # Known-answer tests ``` ## License TBD