Skip to content

emretuncer256/securechat

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

12 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ” SecureChat β€” End-to-End Encrypted Chat Application

Computer Networks Course Project A real-time, browser-based chat application featuring hybrid RSA-2048 / AES-256-CBC end-to-end encryption. The server operates as a cryptographically blind relay β€” it never sees, logs, or processes message content or session keys in plaintext.

Python FastAPI License


✨ Features

  • Hybrid E2EE Encryption β€” RSA-2048 for key exchange, AES-256-CBC for message encryption, all using the browser's native Web Crypto API (no external crypto libraries)
  • Blind Relay Architecture β€” The server routes encrypted payloads without ever accessing plaintext content
  • Ephemeral Media (Voice & Photo) β€” Send end-to-end encrypted photos and voice recordings with real-time animated audio waveforms
  • Real-time WebSocket Communication β€” Instant message delivery with automatic reconnection and exponential backoff
  • Private & Group Messaging β€” 1-to-1 direct messages and multi-user chat rooms with per-room encryption keys
  • Zero Persistent Message Storage β€” Messages are strictly ephemeral; only user credentials are stored in SQLite
  • Premium Modern UI β€” A stunning landing page, glassmorphism-inspired design, dynamic CSS animations (AOS.js), and interactive UI elements
  • User Presence Tracking β€” Real-time online/offline status indicators

πŸ“Έ Screenshots & Demo

Video Demo

You can watch the demonstration of the SecureChat application below:

(Alternatively, you can view the video file directly: docs/demo.mp4)

Application Screenshots

Landing Page Landing Page

Login & Register Page Login & Register

Private Chat Private Chat

Group Chat Group Chat

Group Chat Settings Group Chat Settings

πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        CLIENT (Browser)                     β”‚
β”‚                                                             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚ crypto.jsβ”‚   β”‚ state.js β”‚   β”‚    websocket.js       β”‚   β”‚
β”‚  β”‚ RSA-2048 β”‚   β”‚ App Stateβ”‚   β”‚ WS Connection Manager β”‚   β”‚
β”‚  β”‚ AES-256  β”‚   β”‚ Auth Mgr β”‚   β”‚ Key Exchange Protocol β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  ui.js   β”‚   β”‚     index.html + style.css           β”‚   β”‚
β”‚  β”‚ Renderer β”‚   β”‚  Tailwind CSS + Glassmorphism UI     β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                           β”‚  WebSocket (ws://)
                           β”‚  REST API (HTTP)
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     SERVER (FastAPI)                         β”‚
β”‚                                                             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚ auth.py  β”‚   β”‚ websocket_     β”‚   β”‚    state.py      β”‚  β”‚
β”‚  β”‚ JWT Auth β”‚   β”‚ handler.py     β”‚   β”‚  In-Memory State β”‚  β”‚
β”‚  β”‚ bcrypt   β”‚   β”‚ Blind Relay    β”‚   β”‚  Connections/Keysβ”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚models.py β”‚   β”‚  database.py (SQLite β€” users only)   β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ”’ Security Model

Encryption Flow

1. User logs in β†’ Browser generates RSA-2048 key pair (volatile, lost on refresh)
2. RSA public key registered on server (in-memory only)
3. User A wants to message User B:
   a. A requests B's RSA public key from server
   b. A generates a random AES-256-CBC session key
   c. A encrypts the AES key with B's RSA public key
   d. Server relays the encrypted AES key to B (blind relay)
   e. B decrypts the AES key with their RSA private key
4. Messages encrypted with AES-256-CBC:
   - Random 16-byte IV generated per message
   - IV prepended to Base64-encoded ciphertext
   - Server forwards the opaque blob without inspection

Security Guarantees

Property Implementation
Confidentiality AES-256-CBC with per-message random IV
Key Exchange RSA-2048 (OAEP + SHA-256)
Authentication JWT tokens with bcrypt password hashing
Forward Secrecy New RSA keys on every page load/reconnection
Server Blindness Server never accesses plaintext or AES keys
No Persistence Messages exist only in browser memory

πŸ“ Project Structure

ChatApp/
β”œβ”€β”€ main.py                 # FastAPI app entry point, CORS, static mount
β”œβ”€β”€ auth.py                 # REST API: register, login, user list (JWT + bcrypt)
β”œβ”€β”€ models.py               # Pydantic request/response schemas
β”œβ”€β”€ database.py             # Async SQLite operations (users table only)
β”œβ”€β”€ state.py                # In-memory state: connections, keys, rooms
β”œβ”€β”€ websocket_handler.py    # WebSocket endpoint, event routing, blind relay
β”œβ”€β”€ static/
β”‚   β”œβ”€β”€ index.html          # SPA: auth screen + chat interface
β”‚   β”œβ”€β”€ style.css           # Custom CSS: glassmorphism, animations, scrollbar
β”‚   β”œβ”€β”€ crypto.js           # Web Crypto API: RSA-2048 + AES-256-CBC
β”‚   β”œβ”€β”€ state.js            # Client-side auth & application state
β”‚   β”œβ”€β”€ websocket.js        # WebSocket manager, key exchange, messaging
β”‚   β”œβ”€β”€ ui.js               # DOM rendering, toasts, modals
β”‚   └── app.js              # Entry point / initialization
β”œβ”€β”€ pyproject.toml          # Project metadata & dependencies
└── uv.lock                 # Dependency lock file

πŸš€ Getting Started

Prerequisites

  • Python 3.14+
  • uv β€” Fast Python package manager

Installation

# Clone the repository
git clone https://github.com/emretuncer256/securechat.git
cd ChatApp

# Install dependencies (uv will create a virtual environment automatically)
uv sync

Running the Server

uv run uvicorn main:app --reload --port 8000

Open http://localhost:8000 in your browser.

Testing E2EE Messaging

  1. Open two browser windows (or one regular + one incognito)
  2. Register two different accounts (e.g., alice and bob)
  3. Log in with each account in separate windows
  4. Click on a user in the sidebar to start a private chat
  5. Messages are encrypted in the sender's browser and decrypted in the receiver's browser β€” the server never sees the plaintext

βš™οΈ Tech Stack

Layer Technology
Backend FastAPI, Uvicorn, Python 3.14
Database SQLite (via aiosqlite) β€” users only
Auth JWT (python-jose) + bcrypt
Real-time Native WebSocket (FastAPI)
Frontend Vanilla JavaScript (ES6+)
Styling Tailwind CSS (CDN) + Custom CSS
Encryption Web Crypto API (RSA-OAEP, AES-CBC)
Icons Lucide Icons
Animations AOS.js (Animate on Scroll)
Package Mgr uv

πŸ“ API Reference

REST Endpoints

Method Endpoint Description Auth
POST /api/register Create a new user account No
POST /api/login Authenticate and receive JWT No
GET /api/users List all users with online status Bearer

WebSocket Events

Event Direction Description
key_register Client β†’ Server Register RSA public key
key_request Client β†’ Server Request a user's public key
key_exchange Bidirectional Relay encrypted AES session key
message Bidirectional Relay encrypted private message
create_room Client β†’ Server Create a new chat room
invite_to_room Client β†’ Server Invite a user to a room
room_message Bidirectional Relay encrypted room message
room_key_exchange Client β†’ Server Distribute room AES keys
user_online / user_offline Server β†’ Client Presence updates
init_state Server β†’ Client Initial state on connection

⚠️ Limitations

  • Local Network Only β€” Designed for local development; no HTTPS/WSS configuration
  • No Message Persistence β€” All messages are lost when the browser tab is closed (by design)
  • Volatile Keys β€” RSA key pairs are regenerated on every page refresh
  • Single Server β€” No horizontal scaling; in-memory state is per-process

πŸ“„ License

This project is developed as part of a Computer Networks university course. Feel free to use it for educational purposes.

About

A modern, privacy-first, real-time chat application featuring hybrid RSA/AES end-to-end encryption, ephemeral media sharing, and a cryptographically blind relay architecture.

Topics

Resources

Stars

Watchers

Forks

Contributors