Technology Stack
Project: encrypted_archive (Custom Encrypted Archiver)
Researched: 2026-02-24
Overall confidence: MEDIUM (versions from training data — verify before use)
Critical Constraint: Three-Platform Compatibility
Every technology choice is constrained by the weakest link: busybox shell. The Rust archiver can use any library, but the format it produces must be decodable by:
- Kotlin on Android 13 (javax.crypto / java.security)
- busybox shell (openssl, dd, xxd)
This constraint eliminates many otherwise-superior choices.
Recommended Stack
Encryption
| Technology |
Version |
Purpose |
Why |
Confidence |
aes crate |
^0.8 |
AES-256-CBC block cipher |
busybox openssl supports aes-256-cbc — the critical three-way constraint. Android javax.crypto supports AES natively. |
HIGH |
cbc crate |
^0.1 |
CBC mode of operation |
Standard mode: openssl CLI aes-256-cbc, javax.crypto AES/CBC/PKCS5Padding |
HIGH |
hmac + sha2 |
^0.12 / ^0.10 |
HMAC-SHA256 integrity |
Encrypt-then-MAC. busybox openssl dgst -sha256 -hmac. Kotlin Mac("HmacSHA256") |
HIGH |
Why AES-256-CBC over AES-GCM: busybox openssl does NOT support AEAD modes (GCM/CCM) in openssl enc. AES-CBC + HMAC-SHA256 (encrypt-then-MAC) provides equivalent security. CBC is the only AES mode reliably available across all three platforms.
Why NOT ChaCha20-Poly1305: busybox openssl does not support ChaCha20. Android javax.crypto has no standard ChaCha20 support. Would require native libraries, violating constraints.
Why NOT aes-gcm crate: Not decodable via openssl enc in busybox.
Compression
| Technology |
Version |
Purpose |
Why |
Confidence |
flate2 crate |
^1.0 |
gzip compression |
busybox gunzip works natively. Android GZIPInputStream works natively. Simplest cross-platform path. |
HIGH |
Why gzip-wrapped DEFLATE: busybox gunzip handles it. Android GZIPInputStream handles it. flate2 GzEncoder/GzDecoder produces standard gzip.
Why NOT zstd/lz4/brotli: busybox has no decompressors for any of these.
CLI Framework
| Technology |
Version |
Purpose |
Why |
Confidence |
clap |
^4 |
CLI argument parsing |
De facto Rust standard. Derive macros. Subcommands (pack/unpack/inspect). |
HIGH |
Binary Format
| Technology |
Version |
Purpose |
Why |
Confidence |
| Manual byte-level I/O |
N/A |
Custom binary format |
Using bincode/serde would make format recognizable by forensic tools. Manual bytes give full control for obfuscation. |
HIGH |
Hashing / Integrity
| Technology |
Version |
Purpose |
Why |
Confidence |
sha2 crate |
^0.10 |
SHA-256 checksums |
busybox sha256sum, Android MessageDigest("SHA-256") |
HIGH |
Random / IV Generation
| Technology |
Version |
Purpose |
Why |
Confidence |
rand |
^0.8 |
Random IV generation |
CSPRNG for AES-CBC initialization vectors. Each archive gets unique IV. |
HIGH |
Error Handling
| Technology |
Version |
Purpose |
Why |
Confidence |
anyhow |
^1 |
Application errors |
CLI app, not library. Ergonomic error chains. |
HIGH |
thiserror |
^2 |
Typed format errors |
Specific errors for format validation, decryption, integrity. |
MEDIUM |
Testing
| Technology |
Version |
Purpose |
Why |
Confidence |
Built-in #[test] |
N/A |
Unit tests |
Round-trip pack/unpack/compare |
HIGH |
assert_cmd |
^2 |
CLI integration tests |
Test actual binary |
MEDIUM |
tempfile |
^3 |
Temp dirs |
Clean test isolation |
HIGH |
Kotlin/Android Decompressor Stack (Zero External Dependencies)
| Technology |
Source |
Purpose |
javax.crypto.Cipher |
Android SDK |
AES-256-CBC: Cipher.getInstance("AES/CBC/PKCS5Padding") |
javax.crypto.spec.SecretKeySpec |
Android SDK |
32-byte hardcoded key |
javax.crypto.spec.IvParameterSpec |
Android SDK |
IV from archive header |
javax.crypto.Mac |
Android SDK |
HMAC-SHA256: Mac.getInstance("HmacSHA256") |
java.util.zip.GZIPInputStream |
Android SDK |
Gzip decompression |
java.security.MessageDigest |
Android SDK |
SHA-256 integrity |
java.nio.ByteBuffer |
Android SDK |
Little-endian parsing |
Busybox Shell Decompressor Stack
| Tool |
Purpose |
Key Flags |
dd |
Extract byte ranges |
bs=1 skip=N count=M |
xxd |
Hex encode/decode keys |
xxd -p |
openssl enc |
AES-256-CBC decrypt |
-d -aes-256-cbc -K HEX -iv HEX -nosalt |
openssl dgst |
HMAC-SHA256 verify |
-sha256 -hmac KEY -binary |
gunzip |
Gzip decompress |
Standard input/output |
sha256sum |
Integrity check |
-c checksums |
Critical: busybox openssl enc uses EVP_BytesToKey by default. MUST pass -K (hex key) + -iv (hex IV) + -nosalt for raw key mode. IV must be in cleartext header.
Cross-Platform Compatibility Matrix
| Rust |
Android SDK |
busybox |
Notes |
aes+cbc (PKCS7) |
Cipher("AES/CBC/PKCS5Padding") |
openssl enc -aes-256-cbc |
PKCS5=PKCS7 for 16-byte blocks |
hmac+sha2 |
Mac("HmacSHA256") |
openssl dgst -sha256 -hmac |
Raw key, not password |
flate2 (GzEncoder) |
GZIPInputStream |
gunzip |
Standard gzip |
sha2 |
MessageDigest("SHA-256") |
sha256sum |
Hex comparison |
Alternatives Considered
| Category |
Recommended |
Alternative |
Why Not |
| Encryption |
AES-256-CBC + HMAC |
AES-256-GCM |
busybox openssl lacks GCM |
| Encryption |
AES-256-CBC + HMAC |
ChaCha20-Poly1305 |
Not in busybox/Android SDK |
| Compression |
flate2 (gzip) |
zstd |
No busybox decompressor |
| Compression |
flate2 (gzip) |
lz4 |
No busybox decompressor |
| Format |
Manual bytes |
bincode/serde |
Recognizable patterns |
| Crypto ecosystem |
RustCrypto (aes+cbc) |
ring |
ring bundles C code |
| Crypto ecosystem |
RustCrypto (aes+cbc) |
openssl-rs |
Unnecessary system dep |
Cargo.toml
WARNING: Versions from training data (cutoff May 2025). Verify with cargo search CRATE --limit 1 before use.
Gaps Requiring Verification
- Exact latest crate versions (could not verify via crates.io)
- Confirm target busybox build includes
openssl applet
- Confirm
xxd availability in target busybox (fallback: od)
- Test PKCS7 padding round-trip across all three platforms
- Test flate2 GzEncoder output with busybox
gunzip and Android GZIPInputStream