encrypted terminal chat with file xfer, shared terminal acess, sandbox vm supporitn docker, multipass and virtualbox. also local ai model integration.
Go to file
2026-05-31 23:39:26 -07:00
.github/workflows Add Django CI workflow for testing 2026-01-15 18:40:26 +02:00
cmd_chat feat: encrypted file transfer with propose/accept flow 2026-05-26 00:01:51 -07:00
lab feat: add host-chat.sh — one-command server setup with friend instructions 2026-05-25 22:40:57 -07:00
tests fix(security): comprehensive security hardening — TLS, HMAC WS auth, rate limiting, IP leak prevention 2026-05-25 20:30:40 -07:00
.gitignore feat: add SRP authentication, improve security 2026-01-02 23:09:00 +03:00
cmd_chat.py feat: complete client-server architecture refactoring 2026-01-02 14:42:33 +03:00
CONTRIBUTING.md Add CONTRIBUTING.md file 2026-01-17 16:52:33 +09:00
example.gif New README + Demonstartional video 2026-01-02 20:37:11 +03:00
LICENSE Code refactoring 2023-03-08 18:59:38 +03:00
README.MD Update README.MD 2026-05-31 23:39:26 -07:00
requirements.txt feat: add interactive 2-user lab environment + fix requirements.txt encoding 2026-05-25 21:44:24 -07:00
tests.bat feat: add SRP authentication, improve security 2026-01-02 23:09:00 +03:00

HACK-HOUSE

end-to-end encrypted terminal chat with file transfer

License: MIT Python 3.10+


Fork from https://github.com/diorwave/cmd-chat

This tool a privacy and security oriented chatroom that we added file sharing as well as shared terminal sessions.

For sharing. For learnng. For hacking. For building. For demos. For teaching. For mentorhsip for the people who dont want to trust corporations to manage their data and communications.

Encrypted chat that runs in your terminal. You host the server, you control the room. Close the window — everything's gone. Messages and files are encrypted client-side before the server ever sees them.

Features

  • End-to-end encrypted — messages encrypted with Fernet (AES-128-CBC + HMAC) before leaving your machine
  • TLS by default — auto-generated self-signed certs, or bring your own
  • SRP authentication — password never sent over the network (zero-knowledge proof)
  • Encrypted file transfer/send, /accept, /reject with SHA-256 verification
  • RAM only — nothing written to disk on the server
  • Rate limiting — brute-force protection on auth endpoints
  • No IP leaks — client IPs never broadcast to other users
  • Password hidden — prompted securely via getpass, never visible in ps or shell history

Install

git clone https://github.com/diorwave/cmd-chat.git
cd cmd-chat
pip install -r requirements.txt

Quick Start

Host a chat room:

python3 cmd_chat.py serve 0.0.0.0 3000

You'll be prompted for a room password (hidden input). An admin token and TLS cert path will print to the console.

Connect to a chat room:

python3 cmd_chat.py connect SERVER_IP 3000 yourname --insecure

--insecure is needed for self-signed certs. You'll be prompted for the room password.

Securing Your Connection

Both parties install Tailscale. Traffic goes through an encrypted WireGuard tunnel. No port forwarding, works across NATs.

# Host
python3 cmd_chat.py serve 0.0.0.0 3000

# Friend connects using your Tailscale IP
python3 cmd_chat.py connect 100.x.x.x 3000 theirname --insecure

Find your Tailscale IP: tailscale ip -4

LAN (same network)

Use your local IP. Both devices must be on the same WiFi/network.

python3 cmd_chat.py connect 192.168.1.x 3000 theirname --insecure

Public Internet

Requires port forwarding on your router (TCP port 3000 to your machine). Use --cert and --key with a real certificate for production use.

python3 cmd_chat.py connect PUBLIC_IP 3000 theirname --insecure

Find your public IP: curl ifconfig.me

Sharing the Room Password

The password must be shared outside the chat. Never send it over an unencrypted channel.

  1. In person — tell them verbally
  2. Signal — disappearing message set to 30 seconds
  3. One-time linkonetimesecret.com (self-destructs after one view)
  4. Split it — send half via Telegram, half via SMS

Chat Commands

Command Action
/send <filepath> Propose a file transfer to the room
/accept Accept a pending file offer
/reject Decline a pending file offer
q Disconnect

File Transfer

Files are chunked (64KB), encrypted with the room key, and relayed through the server as opaque ciphertext. The server never sees file names, contents, or metadata.

alice> /send report.pdf
bob>   "alice wants to send report.pdf (1.2 MB) — /accept or /reject"
bob>   /accept
       Receiving: 100% (1.2 MB/1.2 MB)
       File saved: ./downloads/report.pdf — SHA-256 verified
  • Max file size: 50 MB
  • Files saved to ./downloads/ relative to where the client was launched
  • SHA-256 integrity check on every transfer

CLI Reference

Server

python3 cmd_chat.py serve <bind_ip> <port> [options]
Flag Purpose
--password, -p Room password (prompted if omitted)
--cert Path to TLS certificate
--key Path to TLS private key
--no-tls Disable TLS (local dev only)

Client

python3 cmd_chat.py connect <server_ip> <port> <username> [options]
Flag Purpose
--password, -p Room password (prompted if omitted)
--insecure, -k Skip TLS cert verification (self-signed certs)
--no-tls Connect without TLS

Environment Variable

Set CMD_CHAT_PASSWORD to skip the password prompt for both server and client.

Helper Scripts

./lab/host-chat.sh

One-command server setup. Detects your IPs (Tailscale, LAN, public), prints the exact connect command your friend needs, then starts the server.

./lab/host-chat.sh              # TLS on port 4000
./lab/host-chat.sh --port 5000  # custom port
./lab/host-chat.sh --no-tls     # disable TLS

./lab/setup-lab.sh

Spins up a tmux session with the server and two chat clients side-by-side for local testing.

./lab/setup-lab.sh                          # default lab
./lab/setup-lab.sh --no-tls --port 4001     # plain HTTP
./lab/setup-lab.sh --user1 alice --user2 bob
./lab/setup-lab.sh --teardown               # clean up

Attach with tmux attach -t cmd-chat-lab. Switch panes with Ctrl+B then arrow keys.

How It Works

CLIENT                              SERVER                         CLIENT
  │                                   │                               │
  │── POST /srp/init {A} ──────────► │                               │
  │◄── {B, salt, room_salt} ──────── │                               │
  │                                   │                               │
  │  derive room_key = HKDF(password, room_salt)                      │
  │                                   │                               │
  │── POST /srp/verify {M} ────────► │                               │
  │◄── {H_AMK, ws_token} ─────────── │                               │
  │                                   │                               │
  │══ WSS /ws/chat?ws_token ════════► │ ◄══════════════════════════════│
  │                                   │                               │
  │  encrypt(msg, room_key) ────────► │ ──── ciphertext ────────────► │
  │                                   │           decrypt(ciphertext, room_key)
  │                                   │                               │
  │  server stores ONLY ciphertext    │                               │
  │  server CANNOT read messages      │                               │

SRP (Secure Remote Password) — both sides prove they know the password without transmitting it. A network observer learns nothing.

Room Key — derived independently by each client via HKDF(password, room_salt). All clients with the same password get the same key. The server never has the key.

WebSocket Auth — HMAC-SHA256 token issued after SRP verification. Prevents session hijacking.

Admin

The server prints an admin token at startup. Use it to clear message history:

curl -k -X DELETE https://SERVER:3000/clear \
  -H "Authorization: Bearer <admin-token>"

License

MIT