A full-stack, zero-tracking, privacy-first communication platform built with Node.js (Express + Socket.io), MongoDB (Mongoose), and React 18 (Tailwind CSS + Framer Motion).
GhostPing delivers ephemeral and persistent anonymous messaging without requiring phone numbers, email addresses, or passwords. Users operate entirely under collision-resistant alphanumeric PINs (XXXX-XXXX) and device-managed cryptographic keys, featuring browser-native End-to-End Encryption (E2EE), WebRTC Voice & Video Calling, and 24-Hour Ephemeral Status Updates.
- 🕵️ Zero-Credential Onboarding: Create an account with just a Display Name. No SMS verification, email collection, or password hashes.
- 🔏 Collision-Resistant 8-Character PINs: Cryptographically randomized
XXXX-XXXXPIN handles excluding ambiguous symbols (O,I,L,0,1). - 🛡️ Native End-to-End Encryption (E2EE): Powered by the browser's native Web Crypto API (SubtleCrypto) with zero external crypto dependencies:
- Key Exchange: Elliptic Curve Diffie-Hellman (ECDH) on the P-256 curve.
- Payload Cipher: Symmetric AES-GCM (256-bit) with unique 12-byte initialization vectors (IVs) per message.
- Zero-Knowledge Key Custody: Private keys reside strictly in device storage and never cross the wire.
- 🔑 12-Word Mnemonic Recovery: Secure cross-device account recovery using a 12-word recovery phrase. Encrypted server-side via AES-256-CBC with deterministic SHA-256 index hashing.
- 📞 P2P WebRTC Audio & Video Calling: Low-latency 1-on-1 voice and video calling signaled via real-time WebSocket channels with call duration logs.
- ⏳ Ephemeral 24-Hour Stories / Status Updates: WhatsApp/Signal-style media and text statuses automatically purged after 24 hours via MongoDB TTL indices and active server cleanup jobs.
- 👥 Group Chats & Communities: Create group spaces with dedicated group PINs, encrypted key envelope distribution for group members, admin controls, and group avatars.
- 🎛️ Granular Privacy Controls: Toggle between Public and Private profiles, screen and approve incoming connection requests, pause chats, assign private nicknames, and attach custom relationship tags.
- 💬 Rich Messaging Features: Real-time read receipts (
sent,delivered,read), emoji reactions, swipe-to-reply threads, message forwarding, starred messages, and double-sided message deletion (Delete for Me / Delete for Everyone). - 📷 Integrated QR Code Scanner & Generator: Scan and share PIN handles on the fly using camera-based QR scanning and instant code rendering.
- 🎨 Adaptive Multi-Theme Engine: 7 vibrant accent palettes (Emerald, Cyberpunk, Midnight, Slate Ocean, Sunset Glow, Amethyst, Sakura Blossom) plus Dark and Light modes.
GhostPing/
├── backend/
│ ├── models/
│ │ ├── ConnectionRequest.js # Pending/accepted/rejected connection requests
│ │ ├── Conversation.js # Direct & group chat schemas, encrypted key envelopes
│ │ ├── Message.js # Ciphertext storage, IVs, reactions, read status, replies
│ │ ├── Status.js # 24h ephemeral status schema with MongoDB TTL index
│ │ └── User.js # PINs, public keys, encrypted mnemonics, online state
│ ├── routes/
│ │ └── api.js # REST controllers (auth, connections, groups, messages, status)
│ ├── sockets/
│ │ └── chatSocket.js # Socket.io events, room management, WebRTC signaling
│ ├── utils/
│ │ └── cryptoMnemonic.js # Server-side AES-256-CBC mnemonic cipher & SHA-256 hasher
│ ├── deleteUsers.js # Maintenance script to purge user documents
│ ├── migrateMnemonics.js # Database migration script for legacy mnemonics
│ ├── server.js # Express initialization, MongoDB connector & scheduled purges
│ ├── package.json # Backend dependencies and runner scripts
│ └── .env # Backend environment parameters
│
├── frontend/
│ ├── public/
│ │ └── index.html # Application entry point
│ ├── src/
│ │ ├── components/
│ │ │ ├── GhostPingLayout.js # Main chat dashboard, sidebars, WebRTC calls, settings
│ │ │ └── GhostPingLogin.js # Registration, PIN login, and 12-word mnemonic recovery
│ │ ├── crypto.js # Web Crypto API ECDH P-256 & AES-GCM 256 E2EE routines
│ │ ├── storageUtils.js # Safe storage fallbacks for browser sandboxes
│ │ ├── App.js # Session state orchestrator
│ │ ├── App.css # Global layouts and animations
│ │ ├── tailwind.css # Tailwind CSS directives
│ │ └── index.js # React root renderer
│ ├── tailwind.config.js # Tailwind configuration and theme definitions
│ ├── postcss.config.js # PostCSS configuration
│ ├── package.json # Frontend React client dependencies
│ └── .env # Frontend environment configuration
│
└── README.md # Comprehensive project documentation
GhostPing is engineered with a zero-trust paradigm between the client and the central server:
[ Alice Client ] [ Bob Client ]
│ │
├──── Generate ECDH P-256 Keypair ──────────────────────────┤
│ (Private Key stays in localStorage) │
│ │
├──── Upload Public Key (JWK) ────► [ Server ] ◄────────────┤
│ (MongoDB) │
│ │ │
│◄─── Fetch Bob's Public Key ───────────┴──────────────────►│
│ │
├──── Derive Shared Secret: ECDH(Alice_Priv, Bob_Pub) ──────┤
│ -> Symmetric AES-GCM 256-bit Key │
│ │
├──── Encrypt with fresh 12-byte IV ────────────────────────┤
│ Ciphertext + IV sent to Socket.io │
│ │
└──── Receive Ciphertext + IV ──► Decrypt via Shared Key ───┘
- Key Pair Generation: Upon registration or login, the browser invokes
window.crypto.subtle.generateKeyto create an ECDH keypair using the NIST P-256 curve. - Key Agreement: When messaging a contact, the client computes a shared secret using its local private key and the recipient's public key (
deriveKey). The resulting 256-bit symmetric key is kept non-extractable in memory. - Payload Encryption: Text payloads are encrypted via AES-GCM (256-bit) using a cryptographically randomized 12-byte initialization vector (
crypto.getRandomValues(new Uint8Array(12))). Only ciphertext and the IV are dispatched to the server. - Group Chat Key Envelopes: Group chats utilize a shared group AES key encrypted individually for each participant with their respective ECDH shared key. Group members can read group messages only by decrypting their envelope.
- 12-Word Recovery: Users receive a 12-word seed phrase generated from a standard word pool at registration.
- Dual-Layer Server Security:
- The server stores the mnemonic encrypted using AES-256-CBC (
crypto.createCipheriv) with a private environment key (MNEMONIC_ENCRYPTION_KEY). - A deterministic SHA-256 hash of the normalized phrase (
recoveryMnemonicHash) is indexed for constant-time lookup during account recovery without exposing plaintext passphrases.
- The server stores the mnemonic encrypted using AES-256-CBC (
- Status posts carry a MongoDB TTL expiration index (
expires: 86400) configured to automatically remove records after 24 hours. - A recurring cron interval in
server.jsexecutes every 30 minutes to ensure any orphaned media entries older than 24 hours are cleanly purged.
- Node.js (v18.x or higher)
- npm (v9.x or higher)
- MongoDB (Local instance running on
mongodb://127.0.0.1:27017or a MongoDB Atlas URI)
-
Navigate to the
backend/directory:cd backend -
Install backend dependencies:
npm install
-
Configure environment variables in
backend/.env:PORT=5000 MONGO_URI=mongodb://127.0.0.1:27017/anonymous_chat MNEMONIC_ENCRYPTION_KEY=6b78d2fb6435c24b9a8cf6a928e1c69e2c69e2f9d8f8a8b8c8d8e8f808182838
💡 Tip: Generate a secure 64-character hexadecimal key in Node.js:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" -
Start the backend development server (with nodemon):
npm run dev
The server initializes on
http://localhost:5000with WebSocket listeners mounted.
-
Open a new terminal and navigate to the
frontend/directory:cd frontend -
Install frontend dependencies:
npm install
-
Configure environment variables in
frontend/.env:REACT_APP_BACKEND_URL=http://localhost:5000 PORT=3001
-
Start the React development client:
npm start
The React interface launches automatically at
http://localhost:3001.
All API routes are prefixed under /api.
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/users/register |
Register a new user with displayName. Returns assigned PIN and 12-word recovery mnemonic. |
POST |
/api/users/login-pin |
Direct login with an existing pin. |
POST |
/api/users/recover |
Recover account and retrieve assigned PIN using the 12-word mnemonic. |
PUT |
/api/users/:pin |
Update profile attributes (displayName, profilePhoto). |
GET |
/api/users/:pin/status |
Retrieve a user's current connection status and lastSeen timestamp. |
GET |
/api/users/:pin/public-key |
Fetch the public ECDH JWK key for a specific user PIN. |
PUT |
/api/users/:pin/public-key |
Publish or update a user's ECDH public key and encrypted private key backup. |
PUT |
/api/users/:pin/privacy |
Toggle user profile visibility (isPrivate: true | false). |
DELETE |
/api/users/:pin/delete-account |
Permanently delete account, connections, messages, and active sessions. |
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/users/connect |
Initiate a direct chat or submit a connection request if the target is private. |
GET |
/api/users/:pin/connection-requests |
Retrieve pending incoming connection requests. |
POST |
/api/users/connection-requests/:id/respond |
Accept or reject an incoming connection request (action: 'accept' | 'reject'). |
GET |
/api/users/:pin/connection-requests/rejected |
Retrieve rejected connection request history. |
DELETE |
/api/users/connection-requests/:id |
Dismiss or remove a connection request record. |
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/users/:pin/conversations |
Retrieve all direct and group conversations for a user. |
POST |
/api/groups/create |
Create a new community group chat with a generated group PIN. |
POST |
/api/groups/join |
Join an existing group space using the group PIN. |
GET |
/api/groups/:conversationId/info |
Fetch group metadata, member roster, and public keys. |
PUT |
/api/groups/:conversationId/rename |
Update the group name (Admin only). |
PUT |
/api/groups/:conversationId/photo |
Update the group avatar image. |
DELETE |
/api/groups/:conversationId/members/:memberPin |
Remove a member or leave a group. |
GET |
/api/groups/:conversationId/my-key/:pin |
Retrieve participant's encrypted group key envelope. |
PUT |
/api/groups/:conversationId/set-member-key |
Upload an encrypted group key envelope for a newly joined member. |
PUT |
/api/conversations/:id/nickname |
Set a local alias/nickname for a specific connection. |
PUT |
/api/conversations/:id/contact-info |
Update shared relationship tags or private notes. |
PUT |
/api/conversations/:id/pause |
Pause/unpause message reception for a conversation. |
DELETE |
/api/users/:pin/conversations/:id |
Remove a conversation from the user's active inbox. |
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/messages/:conversationId |
Retrieve paginated message history for a conversation. |
PUT |
/api/messages/:messageId/delete-for-me |
Hide a specific message locally for the requesting user PIN. |
PUT |
/api/messages/:messageId/star |
Star or unstar a message. |
PUT |
/api/messages/bulk-star |
Bulk star or unstar an array of message IDs. |
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/status |
Create a new text or photo status update (auto-expires in 24 hours). |
GET |
/api/status/feed/:pin |
Retrieve active 24h status stories from all connected contacts. |
GET |
/api/users/:pin/status-recipients |
Fetch list of eligible contacts and public keys for status key envelopes. |
PUT |
/api/status/:id/envelope |
Attach encrypted key envelope for a recipient. |
DELETE |
/api/status/:id |
Manually delete an active status story. |
Socket.io handles real-time data sync, typing state, read acknowledgements, and WebRTC peer signaling.
| Event | Payload | Description |
|---|---|---|
register_session |
{ pin } |
Binds the user's socket ID with their PIN and marks them online. |
join_conversation |
{ conversationId } |
Subscribes socket to a conversation room channel. |
send_message |
{ conversationId, senderPin, text, iv, encrypted, replyTo, clientMsgId } |
Broadcasts an encrypted payload to the conversation room. |
mark_read |
{ conversationId, readerPin } |
Emits read receipts for unread messages in a thread. |
react_message |
{ messageId, conversationId, pin, emoji } |
Toggles an emoji reaction on a message. |
delete_message_everyone |
{ messageId, conversationId, pin } |
Deletes a message for all participants in a room. |
notify_status_update |
{ userPin } |
Alerts connected contacts of a newly posted status story. |
request_group_key |
{ conversationId, requestorPin, requestorPublicKey } |
Prompts group admin to generate and envelope a group key. |
broadcast_group_key_provided |
{ conversationId } |
Notifies the room that a group key envelope has been provisioned. |
| Event | Payload | Description |
|---|---|---|
call_user |
{ targetPin, callerPin, callerName, type, groupId, groupName } |
Rings target peer for an audio or video call session. |
call_response |
{ callerPin, calleePin, accept, reason } |
Relays call accept or decline status to caller. |
webrtc_signal |
{ targetPin, senderPin, signal } |
Exchanges ICE candidates, SDP offers, and SDP answers. |
hangup |
{ targetPin, senderPin } |
Terminates the active peer connection. |
GhostPing includes built-in administrative scripts inside /backend:
If migrating existing databases where user recovery phrases were stored unencrypted:
node backend/migrateMnemonics.jsScans the users collection, verifies existing encryption, calculates SHA-256 search hashes, and securely updates documents.
To wipe all test accounts from the development database:
node backend/deleteUsers.jsGhostPing provides 7 pre-built theme accents configurable through the Settings panel:
| Theme Name | Accent Color | Visual Identity |
|---|---|---|
| Emerald | #00a884 |
Classic stealth messaging aesthetic |
| Cyberpunk | #ec4899 |
Neon magenta cyberpunk vibe |
| Midnight | #0d9488 |
Deep oceanic teal |
| Slate Ocean | #0ea5e9 |
Crisp modern electric sky |
| Sunset Glow | #f97316 |
Warm radiant amber |
| Amethyst | #8b5cf6 |
High-contrast neon violet |
| Sakura Blossom | #f43f5e |
Soft modern rose pink |
Includes full system synchronization for Dark Mode and Light Mode.
This project is licensed under the MIT License. Feel free to use, modify, and distribute with attribution.