A minimal peer-to-peer chat app that performs a password-based, encrypted handshake and then exchanges AES-GCM encrypted messages over a TCP connection. Includes a PySide6 GUI that shows plaintext, ciphertext, nonces, and connection status.
- Password-derived master key (PBKDF2-HMAC-SHA256)
- Per-session key derivation (HKDF-SHA256) with rekeying
- AES-GCM message encryption with associated data
- Simple JSON framing protocol over TCP
- GUI for hosting, connecting, and message inspection
- This is a learning project; it is not production hardened.
- The shared password must be communicated out-of-band.
- If authentication fails, messages are rejected and the connection is closed.
- Python 3.10+
- PySide6
- cryptography
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtpython main.py- On one machine, enter a port and password, then click Host.
- On the other machine, enter the host IP, matching port, and password, then click Connect.
- Once the secure session is verified, type a message and click Send.
- A TCP connection is established.
- The host sends a setup packet containing a random salt and session ID.
- Both peers derive a master key from the password and salt, then a session key from the master key, session ID, and rekey counter.
- The client sends an encrypted "CLIENT_HELLO" and the host replies with an encrypted "SERVER_HELLO" to verify the shared keys.
- Messages are encrypted using AES-GCM with associated data of the form "message:<rekey_counter>".
- Every
rekey_everymessages, a new session key is derived.
- crypto_utils.py: Key derivation, encryption, and decryption helpers
- protocol.py: Framed JSON packet send/receive
- network.py: Connection lifecycle, handshake, and message handling
- gui.py: PySide6 UI and user interactions
- main.py: App entry point
- If you see "Message authentication failed", check that both sides used the same password.
- If the connection drops immediately, verify the port is open and not in use.