terminalphone/CLAUDE.md
2026-02-26 09:39:50 -05:00

120 lines
4.3 KiB
Markdown

# terminalphone
encrypted, anonymous walkie-talkie over tor. single bash script (~3k lines),
no servers, no accounts. your .onion address is your identity.
## what it does
two parties share a secret, connect via tor hidden services, and talk using
push-to-talk voice (opus-encoded, aes-encrypted). also supports encrypted
text chat mid-call.
## audio pipeline
```
mic → raw pcm (8khz mono) → opus encode (16kbps) → aes encrypt → base64 → socat → tor
tor → socat → base64 decode → aes decrypt → opus decode → speaker
```
record-then-send model (not streaming) - irregular transmission patterns make
traffic analysis harder.
## wire protocol
text-based, line-delimited over socat/tor:
- `ID:<onion>` - caller id exchange
- `CIPHER:<name>` - cipher negotiation
- `PTT_START` / `PTT_STOP` - recording state
- `AUDIO:<base64>` - encrypted audio payload
- `MSG:<base64>` - encrypted text message
- `HANGUP` / `PING` - control signals
optional HMAC-SHA256 signing with nonce replay protection (both sides must match).
## project structure
```
terminalphone.sh the whole thing. single script
README.md usage docs
CHANGELOG version history
LICENSE MIT
CLI.png screenshot
```
runtime data lives in `.terminalphone/` (auto-created):
- `tor_data/` - tor hidden service keys
- `audio/` - temp audio files (cleaned on exit)
- `pids/` - process id tracking
- `run/` - named pipes, flags, cipher state
- `shared_secret` - encrypted pre-shared key
- `torrc` - generated tor config
- `config` - user settings
## dependencies
core: `tor`, `opus-tools`, `sox`, `socat`, `openssl`, `arecord`/`aplay`
optional: `snowflake-client`, `qrencode`, `jq` (termux vol-ptt)
platforms: linux (deb/fed/arch), android (termux + termux:api from f-droid)
## running it
```bash
bash terminalphone.sh # interactive menu
bash terminalphone.sh listen # listen mode
bash terminalphone.sh call ADDR # call a .onion address
bash terminalphone.sh install # install deps
bash terminalphone.sh test # audio loopback test
bash terminalphone.sh status # show status
```
in-call: SPACE=ptt, T=text msg, S=settings, Q=hangup
## key code areas
the script is organized roughly as:
- **config** (~line 1-150): load_config/save_config, defaults
- **deps/install** (~150-400): install_deps, check_dep, platform detection
- **tor management** (~400-700): setup_tor, start/stop/restart, get_onion, rotate_onion
- **encryption** (~700-900): encrypt_file/decrypt_file, PBKDF2 key derivation, fd passing
- **protocol** (~900-1050): proto_send/proto_verify, HMAC auth, nonce tracking
- **audio** (~1050-1400): audio_record, start_recording, stop_and_send, audio_play, voice effects
- **call flow** (~1400-1900): listen_for_call, call_remote, in_call_session, cleanup_call
- **settings menus** (~1900-2600): cipher (21 options), opus quality, snowflake, voice effects, tor, security
- **auto-listen** (~2600-2750): background listener management
- **main menu** (~2750-3079): interactive menu loop, cli arg parsing
## config options
stored in `.terminalphone/config`:
- `LISTEN_PORT` (7777), `TOR_SOCKS_PORT` (9050)
- `OPUS_BITRATE` (16kbps), `CIPHER` (aes-256-cbc)
- `SNOWFLAKE_ENABLED`, `AUTO_LISTEN`, `PTT_KEY`
- `SHOW_CIRCUIT`, `EXCLUDE_NODES`, `HMAC_AUTH`
- `VOICE_EFFECT` (none/deep/high/robot/echo/whisper/custom)
## security model
- e2e encryption with 21 cipher options (aes, chacha20, camellia, aria)
- secrets passed via file descriptors (not visible in process table)
- tor hidden service per instance (no ip exposure)
- passphrase-protected secrets at rest (aes-256-cbc + 100k pbkdf2)
- opaque temp filenames (random hex, generic .tmp extension)
- country exclusion for tor circuits (five/nine/fourteen eyes presets)
## hacking notes
- it's all bash - no build step, no transpilation
- named pipes (fifos) are the ipc mechanism between socat and the call session
- `uid()` generates random hex from /dev/urandom
- platform branching happens via `is_termux()` checks throughout
- cleanup_call() is critical - handles pipe/process/file cleanup on disconnect
- the settings system uses a simple key=value flat file
- no test framework exists yet - testing is manual via loopback (option 5)
## style
- bash with `#!/usr/bin/env bash`
- functions use snake_case
- log_info/log_warn/log_error/log_debug for output
- match existing formatting and comment style