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

4.9 KiB

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.