Files
android-encrypted-archiver/.planning/research/PITFALLS.md
2026-02-24 22:51:05 +03:00

90 lines
4.9 KiB
Markdown

# Common Pitfalls
**Domain:** Custom encrypted archiver with busybox/Kotlin decompression
**Researched:** 2026-02-24
**Confidence:** HIGH
## Critical Pitfalls
### Pitfall 1: Busybox OpenSSL Cipher Availability
**What:** Target busybox may not have the chosen cipher. GCM, ChaCha20 are likely unavailable.
**Prevention:** Test `busybox openssl enc -ciphers` on actual device FIRST. Use AES-256-CBC (universally available).
**Phase:** Phase 1 (format design) — blocking decision.
### Pitfall 2: Endianness Mismatch Across Platforms
**What:** Inconsistent byte order between Rust (x86_64), Kotlin (ARM64), shell (xxd parsing).
**Prevention:** Use little-endian everywhere. Rust: `to_le_bytes()`. Kotlin: `ByteBuffer.order(LITTLE_ENDIAN)`. Document in format spec.
**Phase:** Phase 1 (format design).
### Pitfall 3: PKCS7 Padding Incompatibility
**What:** Different padding handling between Rust crates, javax.crypto, and busybox openssl causes last-block corruption.
**Prevention:** Store exact compressed-data length in header. Use `-nopad` in openssl and truncate manually, OR let openssl handle padding with `-K`/`-iv` flags. Test with non-16-byte-aligned data.
**Phase:** Phase 2 (encryption implementation).
### Pitfall 4: OpenSSL Key Derivation (EVP_BytesToKey vs Raw Key)
**What:** busybox `openssl enc` derives keys via EVP_BytesToKey by default. Rust/Kotlin use raw keys. Decryption produces garbage.
**Prevention:** Use `-K HEX -iv HEX -nosalt` flags for raw key mode. Test on target device FIRST. This is the #1 failure mode.
**Phase:** Phase 1 (format design) — blocking.
### Pitfall 5: Shell Arithmetic Overflow with Large Files
**What:** busybox `sh` arithmetic may be 32-bit signed, overflowing at 2GB offsets.
**Prevention:** Use `dd bs=4096` with block-count math. Limit archive size in spec. Test with >50MB archives.
**Phase:** Phase 1 (format) + Phase 5 (shell decoder).
### Pitfall 6: IV/Nonce Reuse with Hardcoded Key
**What:** Same key + same IV = identical ciphertext for identical files. Information leak.
**Prevention:** Random 16-byte IV per file, stored in cleartext alongside ciphertext. Never deterministic IV.
**Phase:** Phase 2 (encryption).
### Pitfall 7: Busybox xxd Behavioral Differences
**What:** busybox `xxd` may not support all GNU xxd flags. Key/IV hex conversion fails silently.
**Prevention:** Use only `xxd -p` and `xxd -r -p`. Test on actual device. Fallback: `od -A n -t x1`.
**Phase:** Phase 5 (shell decoder).
## Moderate Pitfalls
### Pitfall 8: APK Files Don't Compress
**What:** APKs are already ZIP-compressed. Gzip makes them larger.
**Prevention:** Per-file compression flag. Skip compression if output >= input.
**Phase:** Phase 2 (compression).
### Pitfall 9: Missing Integrity Verification
**What:** No checksums = silent data corruption from bit flips during transfer.
**Prevention:** SHA-256 checksum per file. Verify AFTER decompression in all three decoders.
**Phase:** Phase 1 (format) + all decoder phases.
### Pitfall 10: Over-Engineering Obfuscation
**What:** Complex obfuscation (block shuffling, fake headers) triples implementation complexity with minimal security gain against casual users.
**Prevention:** AES encryption IS obfuscation. Custom magic bytes + encrypted payload is sufficient. Keep it simple.
**Phase:** Phase 1 (format design).
### Pitfall 11: Rust/Kotlin Crypto Output Incompatibility
**What:** "Same algorithm" produces different bytes due to framing differences (IV placement, padding).
**Prevention:** Define wire format explicitly: `[16-byte IV][PKCS7-padded ciphertext]`. Golden test vectors mandatory.
**Phase:** Phase 2 (encryption).
### Pitfall 12: Android Filesystem Permissions
**What:** Extracted files land in wrong location or have wrong permissions on Android.
**Prevention:** Store only relative paths. Don't store Unix permissions. Let each decoder handle permissions.
**Phase:** Phase 4 (Kotlin decoder).
## Minor Pitfalls
- **#13:** Flush/sync writes in shell script — use `sync` after critical files
- **#14:** Missing version field — add 1-2 byte version after magic bytes (non-negotiable)
- **#15:** Testing only ASCII filenames — include Cyrillic test files
- **#16:** Hardcoded key visible in `strings` — store as byte array, split hex fragments in shell
## Key Insight
**The busybox shell constraint drives everything.** Every format decision must be validated against "can busybox sh + dd + xxd + openssl actually implement this?" Build shell decompressor prototype EARLY, not last.
## Phase Mapping
| Phase | Critical Pitfalls | Action |
|-------|------------------|--------|
| Format design | #1, #2, #4, #5, #10, #14 | Test busybox on device. Write format spec. Keep it simple. |
| Encryption | #3, #6, #8, #11 | Golden test vectors. Random IV. Per-file compression flag. |
| Kotlin decoder | #11, #12 | Explicit wire format. Test on device. |
| Shell decoder | #1, #4, #5, #7, #15 | Busybox compatibility suite. Large file tests. |