Decentralized End-to-End Encrypted Messenger
Serverless, Trustless, Attacless Private Messaging.
- โจ Features
- ๐ก๏ธ Security
- ๐ฆ Installation
- ๐ Usage
- ๐จ Themes
- ๐ฎ Fun Features
- ๐พ Session Management
- ๐ Updates
- ๐ฑ Ping on Mobile
- ๐ How It Works
- ๐ค Contributing
- ๐ License
- ๐ Acknowledgments
- End-to-end encryption with X25519 + ChaCha20-Poly1305
- Ephemeral chat sessions - new keys each session by default
- No accounts - no email, no phone, no registration
- No metadata - encrypted envelopes hide message patterns
- Memory only - Runs by default in memory-only mode without session history
- Nostr protocol - censorship-resistant relay network
- No central server - messages route through public relays
- Works offline-first - reconnects automatically
- Self-hosted option - run your own relay
- Room-based group chats
- Direct messages between peers
- Password-protected rooms
- Invite codes with QR generation
- Sound notifications with mention detection
- Exportable sessions - sessions can be saved/loaded from local storage
- @mentions with tab completion and disambiguation
- Unicode/emoji support - paste emojis directly
- Curses-based interface with split panes
- Right panel showing connection info and peer list
- Status bar with room info and shortcuts
- Mouse text selection for copy/paste
- Scrollable chat history with Page Up/Down
- Tab completion for commands, usernames, and @mentions
- Command history with Up/Down arrows
- 20+ color themes (matrix, tron, amber, etc.)
- Dice rolling with ASCII art
- Dice duels - challenge peers to dice battles
- ASCII stickers - customizable sticker packs
- Name changes broadcast to room in real-time
Ping uses a modern cryptographic stack:
| Layer | Algorithm | Purpose |
|---|---|---|
| Key Exchange | X25519 ECDH | Derive shared secrets |
| Encryption | ChaCha20-Poly1305 | Authenticated encryption |
| Key Derivation | HKDF-SHA256 | Expand shared secret |
| Nostr Identity | secp256k1 Schnorr | Sign Nostr events |
| Mode | Flag | Protection Level |
|---|---|---|
| Default | - | Encrypted envelopes + ephemeral Nostr keys |
| Hardened | --hardened |
Default + decoy traffic + timing jitter |
| Legacy | --legacy |
E2E encryption only |
- Python 3.12 or higher
- pip (Python package manager)
# Clone the repository
git clone https://github.com/attacless/ping.git
cd ping
# Install dependencies
pip install cryptography websockets certifi
# Optional: faster crypto (recommended)
pip install secp256k1
# or
pip install coincurve
# Optional: QR code generation
pip install qrcodecurl -O https://raw.githubusercontent.com/attacless/ping/main/ping.py && pip install cryptography websockets certifi && python ping.py# Clone the repository
git clone https://github.com/attacless/ping.git
cd ping
# Install pip
sudo apt install python3-pip
# Install dependencies
sudo apt install python3-cryptography python3-websockets python3-certifi
# Install optional dependencies
sudo apt install python3-coincurve python3-secp256k1
# Optional: QR code generation
sudo apt install qrcode# Install pip
sudo yum install python-pip
# Install required packages
pip install cryptography websockets certifi
# Install optional packages
pip install coincurve secp256k1
# Install optional QR code library
pip install qrcode# Install python
pkg install python
# Download
curl -O https://raw.githubusercontent.com/attacless/ping/main/ping.py
# Make file executable
chmod +x ping.py
# Export ANDROID_API_LEVEL
export ANDROID_API_LEVEL=$(getprop ro.build.version.sdk)
# Install rust
pkg install rust
# Install cryptography
pip install cryptography websockets certifi# Install dependencies
pip3 install cryptography websockets certifi
# Download
curl -O https://raw.githubusercontent.com/attacless/ping/main/ping.py
# Make file executable
chmod +x ping.py| Package | Required | Purpose |
|---|---|---|
cryptography |
โ Yes | X25519, ChaCha20-Poly1305, HKDF |
websockets |
โ Yes | Nostr relay connections |
certifi |
โ Yes | SSL certificates |
secp256k1 |
โญ Recommended | Fast Schnorr signatures |
coincurve |
๐ Alternative | Schnorr signatures |
qrcode |
๐ฑ Optional | QR invite codes |
Note: If neither
secp256k1norcoincurveis installed, Ping falls back to a pure Python implementation (slower but works everywhere).
# Start Ping (interactive mode with curses UI)
python ping.py
# Start in classic terminal mode (no curses)
python ping.py --classic
# Join a room directly
python ping.py -r myroom
# Join a password-protected room
python ping.py -r secretroom -p mypassword
# Join via invite code
python ping.py -i ping1eyJyIjoibXlyb29tIn0python ping.py [OPTIONS]
Options:
-r, --room ROOM Join a room on startup
-p, --password PASS Room password
-i, --invite CODE Join via invite code
-u, --username NAME Set your display name
-c, --color THEME Set color theme (e.g., matrix, tron)
-l, --load Load session from pingconfig.json
--persist Persistent mode (save to ~/.ping)
--legacy Legacy mode (compatible with old clients)
--hardened Hardened privacy mode
--classic Classic terminal mode (no curses UI)
--no-sound Disable sound notifications
--update Check for and install updates
-d, --debug Show debug output
-v, --version Show version
| Category | Command | Description |
|---|---|---|
| Room | /join <room> [pass] |
Join a room (with optional password) |
/leave |
Leave current room | |
/invite |
Generate invite code + QR | |
/peers |
Show connected peers with fingerprints | |
/reconnect |
Reconnect to relays | |
| Chat | /dm <user> <msg> |
Send direct message |
/name <username> |
Change display name (broadcasts to room) | |
/roll |
Roll two dice with ASCII art ๐ฒ | |
/challenge <user> |
Challenge peer to dice duel โ๏ธ | |
/accept |
Accept a dice challenge | |
/decline |
Decline a dice challenge | |
/sticker |
Show available ASCII stickers | |
/sticker <num|name> |
Send a sticker ๐จ | |
| View | /info |
Show session info |
/relays |
Show relay status | |
/clear |
Clear screen | |
| Config | /color [theme] |
Set colors (/color themes for list) |
/color <bg> <fg> |
Set custom background/foreground | |
/sound [on|off|test] |
Toggle sound notifications | |
| Session | /printsession |
Show encryption keys |
/save |
Export session to pingconfig.json | |
/save withhistory |
Export session + chat history | |
/load |
Import session from pingconfig.json | |
| Misc | /update [apply] |
Check for updates |
/wipe |
Delete all local data | |
/quit |
Exit Ping | |
/help |
Show command help |
| Shortcut | Action |
|---|---|
Ctrl+F |
Toggle side panel |
Ctrl+T |
Cycle through themes |
Page Up/Down |
Scroll chat history |
โ/โ |
Command history |
Tab |
Auto-complete commands/usernames |
Ctrl+U |
Clear input line |
Ctrl+W |
Delete word |
Ctrl+A |
Beginning of line |
Ctrl+E |
End of line |
Mention peers in messages with @username:
- Tab completion for usernames
- Sound notification when mentioned
- Fingerprint disambiguation for duplicate names:
@alice[abc12345]
Ping includes 20+ built-in color themes:
# Apply a theme
/color matrix # Green on black (hacker style)
/color tron # Cyan on black
/color amber # Yellow on black (CRT monitor)
/color ocean # Cyan on blue
# Custom colors
/color blue white # Blue background, white text
/color - lgreen # Keep background, light green text
# Show all themes
/color themes
# Reset to default
/color resetAvailable themes: default, matrix, tron, classic, amber, light, dark, ocean, sunset, grape, snow, midnight, coffee, forest, rose, slate, mono, neon, retro, vapor, nord
Roll dice with ASCII art that's broadcast to the room:
/roll
Output:
๐ฒ rolled:
โโโโโโโโโ โโโโโโโโโ
โ โ โ โ โ โ โ
โ โ โ โ โ โ
โ โ โ โ โ โ โ
โโโโโโโโโ โโโโโโโโโ
Total: [5] + [3] = 8
Challenge other peers to dice battles:
/challenge alice # Challenge alice to a duel
/accept # Accept a challenge
/decline # Decline a challenge
The winner is announced to the entire room!
Send customizable ASCII art stickers:
/sticker # Show all available stickers
/sticker 1 # Send sticker #1
/sticker smile # Send sticker by name
Stickers are loaded from pingstickers.json. Place this file in:
- Current directory (
./pingstickers.json) - Home config (
~/.ping/pingstickers.json) - Home directory (
~/pingstickers.json)
Sample sticker format:
{
"version": 1,
"stickers": [
{
"name": "smile",
"art": [
" โโโโโโโโโโโโ ",
" โ โ โ โ ",
" โ __ โ ",
" โ \\__/ โ ",
" โโโโโโโโโโโโ "
]
}
]
}By default, Ping runs in ephemeral mode - a new keyset is generated each session for maximum privacy.
# Save current user session to pingconfig.json
/save
# Save with chat history
/save withhistory
# Load user on next run
python ping.py --load# Always use the same user session (stored in ~/.ping)
python ping.py --persistThe pingconfig.json file contains your user session keys:
{
"version": 2,
"identity": {
"nostr_private_key": "base64...",
"nostr_public_key": "hex...",
"npub": "npub1...",
"encryption_private_key": "base64...",
"encryption_public_key": "base64...",
"ping_id": "abcd1234",
"created_at": 1234567890
},
"username": "cosmic-wolf-123",
"settings": {
"sound_enabled": true,
"theme": "matrix"
},
"room": {
"name": "myroom",
"password": null
},
"exported_at": 1234567890
}
โ ๏ธ Keep this file secure! Anyone with access to it can impersonate you.
Ping can update itself:
# From command line
python ping.py --update
# From within Ping
/updateAfter updating, you'll be prompted to restart automatically.
Ping works great on mobile terminal apps like Termux (Android) or a-Shell mini (iOS):
# Install on Termux
pkg install python
pip install cryptography websockets certifi
curl -O https://raw.githubusercontent.com/attacless/ping/main/ping.py
python ping.pyTip: Use
--no-soundif terminal bells are annoying on mobile. Use--classicif the curses UI doesn't work well on your terminal.
Ping uses the Nostr protocol for decentralized message relay, with end-to-end encryption ensuring only the intended recipients can read messages.
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ
โ Alice โ โ Nostr โ โ Bob โ
โ (ping.py) โโโโโโถโ Relays โโโโโโโ (ping.py) โ
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ
โ โ โ
โ 1. Key Exchange (signed, public) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโถโ
โ โ
โ 2. Encrypted Messages (E2E) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโถโ
โ (Only Alice & Bob can decrypt) โ
When Alice sends a message to Bob:
-
Create Message Payload - Alice's message is packaged with metadata: content, timestamp, username, and a unique ID.
-
ECDH Key Agreement - Alice combines her X25519 private key with Bob's public key to derive a shared secret. Bob can compute the same secret using his private key + Alice's public key.
-
Key Derivation (HKDF) - The shared secret is expanded using HKDF-SHA256 with the info string
ping-nostr-chacha20poly1305-v1to produce the encryption key. -
Message Padding - The message is padded to a fixed bucket size (256, 512, 1024, 2048, 4096, or 8192 bytes) to hide its actual length from observers.
-
Authenticated Encryption - ChaCha20-Poly1305 encrypts the padded message with a random 12-byte nonce. The Poly1305 tag ensures integrity and authenticity.
-
Create Nostr Event - The ciphertext is wrapped in a Nostr event (kind 4242) with room tag and recipient's pubkey in the tags.
-
Sign & Broadcast - Alice signs the event with her secp256k1 key (BIP-340 Schnorr) and publishes to all connected relays.
-
Relay Distribution - Nostr relays broadcast the event to all subscribers of that room tag. Relays see only ciphertext.
-
Receive & Verify - Bob receives the event, verifies the Schnorr signature, and checks the
["p"]tag matches his pubkey. -
Decrypt & Display - Bob derives the same shared secret, decrypts with ChaCha20-Poly1305, removes padding, and displays the message.
| Component | Algorithm |
|---|---|
| Key Agreement | X25519 (Curve25519 ECDH) |
| Key Derivation | HKDF-SHA256 |
| Encryption | ChaCha20-Poly1305 (AEAD) |
| Nostr Signing | BIP-340 Schnorr (secp256k1) |
| Hashing | SHA-256 |
| Transport | WebSocket (WSS/TLS) |
Plaintext โ Pad โ ChaCha20-Poly1305 โ Base64 โ JSON โ Nostr Event โ Sign โ Relay
โฒ
โ
HKDF(X25519(my_priv, their_pub))
See PROTOCOL for the complete technical specification including privacy envelope structure, event kinds, and security properties.
Contributions are welcome! Please feel free to submit issues and pull requests.
# Fork and clone
git clone https://github.com/attacless/ping.git
# Make changes
# ...
# Test
python ping.py -d # Debug mode
# Submit PRAGPLv3 License - see LICENSE for details.
- Satoshi Nakamoto
- Nostr protocol
- Attacless Angels
- Public relay operators

