Peer-to-peer encrypted chat with a custom cryptographic protocol — no TLS, no third parties, no trust required.
Zero-configuration • Auto-enrollment • Forward secrecy • Ephemeral certificates
Most encrypted chat tools lean on TLS or rely on centralized key servers. WhisperNode takes a different path: a custom CertECDHE protocol built from the ground up — certificate-authenticated, ephemeral Diffie-Hellman key exchange over raw TCP. One person hosts, the other joins. Certificates are issued on the fly, keys are exchanged, and a secure AES-256-GCM channel is established — all in under a second, on a single port, with zero manual setup.
When the chat ends, all cryptographic material is automatically destroyed.
| Feature | Detail | |
|---|---|---|
| 🔑 | Custom CertECDHE Protocol | Certificate-authenticated ECDHE — no TLS dependency |
| 🛡️ | AES-256-GCM Encryption | Authenticated encryption with counter-based nonces (replay-proof) |
| ⚡ | Ed25519 Identity Keys | ~128-bit security, faster than RSA, smaller signatures |
| 🔄 | X25519 Ephemeral Key Exchange | Perfect forward secrecy — compromise of long-term keys can't decrypt past sessions |
| 📜 | Auto-Enrollment (CSR) | Joining peers get a signed certificate over the wire — no manual cert transfer |
| 🧹 | Ephemeral Certificates | All user keys and certs are deleted on disconnect |
| 🖥️ | Dual Interface | Full CLI and a polished Tkinter GUI (Catppuccin Mocha theme) |
| 📦 | Single Dependency | Only requires the cryptography library |
┌─────────────────────────────────────────────────────────────────┐
│ WhisperNode │
├──────────────┬──────────────┬────────────────┬──────────────────┤
│ cli.py │ gui.py │ protocol.py │ crypto_utils.py │
│ CLI entry │ GUI entry │ CertECDHE │ AES-GCM, HKDF, │
│ + chat loop │ + Tkinter │ key exchange │ Ed25519, certs │
├──────────────┴──────────────┴────────────────┴──────────────────┤
│ setup_certs.py │
│ Root CA generation • Client certificate issuance │
└─────────────────────────────────────────────────────────────────┘
| File | Purpose |
|---|---|
cli.py |
Interactive terminal interface — host or join, auto-enroll, chat |
gui.py |
Tkinter GUI with rounded widgets, chat bubbles, dark theme |
protocol.py |
The CertECDHE handshake — mutual auth + ephemeral key agreement |
crypto_utils.py |
AES-256-GCM SecureChannel, HKDF, Ed25519 sign/verify, cert utilities |
setup_certs.py |
X.509 Root CA and client certificate generation (Ed25519) |
WhisperNode implements a 7-step custom key exchange that combines X.509 certificate authentication with ephemeral Diffie-Hellman — providing both mutual identity verification and forward secrecy.
Alice (Initiator) Bob (Responder)
│ │
─────┤ Step 1: HELLO + Certificate (PEM) │
│─────────────────────────────────────────────►│
│ ├──── Verify Alice's cert
│ Step 2: HELLO_ACK + Certificate ├──── against trusted CA
│◄─────────────────────────────────────────────│
─────┤ │
Verify Bob's cert │
against trusted CA │
│ │
─────┤ Step 4: X25519 public key + Ed25519 sig │
│─────────────────────────────────────────────►│
│ ├──── Verify signature
│ Step 5: X25519 public key + sig │ Generate shared secret
│◄─────────────────────────────────────────────│
─────┤ │
Verify signature │
Generate shared secret │
│ │
═════╪══════════════════════════════════════════════╪═════
│ Step 7: HKDF-SHA256 key derivation │
│ (salted with sorted ECDH public keys) │
│ │
│ AES-256-GCM Secure Channel │
│◄════════════════════════════════════════════►│
Key properties:
- Mutual authentication — both sides prove identity via CA-signed certificates
- Forward secrecy — ephemeral X25519 keys are generated per session and never stored
- Replay protection — counter-based nonces with strict monotonic validation
- No TLS — the entire handshake runs over raw TCP with length-prefixed JSON framing
- Key binding — HKDF salt includes both ECDH public keys, preventing key-compromise impersonation
New peers don't need pre-shared certificates. When someone joins a host for the first time, an inline CSR enrollment runs transparently before the key exchange — all on the same TCP connection:
Joiner Host
│ │
│ 1. Generate Ed25519 key │
│ 2. Build CSR (Certificate Signing Request) │
│ │
│ ──── ENROLL_REQUEST { name, CSR } ────────► │
│ │ 3. Validate CSR signature
│ │ 4. Sign cert with Root CA
│ ◄─── ENROLL_RESPONSE { cert, CA cert } ──── │
│ │
│ 5. Save cert + CA cert locally │
│ │
│ ═══════ CertECDHE handshake begins ═══════ │
- Python 3.10+
pippackage manager
git clone https://github.com/your-username/whisperNode.git
cd whisperNode
pip install -r requirements.txtThe only dependency is
cryptography>=41.0.0.
python cli.pyYou'll be prompted for your name and whether to host or join:
╔══════════════════════════════════════════════════════════╗
║ WhisperNode — Interactive Setup ║
║ Custom CertECDHE Key Exchange + AES-256-GCM ║
╚══════════════════════════════════════════════════════════╝
Enter your name: Alice
1) Host a chat (you are the server)
2) Join a chat (connect to someone else)
Your choice [1/2]: 1
Port [5555]:
[*] Alice's server listening on port 5555
[*] Your IP: 192.168.1.42
Tell the other person to run:
python cli.py
and connect to 192.168.1.42:5555
On the other machine (or terminal):
Enter your name: Bob
Your choice [1/2]: 2
Server IP address [127.0.0.1]: 192.168.1.42
Port [5555]:
[+] Connected!
[*] Enrolling with host...
[+] Enrolled! Certificate saved.
[Protocol] Key exchange COMPLETE — secure channel established!
Secure channel with Alice established!
Type messages below. Ctrl+C, /quit or /close to exit.
You >
python gui.pyA dark-themed Tkinter window opens with:
- Name field, Host/Join toggle, IP & port inputs
- One-click Start Chat button
- Chat bubbles, encryption badge, online status indicator
Generate certificates manually (optional — the interactive modes handle this automatically):
# Generate Root CA + Alice & Bob certificates
python setup_certs.py
# Generate CA + custom names
python setup_certs.py --names Charlie Diana
# Add a user to an existing CA
python setup_certs.py --add-user EveCertificates are stored in ./certs/ and use the following structure:
certs/
├── ca_key.pem # Root CA private key (Ed25519)
├── ca_cert.pem # Root CA certificate (10-year validity)
├── alice_key.pem # Alice's private key
├── alice_cert.pem # Alice's certificate (1-year, signed by CA)
├── bob_key.pem # Bob's private key
└── bob_cert.pem # Bob's certificate (1-year, signed by CA)
Note: In interactive mode (CLI/GUI), user certificates and keys are automatically deleted when the chat session ends or the application is closed.
| Layer | Algorithm | Purpose |
|---|---|---|
| Identity keys | Ed25519 | Long-term identity, certificate signing (~128-bit security) |
| Key exchange | X25519 | Ephemeral ECDHE — a new keypair per session |
| Key derivation | HKDF-SHA256 | Derives 256-bit AES key from shared secret |
| Encryption | AES-256-GCM | Authenticated encryption with 96-bit counter nonces |
| Certificates | X.509 (PEM) | Standard certificate format with CA trust chain |
| Framing | 4-byte length prefix | Binary framing over raw TCP |
whisperNode/
├── cli.py # Terminal interface (host/join/chat)
├── gui.py # Tkinter GUI interface
├── protocol.py # CertECDHE key exchange implementation
├── crypto_utils.py # Cryptographic primitives & secure channel
├── setup_certs.py # Certificate authority & cert generation
├── requirements.txt # Dependencies (cryptography>=41.0.0)
└── certs/ # Generated certificates (gitignored)
- Confidentiality — AES-256-GCM encrypts all messages after key exchange
- Integrity — GCM authentication tags detect any tampering
- Authentication — Ed25519 certificates verify both peers' identities
- Forward secrecy — Ephemeral X25519 keys ensure past sessions stay private
- Replay protection — Monotonic counter nonces reject reordered/replayed messages
- Ephemeral operation — Certificates are destroyed on session end
The host acts as the Certificate Authority. When a peer joins, they receive a certificate signed by the host's CA. Both sides verify each other against this shared CA during the CertECDHE handshake. This is a trust-on-first-use (TOFU) model — the joiner trusts the host's CA upon enrollment.
- Anonymity — IP addresses are visible to both peers
- Multi-party chat — designed for 1:1 sessions
- Persistence — messages are not stored; when the session ends, they're gone
- Protection against a compromised host — the host controls the CA
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Built with 🔐 and raw sockets — because sometimes you want to know exactly what's happening on the wire.