Files
android-encrypted-archiver/README.md
2026-02-25 02:50:47 +03:00

7.0 KiB
Raw Permalink Blame History

encrypted_archive

Русская версия (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 644096 bytes between data blocks
  • Three decoders: Rust (native CLI), Kotlin (JVM/Android), Shell (POSIX)

Quick Start

# 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.

# 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:

# 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():

// 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.

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

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)  │  644096 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

# Debug build
cargo build

# Release build (optimized)
cargo build --release

# Run all tests (unit + integration + golden vectors)
cargo test

Running Cross-Validation Tests

# 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