Skip to content

emilycodestar/cmd-chat

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

142 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🀐 CMD-CHAT

encrypted terminal chat. no servers. no logs. ram only.

License: MIT Python 3.10+


peer-to-peer encrypted chat that runs in your terminal. you host, you control. close the window β€” everything's gone.

why

every "secure" messenger still stores metadata somewhere. this doesn't. it's just two terminals talking over an encrypted tunnel. nothing written to disk, ever.

how it works

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ SRP AUTHENTICATION β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ CLIENT SERVER β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ │══════════════ TCP CONNECT ══════════════════►│ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ │─── {"cmd":"srp_init","username","A"} ──────► β”‚ β”‚ β”‚ β”‚ (A = client public ephemeral) β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ │◄──── {"user_id","B","salt","room_salt"} ──── β”‚ β”‚ β”‚ β”‚ (B = server public ephemeral) β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ [client derives room_key via HKDF: β”‚ β”‚ β”‚ β”‚ room_key = HKDF(password, room_salt)] β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ │─── {"cmd":"srp_verify","user_id","M"} ─────► β”‚ β”‚ β”‚ β”‚ (M = client proof) β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ │◄──────── {"H_AMK","session_key"} ─────────── β”‚ β”‚ β”‚ β”‚ (H_AMK = server proof) β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ [password never transmitted] β”‚ β”‚ β”‚ β”‚ [MITM can't derive session key] β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ E2E ENCRYPTED CHAT (same socket) β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ β”‚ β”‚ │◄─────── {"type":"init","messages","users"} ─ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”΄β”€β” β”Œβ”€β”€β”΄β”€β”€β” β”‚ β”‚ β”‚ C │─ {"type":"message","text":encrypted} ─►│ S β”‚ β”‚ β”‚ β”‚ L β”‚ β”‚ E β”‚ β”‚ β”‚ β”‚ I │◄── {"type":"message","data":{...}} ────│ R β”‚ β”‚ β”‚ β”‚ E β”‚ β”‚ V β”‚ β”‚ β”‚ β”‚ N │◄── {"type":"user_joined",...} ─────────│ E β”‚ β”‚ β”‚ β”‚ T β”‚ β”‚ R β”‚ β”‚ β”‚ β”‚ │◄── {"type":"user_left",...} ───────────│ β”‚ β”‚ β”‚ β””β”€β”¬β”€β”˜ β””β”€β”€β”¬β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ [server stores ONLY ciphertext] β”‚ β”‚ β”‚ β”‚ [server CANNOT read messages] β”‚ β”‚ β”‚ β”‚ [all clients with same password β”‚ β”‚ β”‚ β”‚ derive identical room_key] β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ Encryption: Fernet (AES-128-CBC + HMAC) β”‚ β”‚ β”‚ β”‚ Key derivation: HKDF-SHA256 β”‚ β”‚ β”‚ β”‚ Protocol: newline-delimited JSON over TCP β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ [on disconnect: keys wiped from RAM] β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ KEY HIERARCHY β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ password ──┬──► SRP ──► session_key (per-user, auth only) β”‚ β”‚ β”‚ β”‚ β”‚ └──► HKDF(password, room_salt) ──► room_key (shared) β”‚ β”‚ β”‚ β”‚ room_salt: generated once at server start β”‚ β”‚ room_key: deterministic, same for all clients with same pwd β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ 

SRP (Secure Remote Password) β€” password is never sent over the network. both sides prove they know it via zero-knowledge proof, then derive identical session keys.

install

git clone https://github.com/emilycodestar/cmd-chat.git cd cmd-chat python -m venv venv && source venv/bin/activate && pip install -r requirements.txt

windows:

python -m venv venv ; .\venv\Scripts\activate ; pip install -r requirements.txt

usage

start server:

python cmd_chat.py serve 0.0.0.0 3000 --password mysecret

connect:

python cmd_chat.py connect SERVER_IP 3000 username mysecret

Example

features

  • ram only β€” nothing touches disk
  • pure sockets β€” no http, no websocket, just raw tcp
  • srp auth β€” password never sent over network
  • e2e encryption β€” Fernet (AES-128-CBC + HMAC)
  • zero dependencies on web frameworks β€” only asyncio

license

MIT

About

My ISP tried to block this repo. 🀐 A truly peer-to-peer, end-to-end encrypted CLI chat that leaves NO logs. Perfect for... sensitive discussions. πŸ”₯ Get it before it gets taken down

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages