Skip to content

Danindu05/encrypted-chat-app

Repository files navigation

🔐 Chatr — Secure Realtime Messaging Platform

A security-focused 1-to-1 chat application built with Next.js, Firebase, Firestore, Tailwind CSS, and the Web Crypto API. Messages are encrypted in the browser before they are written to Firestore, and the app uses a device-based session architecture that is materially stronger than the original single-key browser chat model.


🌐 Website Features

  • 🔐 Firebase Authentication - Sign up and sign in with persistent email/password sessions.
  • 👤 Username Onboarding - Create an identity with a unique username and color-based avatar.
  • 💬 Realtime 1-to-1 Messaging - Search users, create chats instantly, and receive live updates with Firestore listeners.
  • 🛡️ Browser-Side Encryption - Encrypt message content on the client before it is stored remotely.
  • 📱 Device Security Center - Review device state, trusted contacts, recovery metadata, and local session status.
  • ✅ Safety Number Verification - Compare fingerprints manually and mark trusted contacts as verified.
  • 🚨 Key Change Warnings - Surface visible warnings when a contact device identity changes.
  • 🟢 Presence and Typing Signals - Show online status, typing indicators, and inactive chat alerts.
  • 🌗 Responsive Interface - Works across desktop and mobile with theme support.

🛡️ Security Highlights

  • 🗝️ Device-Scoped Identity Keys - Each browser creates its own identity instead of sharing one long-lived account-wide key.
  • 💾 IndexedDB Key Storage - Private device material stays in browser storage backed by IndexedDB instead of localStorage.
  • ✍️ Signed Prekeys - Remote device prekeys are signed and verified before secure session establishment.
  • 🤝 Session-Based Encryption - New chats use derived conversation session keys instead of static direct key wrapping for every message.
  • 🔄 Automatic Session Rotation - Session material rotates after message-count and age thresholds, and when remote device state changes.
  • 🧾 Ciphertext Integrity Signatures - Messages are signed so tampered ciphertext or metadata can be detected instead of silently rendered.
  • 🔍 Contact Verification - Safety numbers let users confirm identity material out of band.
  • 🚫 No Plaintext in Firestore - Firestore stores encrypted payloads and metadata, not raw message text.

🚀 Why Chatr is Different

Unlike traditional browser chat demos that rely on static encryption models, chatr introduces:

  • Device-scoped cryptographic identities
  • Signed prekey verification
  • Session-derived encryption keys
  • Automatic session rotation
  • Ciphertext integrity validation
  • Local trust verification workflows
  • Key-change detection warnings
  • IndexedDB-backed secure key persistence

This creates a significantly stronger browser-based secure messaging architecture than typical realtime Firebase chat applications.


🧠 Security Architecture

1. Device Identity

Each browser creates its own device bundle with:

  • ECDSA P-256 identity keypair
  • ECDH P-256 signed prekey
  • device metadata such as deviceId, deviceName, createdAt, and lastActive

Public device material is stored in Firestore under:

users/{uid}/devices/{deviceId}

Private device keys stay in local IndexedDB as CryptoKey objects and are never uploaded to Firebase.

2. Session Establishment

When a secure chat session is created:

  1. The sender verifies the recipient device's signed prekey signature.
  2. The sender generates an ephemeral ECDH keypair.
  3. A shared secret is derived with the recipient's signed prekey.
  4. HKDF derives a conversation session AES-GCM key.
  5. Session metadata is signed by the sender's device identity key.
  6. The session key is stored only in local IndexedDB.

Session state is written to:

chats/{chatId}/sessions/{sessionId}

3. Message Encryption

New messages are encrypted with the active conversation session key:

  • AES-GCM encrypts the plaintext
  • authenticated additional data binds chatId, sessionId, sender and recipient ids, device ids, key version, encryption version, and client timestamp
  • ciphertext metadata is signed with the sender's identity key

Firestore stores only encrypted payloads and metadata such as:

  • encryptedText
  • iv
  • signature
  • aad
  • sessionId
  • sender and recipient metadata
  • version metadata

