# 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 <FILES>... -o <OUTPUT> [--no-compress <PATTERNS>...]
```

| Argument | Description |
|----------|-------------|
| `<FILES>...` | 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 <ARCHIVE> [-o <DIR>]
```

| Argument | Description |
|----------|-------------|
| `<ARCHIVE>` | Archive file to extract |
| `-o, --output-dir` | Output directory (default: `.`) |

### `inspect` — View metadata

```
encrypted_archive inspect <ARCHIVE>
```

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
