docs: add project research
This commit is contained in:
174
.planning/research/STACK.md
Normal file
174
.planning/research/STACK.md
Normal file
@@ -0,0 +1,174 @@
|
||||
# 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:
|
||||
1. Kotlin on Android 13 (javax.crypto / java.security)
|
||||
2. 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
|
||||
|
||||
```toml
|
||||
[package]
|
||||
name = "encrypted_archive"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
aes = "0.8"
|
||||
cbc = "0.1"
|
||||
hmac = "0.12"
|
||||
sha2 = "0.10"
|
||||
flate2 = "1.0"
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
rand = "0.8"
|
||||
anyhow = "1"
|
||||
thiserror = "2"
|
||||
|
||||
[dev-dependencies]
|
||||
assert_cmd = "2"
|
||||
tempfile = "3"
|
||||
```
|
||||
|
||||
**WARNING: Versions from training data (cutoff May 2025). Verify with `cargo search CRATE --limit 1` before use.**
|
||||
|
||||
---
|
||||
|
||||
## Gaps Requiring Verification
|
||||
|
||||
1. Exact latest crate versions (could not verify via crates.io)
|
||||
2. Confirm target busybox build includes `openssl` applet
|
||||
3. Confirm `xxd` availability in target busybox (fallback: `od`)
|
||||
4. Test PKCS7 padding round-trip across all three platforms
|
||||
5. Test flate2 GzEncoder output with busybox `gunzip` and Android `GZIPInputStream`
|
||||
Reference in New Issue
Block a user