Firestore does not store plaintext message content.

4. Session Rotation and Key Hardening

  • Continuous rotation of cryptographic session material during active encrypted conversations
  • Session renewal triggered by conversation activity, session aging, and remote device identity changes
  • Reduces long-lived key exposure across secure messaging sessions
  • Improves isolation between encrypted communication states
  • Previously rotated session material cannot decrypt newly established secure sessions
  • Strengthens forward-security characteristics compared to traditional static-key browser chat architectures.

5. Verification and Trust

For each contact, the app derives a deterministic safety number from both devices' identity public keys.

Users can:

  • compare the safety number with a contact
  • mark a contact as verified
  • see verified or unverified state in chat
  • receive warnings when a remote device key changes

Trust records are stored locally per browser in IndexedDB, not in Firestore.

6. Message Integrity

Each secure message includes a signature over ciphertext metadata. If ciphertext or bound metadata is modified, verification fails and the UI surfaces an integrity warning instead of quietly treating the message as trustworthy.


🎯 Threat Model

chatr is engineered to reduce risks associated with:

  • plaintext exposure in Firestore
  • passive database compromise revealing message bodies
  • ciphertext tampering without detection
  • over-reliance on one long-lived encryption key for future traffic
  • silent remote key replacement going unnoticed in the interface

These protections are reinforced by IndexedDB-backed private key persistence, device identities, signed prekeys, session rotation, safety-number verification, key-change detection, and ciphertext integrity checks throughout the chat flow.


🛠️ Technologies Used

  • Next.js 16 App Router
  • React 19
  • TypeScript
  • Tailwind CSS v4
  • Firebase Authentication
  • Cloud Firestore
  • Web Crypto API
  • IndexedDB
  • pnpm

🗂️ Project Structure

  • app/ - App Router routes
  • components/ - Auth, chat, settings, and shared UI
  • context/ - Auth and device/session bootstrap state
  • hooks/ - Auth access, presence, notifications, and typing state
  • lib/firebase.ts - Firebase initialization
  • lib/auth.ts - Auth flows, profile creation, and secure identity rotation
  • lib/encryption.ts - Legacy RSA compatibility helpers
  • lib/security.ts - Device identities, signed prekeys, session derivation, verification, and trust state
  • lib/secure-storage.ts - IndexedDB persistence for secure local records and keys
  • lib/chat.ts - Chat creation, secure session handling, and message decryption helpers

🗃️ Firestore Model

  • users/{uid}
  • users/{uid}/devices/{deviceId}
  • usernames/{usernameLower}
  • chats/{chatId}
  • chats/{chatId}/sessions/{sessionId}
  • messages/{chatId}/items/{messageId}
  • typing/{chatId}

🔐 Environment Setup

  1. Copy the sample environment file:
    cp .env.local.example .env.local
  2. Add your Firebase web app values to .env.local:
    NEXT_PUBLIC_FIREBASE_API_KEY=your-api-key
    NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=your-project-id.firebaseapp.com
    NEXT_PUBLIC_FIREBASE_PROJECT_ID=your-project-id
    NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=your-project-id.firebasestorage.app
    NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=your-messaging-sender-id
    NEXT_PUBLIC_FIREBASE_APP_ID=your-app-id
    NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID=your-measurement-id

🔥 Firebase Setup

  1. Create a Firebase project and register a web app.
  2. Enable Email/Password authentication in Firebase Auth.
  3. Create a Cloud Firestore database.
  4. Paste the rules from:
    firestore.rules
    
  5. Publish the Firestore rules before using the app.

💻 Local Development

  1. Clone the repository:
    git clone https://github.com/Danindu05/encrypted-chat-app.git
  2. Move into the project directory:
    cd encrypted-chat-app
  3. Install dependencies:
    pnpm install
  4. Start the development server:
    pnpm dev
  5. Open in your browser:
    http://localhost:3000
    

About

A secure realtime messaging platform with browser-side encryption, device identities, session-based cryptography, and integrity-verified communication.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors