MeeChat is an end to end encrypted messaging web app. This app leveraging the usage of websocket for realtime communication between two users on the chat, and asymmetric encryption using Elliptic Curve Digital Signature Algorithm.
The primary intention of this project is to apply cryptographic techniques practically within a web-based communication platform. MeeChat solves the problem of data privacy and message interception. By executing all cryptographic functions on the client side, the server operates strictly as a relay and storage mechanism for encrypted data. The server does not possess the keys required to read the messages, which prevents eavesdropping and ensures that only the designated communicating parties can access the plaintext. It also guarantees message integrity and authenticity, ensuring messages are not manipulated in transit
System Architecture and Technology Stack
- Frontend (Client): React, Vite, Tailwind CSS.
- Function: Renders the user interface in the browser and handles all cryptographic processing.
- Reasoning: Executing cryptography directly within the browser ensures that private keys are generated and stored locally, never traversing the network.
- Backend (Server): Express JS (Node.js framework).
- Function: Manages REST API requests, authentication flows, contact requests, and provides real-time WebSocket connections for message delivery.
- Reasoning: The backend acts exclusively as a stateless intermediary. It performs no encryption or decryption, neutralizing the server as a point of vulnerability for plaintext data.
- Database: MongoDB with Mongoose ODM (Object Document Mapping).
- Function: Stores application data, including user public keys, login challenges, and encrypted message payloads.
- Reasoning: Mongoose ODM provides structured schemas that simplify data validation and mapping, ensuring communication between the server and database remains consistent. MongoDB only receives data that has already been encrypted by the client.
System Flow
The flow of the program described below,
1. Registration and Key Generation
The registration process binds a user to a unique cryptographic identity.
- The user inputs a username and password into the client.
- The client utilizes PBKDF2 (Password-Based Key Derivation Function 2) to generate a cryptographic seed. PBKDF2 is a key derivation function that iteratively hashes the password to mitigate brute-force attacks. To prevent rainbow table attacks, the user's username is concatenated and used as the cryptographic salt.
- This seed generates a private key using ECC (Elliptic Curve Cryptography). ECC relies on the algebraic structure of elliptic curves over finite fields to provide high security with small key sizes. The specific curve utilized is the NIST-P256 (secp256r1) standard (even though some people said NIST-P256 is not good enough if the seed is not truly random).
- The public key is mathematically derived from the private key. The private key is saved securely in the browser's local storage, while the public key is transmitted to the database.
2. Authentication (Login)
Login relies on a cryptographic challenge-response protocol rather than transmitting a static password.
- Upon entering credentials, the client regenerates the private key using the exact PBKDF2 parameters used during registration.
- The client requests a challenge from the server. The server generates a 32-bit nonce (a random number used once) and sends it to the client.
- The client signs this nonce using their private key and returns the signature to the server.
- The server verifies the signature against the user's stored public key. If the signature is mathematically valid, the session is authenticated.
3. Messaging (Encryption and Signing)
When users communicate, the system combines asymmetric key exchange with symmetric encryption.
- Connection: The sender initiates a WebSocket connection to the server, validated via a JWT (JSON Web Token) to maintain the session state.
- Hashing and Signing: The plaintext message is hashed using the SHA3-256 algorithm. SHA-3 utilizes a Sponge Construction architecture to absorb data and squeeze out a fixed-length hash. The sender then uses ECDSA (Elliptic Curve Digital Signature Algorithm) to sign this hash with their private key, creating a digital signature to guarantee authenticity.
- Key Exchange: The client generates a shared secret using ECDH (Elliptic Curve Diffie-Hellman). ECDH allows two parties to establish a shared secret over an insecure channel. The sender derives this secret by multiplying their private key with the receiver's public key. * Encryption: The message is encrypted symmetrically using AES-GCM (Advanced Encryption Standard - Galois/Counter Mode). AES-GCM provides both confidentiality and data integrity through an Authenticated Encryption with Associated Data (AEAD) approach. The encryption utilizes the ECDH shared secret as the key and a randomly generated IV (Initialization Vector) as the seed.
- Transmission: The ciphertext, the digital signature, and the IV are transmitted to the server.
4. Server Validation and Decryption
- Server Processing: Before storing the payload, the server extracts the sender's public key from the database and verifies the digital signature. If an attacker alters the message or uses a forged key, the verification fails, and the database flags the message as "unverified". The server then routes the data to the receiver via WebSocket.
- Decryption: The receiving client reconstructs the shared secret via ECDH by multiplying their own private key with the sender's public key. Because of the properties of elliptic curves, this results in the exact same shared secret generated by the sender. The receiver uses this shared secret and the transmitted IV to decrypt the AES-GCM ciphertext back into the original plaintext message.
MeeChat's deployed app on Vercel is currently down due to free Azure server limitation. To try using the app, go to source code and build it yourself.