Skip to content

Latest commit

 

History

7 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🔐 Cryptex — E2E Encrypted Chat Application

Cryptex — the server carries your messages. It just can't read them.

License: MIT Python Version

Cryptex is an end-to-end (E2E) encrypted 1:1 messaging application built over WebSockets. Utilizing a hybrid cryptographic scheme combining RSA asymmetric key exchange and AES-GCM symmetric message encryption, it ensures that the central relay server never has access to plaintext messages, private keys, or raw session keys.


🔑 Cryptographic Design & Architecture

Hybrid Encryption Scheme

The application uses an industry-standard hybrid encryption pattern:

  1. RSA-3072 for Key Exchange: RSA is highly secure but too slow for encrypting large amounts of data. We use 3072-bit keys (providing a higher security margin than 2048-bit keys) to encrypt the ephemeral AES keys.
  2. AES-256-GCM for Message Payload:
    • For every single message sent, the sender generates a fresh, cryptographically secure 256-bit AES session key.
    • The message is encrypted using AES-GCM (Galois/Counter Mode). This provides both confidentiality and authenticity (tamper detection).
    • A unique 12-byte initialization vector (nonce) is generated randomly per message. Nonces are never reused under the same key.
    • The ephemeral AES key is then encrypted with the recipient's RSA public key.

Message Flow

    [Sender Client]                                            [Recipient Client]
           │                                                           │
 1. Generate AES key                                                   │
 2. Encrypt msg with AES-GCM                                           │
 3. Encrypt AES key with                                               │
    Recipient's Public Key                                             │
           │                                                           │
           │───────[ JSON Message Bundle (Base64 Fields) ]─────────────►
           │                    (Through Server)                       │
           │                                                           │
           │                                                  1. RSA-Decrypt AES key
           │                                                     with Private Key
           │                                                  2. AES-GCM Decrypt msg
           ▼                                                           ▼

JSON Message Bundle Format

Messages are transmitted as base64-encoded JSON strings:

{
  "type": "message",
  "encrypted_aes_key": "<base64 RSA-encrypted AES key>",
  "nonce": "<base64 12-byte AES-GCM nonce>",
  "ciphertext": "<base64 AES-GCM ciphertext>",
  "tag": "<base64 16-byte AES-GCM auth tag>"
}

Key Generation and Keystore

  • Client-Side Generation: RSA key pairs are generated locally. The private key never leaves the client's device/process.
  • Passphrase-Derived Encryption at Rest: When generating or storing keys, the client can choose to encrypt the private key. It is saved in PEM format using PKCS#8 serialization with BestAvailableEncryption (passphrase-derived key-wrapping).

⚠️ Security Notes & Limitations

Important

Educational Demonstration Only This repository is built as an educational demonstration of E2E encryption principles and is not audited for production/critical security environments.

Known Security Gaps (v1 MVP)

  1. Public Key Authentication (MITM): This version does not implement out-of-band public-key fingerprint verification ("safety numbers"). A compromised or malicious server could theoretically perform a Man-in-the-Middle (MITM) attack by replacing the public keys during the initial connect-time key exchange.
  2. Forward Secrecy: While session keys are generated per-message, true forward secrecy requires a protocol such as Double Ratchet / X3DH (Signal Protocol) to derive new keys from ephemeral DH handshakes. If a private RSA key is compromised, historic message payloads captured on the wire could be decrypted.
  3. Metadata Leakage: The server knows when connections are active and which IP addresses are communicating.

📁 Project Structure

cryptex/
├── cryptex/
│   ├── __init__.py
│   ├── server.py            # WebSocket relay server & client pairing
│   ├── client.py            # CLI-based E2E chat client
│   ├── crypto/
│   │   ├── __init__.py
│   │   ├── rsa_utils.py     # RSA generation, serialization & encryption
│   │   ├── aes_utils.py     # AES-GCM encrypt/decrypt wrappers
│   │   └── keystore.py      # Keystore for encrypted private keys on disk
│   └── protocol.py          # Message serialization (JSON + Base64)
├── tests/
│   ├── test_crypto.py       # Unit tests for cryptographic primitives
│   └── test_integration.py  # Server-client key exchange and relay tests
├── requirements.txt         # Project dependencies
├── LICENSE                  # MIT License
└── README.md                # Documentation

🚀 Setup Instructions

Prerequisites

  • Python 3.12+ installed.

Installation

  1. Clone the repository:

    git clone https://github.com/H8rsh100/Cryptex.git
    cd Cryptex
  2. Create a virtual environment and activate it:

    python -m venv venv
    # On Windows (PowerShell):
    .\venv\Scripts\Activate.ps1
    # On Linux/macOS:
    source venv/bin/activate
  3. Install the dependencies:

    pip install -r requirements.txt

💻 Usage

1. Run the Server

Start the WebSocket relay server on localhost:8765:

python -m cryptex.server

You can configure the host and port using environment variables:

# Windows
$env:CRYPTEX_HOST="0.0.0.0"
$env:CRYPTEX_PORT="8765"
# Linux/macOS
CRYPTEX_HOST="0.0.0.0" CRYPTEX_PORT="8765" python -m cryptex.server

2. Run Client A

Open a terminal and start the client:

python -m cryptex.client
  1. Enter a username (e.g., alice).
  2. Follow the prompt to encrypt the private key with a password.
  3. Keep the default server URL (ws://localhost:8765).

3. Run Client B

Open another terminal and start the client:

python -m cryptex.client
  1. Enter a different username (e.g., bob).
  2. Follow the prompt to set up password encryption for the keys.
  3. Enter the same server URL.

Once Bob connects, both clients will exchange public keys and establish an encrypted session. You can now chat! Type /exit to quit.


🧪 Running Tests

A comprehensive test suite is provided to verify unit-level cryptography and end-to-end messaging logic.

To execute tests:

pytest

🛠️ Planned Features (v2)

  • Key Fingerprint Verification: UI to check safety numbers out-of-band to prevent MITM attacks.
  • Double Ratchet Protocol: Ephemeral Diffie-Hellman handshakes for true forward secrecy.
  • Client-Side Message Database: Encrypted sqlite database for local chat history.
  • File Transfer: E2E encrypted local-to-local file transfers.

About

Production-grade Python E2E encrypted 1:1 messaging application over WebSockets using RSA-3072 key exchange and per-message AES-256-GCM authenticated encryption.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages