This project implements a secure messaging channel protocol inspired by modern cryptographic ratchet designs, featuring Diffie–Hellman key exchange, a key derivation function (KDF), symmetric encryption (AES-CBC), message authentication (HMAC-SHA256), forward secrecy, integrity and replay protection, and a simple simulation of a man-in-the-middle (MITM) attacker. This channel provides confidentiality, integrity, and mutual authentication.
- Note: In a real-world deployment, the initial key exchange would be protected by certificates (e.g., X.509/TLS) or another form of authenticated channel to prevent a man-in-the-middle from tampering with these long-term public keys.
-
Initial Handshake (Asymmetric Key Exchange) Upon connecting, the client and server each possess a long-term ECC keypair (P-256 curve). The client initiates the handshake by sending its public key (Base64‑encoded DER) to the server. The server responds with its own public key in the same format.
- This exchange establishes mutual authentication of the long-term keys.
- Both sides then compute a shared secret via Elliptic‑Curve Diffie–Hellman (ECDH).
-
Key Derivation Function (KDF) The raw ECDH secret is passed into a KDF based on SHAKE128 XOF, which "squeezes" exactly 32 bytes of pseudorandom output.
- Purpose: normalize the secret to a fixed length, ensure high entropy distribution, and prepare it for symmetric-key usage.
-
Symmetric Key Splitting From the 32‑byte KDF output, we derive two distinct symmetric keys by hashing with different labels:
- enc_key is used to encrypt message payloads under AES‑CBC with random IV. = auth_key is used to generate and verify HMAC-SHA256 over the JSON body.
-
Per-Message Ratchet For each message cycle, both client and server generate fresh ephemeral ECC keypairs and include the new public key in the next message or acknowledgment.
- After sending, each side updates its private key to the new ephemeral one, discarding the old.
- They recompute a fresh shared secret and symmetric keys, achieving forward secrecy: past keys cannot decrypt future messages.
-
Message Format and Transmission Each message is encapsulated as a JSON object.
"body": {
"nonce": 1,
"warnings": [],
"text": "5a8717dc4718ff1e40b244d8eec69047",
"iv": "e14ee2ea6d57f701f82acb3c85e98fd9",
"new_pub_key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEkqarK+XcgKKbSTVi+ajdjB8lFp3SlsvFGwTl8qFc7w1NuYLyuKDUnr9QncQl0Q2kZYfBa4nVQckfcFCOQ/3uog=="
},
"hmac": "b4bc93bf989554b30239529c08464420e20fb7ec2a05be9c7c6adb5086574a1d"
}
- nonce prevents replay: each side rejects messages with an older counter.
- warnings accumulates codes for any detected integrity or availability issues.
- text and iv represent the encrypted plaintext and IV.
- new_pub_key seeds the next ratchet step.
-
Message Processing
- Sender: pads and encrypts the UTF-8 plaintext under AES-CBC, encodes IV and ciphertext in hex, builds the JSON body, computes HMAC over the body, and serializes the full payload.
- Receiver: parses JSON, validates structure, verifies HMAC (throws
InvalidHashErroron mismatch), checks nonce order (InvalidNonceErroron replay), decrypts ciphertext (ValueErrorif padding/IV wrong), logs content and warnings, then updates ratchet state.
-
Attack Simulation (MITM) A separate
mitm_wrapper.pyacts as a proxy between client and server, allowing configurable behaviors per message index:- Drop: return empty payload to simulate availability attack.
- Modify: tamper with JSON fields or ciphertext to test integrity checks.
- Replay: resend old messages to test nonce-based replay protection.
- Install dependencies -
pip install -r requirements.txt - (Optional)Generate fresh keys - Run
entrypoints/generate_keys.py, copy the printed base64 values intoconfig/keys.py. - Start the server - run
entrypoints/server_wrapper.py, Ensure the server listens on its configured PORT (default 65432). - (Optional) Start the MITM - run
entrypoints/mitm_wrapper.py, Listen on the client port (65431) and forward to the server port (65432). - Start the client - run
entrypoints/client_wrapper.py(default 65432, set to 65431 if you want to invite the "man in the middle". - Observe logs - Server logs decrypted messages to
server_output.txtand Console warnings appear on integrity or drop attacks.
Enjoy experimenting with secure messaging, ratchets, and MITM resilience! :)
- entrypoints/
- client_wrapper.py
- server_wrapper.py
- mitm_wrapper.py
- generate_keys.py
- vpn/
- crypto.py
- message.py
- vpn_client.py
- vpn_server.py
- config/
- keys.py
If you find any issues, have questions, or suggestions for improvement, feel free to reach out:
- Email: yonzra12@gmail.com
- Linkdin: www.linkedin.com/in/yehonatanezra