中文版 | English
ChatE2E is an end-to-end encrypted (E2EE) instant messaging application developed with Python. It implements a Signal Protocol-like secure communication mechanism, ensuring that messages can only be decrypted by the sender and receiver, with the server unable to access message content.
graph TB
subgraph "Key Initialization"
A1["Alice Generates Key Pairs"] -->|Generate| A2["Identity Key Pair"]
A1 -->|Generate| A3["Signed PreKey Pair"]
A1 -->|Generate| A4["One-Time PreKey Pairs"]
B1["Bob Generates Key Pairs"] -->|Generate| B2["Identity Key Pair"]
B1 -->|Generate| B3["Signed PreKey Pair"]
B1 -->|Generate| B4["One-Time PreKey Pairs"]
end
subgraph "X3DH Key Agreement"
I1["Alice (Initiator) Calculates DH"] -->|DH1| I2["IKa × SPKb"]
I1 -->|DH2| I3["EKa × IKb"]
I1 -->|DH3| I4["EKa × SPKb"]
I1 -->|DH4| I5["EKa × OPKb"]
I2 & I3 & I4 & I5 -->|Combine| SK1["Shared Key SK"]
SK1 -->|HKDF| RK1["Root Key"]
RK1 -->|Derive| CK1["Sending Chain Key"]
RK1 -->|Derive| CK2["Receiving Chain Key"]
end
subgraph "Message Encryption Process"
M1["Sender"] -->|"1. Use Sending Chain Key"| M2["Derive Message Key"]
M2 -->|"2. HKDF Derivation"| M3["New Sending Chain Key"]
M2 -->|"3. AESGCM Encryption"| M4["Encrypted Message"]
M4 -->|"4. Add Header Info"| M5["Final Ciphertext"]
end
subgraph "Message Decryption Process"
D1["Receiver"] -->|"1. Verify Message Source"| D2["Select Correct Chain Key"]
D2 -->|"2. HKDF Derivation"| D3["Message Key"]
D3 -->|"3. AESGCM Decryption"| D4["Decrypted Message"]
D2 -->|"4. Update"| D5["New Receiving Chain Key"]
end
A4 --> I1
B4 --> I1
M5 --> D1
This project includes the following core technical components:
The core security mechanism is based on a variant of the Signal Protocol, implementing Forward Secrecy and Post-Compromise Security.
- X3DH (Extended Triple Diffie-Hellman): Used for initial key agreement. When two users first establish a session, they exchange pre-keys (Identity Key, Signed PreKey, One-Time PreKey) through the server to negotiate a shared key, ensuring asynchronous communication security.
- Double Ratchet Algorithm: Used for key updates during sessions.
- Diffie-Hellman Ratchet: Continuously updates the shared key with message exchanges, providing forward secrecy.
- KDF Chain (Hash) Ratchet: Generates independent encryption keys for each message.
- Cryptographic Primitives:
- X25519: Elliptic curve Diffie-Hellman key exchange.
- AES-GCM: Authenticated encryption with associated data.
- HMAC-SHA256 / HKDF: Key derivation functions.
- Client-Server Model: The server only serves as a message relay and key storage center.
- WebSocket (Socket.IO): Used for real-time message push, friend status updates, and signaling exchange.
- REST API (Flask): Used for user registration, bundle upload and retrieval, offline message pulling, etc.
- PyQt6: Cross-platform desktop GUI built using Python's Qt binding library.
- Local Storage: User keys, session states, and chat history are encrypted and stored in local JSON files.
- Python 3.8 or higher
-
Clone the repository:
git clone https://github.com/NiceAsiv/ChatE2E.git cd ChatE2E -
Create and activate a virtual environment (recommended):
# Using Conda conda env create -f conda_env.yaml conda activate chat_e2e_env # Or using venv python -m venv venv # Windows .\venv\Scripts\activate # Linux/Mac source venv/bin/activate
-
Install dependencies:
pip install -r requirements.txt
This project includes server-side and client-side startup scripts, supporting multi-user communication simulation on the same machine.
First, start the central server to handle signaling exchange and message forwarding.
python start_server.py- The server runs by default on
http://localhost:5000.
You can start multiple client instances to simulate different users.
Start the first client (Alice):
python start_client.pyStart the second client (Bob):
python start_client2.py-
Register/Login: Enter a username (e.g., "Alice" or "Bob") in the client login interface. If it's the first login, the system will automatically register and generate encryption key pairs. Below is an example of a registered account:
Username: test
Password: 123456
{ "user_id": "e7be3149a1614170", "username": "test", "avatar_path": "assets/avatars\\default.png", "status": "offline", "last_seen": "2025-12-13T08:48:48.947842+00:00", "password_hash": "jOW/DBLv9KzEOB9jiy74i6egbUGTIAPyV/dkx5IUc60=", "salt": "faQh1etsHfWvuZO+iuPPsw==", "bundle": { "identity_key_pub": "G+mYjBFpIXI6wWxMGWN90OOJXOxLwDXAGMIJd3diSmk=", "signed_pre_key_pub": "vj5UITryFzcV+4Om3MXS0gFJs852LMpEZrMd4rhu0Qo=", "signed_pre_key_signature": "KgYZ7ue/nHQfIZuHrqL8dcS/7kv0gqeE+8aNpC3VNs4=", "one_time_pre_keys_pub": [ "ZYIA8Sx38/DeIESENuL3tZwglYHVMgDO3Cv9DOdCp3U=", "jiMqTO7VAKHN/D4uQvCidv4/BZVDcfsEkJWn8jVyQi8=", "BNucY7d4LeC7PlhLvmS5obbq54dlphgJtMDN5hOlbws=", "KzDr5L308u3WkKBX89yn3FlI1VnCCmT/tdNM+s6BEG0=", "ZCEn1qqSYBo2eQmKijKdLqnd2K6X0yP4SRLEu22xJnY=", "qaT9wzqJcLOGy+1TUKgnPGmEOe4zwh+2yXHQmJoDkw8=", "cmN6CS3RHw1R+L0qaFTIQbbV/enLB7i6vieTBgEXagQ=", "SShCloFXDmuAOfK0ecqN4FEe22zkJnBqIwbstoCmfE0=", "W4gCafsvi3ZoSmEz6qHTTPKbbCtc5+h2VEcq0nmxb30=", "nTMv+nkrfU76S9ym71MtGclWse0Ya9+fgLYqKNb6yS8=" ] }, "localBundle": { "identity_key_pair": { "private_key": "wLzArjb/k98rK+8HGCeBehQujYpLICrJN/wdsmK4g1Q=", "public_key": "G+mYjBFpIXI6wWxMGWN90OOJXOxLwDXAGMIJd3diSmk=" }, "signed_pre_key_pair": { "private_key": "iPZ8OvbTNghtTGzp85RlMVFXXmb+ZPXm8t3oAHraUkM=", "public_key": "vj5UITryFzcV+4Om3MXS0gFJs852LMpEZrMd4rhu0Qo=" }, "signed_pre_key_signature": "KgYZ7ue/nHQfIZuHrqL8dcS/7kv0gqeE+8aNpC3VNs4=", "one_time_pre_key_pairs": [ { "private_key": "0C3oMHwnnVL7eXEQ9cUp/5LhMy74Nnpy7fz15JbtNWs=", "public_key": "ZYIA8Sx38/DeIESENuL3tZwglYHVMgDO3Cv9DOdCp3U=" }, { "private_key": "kCX7IKTKteUpAmLiZ5WWh2RCXa1SW7AOGjDhQZg5n10=", "public_key": "ZCEn1qqSYBo2eQmKijKdLqnd2K6X0yP4SRLEu22xJnY=" }, { "private_key": "wB0RAdNl2SBqKmgpJnvAnII03k953nZNBY18zpjQiE0=", "public_key": "KzDr5L308u3WkKBX89yn3FlI1VnCCmT/tdNM+s6BEG0=" }, { "private_key": "UHW/CapBgjhVm9EOYkxUvjw8GksEQfPxdrR5QZcTS1Q=", "public_key": "cmN6CS3RHw1R+L0qaFTIQbbV/enLB7i6vieTBgEXagQ=" }, { "private_key": "kJctVVsMO3+kRwN8+JMnKn6tGeiC1BkFUJV13tiO0HE=", "public_key": "BNucY7d4LeC7PlhLvmS5obbq54dlphgJtMDN5hOlbws=" }, { "private_key": "yHH0m6DNkm3ReoYlGDN8g2UO0wVBmu299ISTXhxOh00=", "public_key": "qaT9wzqJcLOGy+1TUKgnPGmEOe4zwh+2yXHQmJoDkw8=" }, { "private_key": "4DVKNEdO9s6IQtE5Pam6pDzQahZVNAcC1hyWAgDOu1c=", "public_key": "W4gCafsvi3ZoSmEz6qHTTPKbbCtc5+h2VEcq0nmxb30=" }, { "private_key": "8N9wx8Ny4C+NrCFMwTBLKiN6aCcv3d20Xnx1fTnXyHI=", "public_key": "nTMv+nkrfU76S9ym71MtGclWse0Ya9+fgLYqKNb6yS8=" }, { "private_key": "6MXQwuem3t9cx+LD5rFUZQG9S5g4wWA3ThWN1o6/WFE=", "public_key": "jiMqTO7VAKHN/D4uQvCidv4/BZVDcfsEkJWn8jVyQi8=" }, { "private_key": "sHJmmTQG/OMsBT7qzULhrQKSyECzvVXl+FSeGTlJYEo=", "public_key": "SShCloFXDmuAOfK0ecqN4FEe22zkJnBqIwbstoCmfE0=" } ] }, "friends": [] } -
Add Friends:
-
Click "Add Friend" in Client A.
-
Enter the User ID (User UUID) of Client B.
-
Note: The user ID can be seen in the console log after successful login or obtained during code debugging. In real applications, users are typically searched by username; this project simplifies it by adding via ID.
-
(Note: The current version implements automatic friend request acceptance logic).
-
-
Send Messages:
chate2e/: Core source packageclient/: Client logic (UI, network communication, business logic)server/: Server logic (Flask App, SocketIO handling)crypto/: Encryption module (Signal protocol implementation, cryptographic primitives wrapper)model/: Data models (messages, users, key bundles)
chat_data/: Client local data storage directory (auto-generated)start_server.py: Server startup scriptstart_client.py: Client startup script
MIT License