Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
NoEyes — Secure terminal chat. E2E encrypted, zero-metadata blind-forwarder server. PyNaCl XSalsa20-Poly1305 + Ed25519 + forward secrecy. Cross-platform Python. | Kitploit
Tools/GitHubGitHub/ymsniper/noeyes
Authentication & AuthorizationEncryption/Decryption ToolsNetwork SecurityCryptographyPrivacyUtilities & Frameworks
GitHubymsniper/noeyes

NoEyes

Secure terminal chat. E2E encrypted, zero-metadata blind-forwarder server. PyNaCl XSalsa20-Poly1305 + Ed25519 + forward secrecy. Cross-platform Python.

View Repository
146923 months agoReviewed by Kitploit

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

NoEyes 🔒 Secure Terminal Chat

Featured in OSINTech's OSINT Anatomy

End-to-end encrypted group chat, private messages, and file transfer in your terminal. The server is a blind forwarder: it cannot read your messages, does not know your username, does not know the room you are in, and cannot link any two messages to the same person, even if fully compromised.

See it in action

Full Showcase - 3 clients, rooms, private messages, sidebar panel

https://github.com/user-attachments/assets/d9faabfb-73bd-46dd-92b2-23f63daf5b06


install.sh - Bootstrap installer

https://github.com/user-attachments/assets/e8e0220d-cd7d-45a2-9443-9a5f20b57f12


install.py - Universal Python installer

https://github.com/user-attachments/assets/15fb383d-a02a-433e-bbd9-8ebadecf9481


Server - Guided launcher startup

https://github.com/user-attachments/assets/bca10cb1-6959-425d-96d6-fc1fbf845538


What is NoEyes?

NoEyes is a Python terminal chat tool for small trusted groups. The server never decrypts anything and never sees who you are - it only handles opaque tokens and forwards encrypted bytes.

You generate the key, share it out-of-band, and the server learns nothing about your conversations.

Useful for small trusted groups who want encrypted comms without trusting any third-party server, self-hosting a private chat with true end-to-end encryption, or anyone who wants to understand exactly what a server can and cannot see.


Features


Quick Start

Option A - Guided (recommended for beginners)

root@kitploit:~
# 1. Run the setup wizard - installs Python, pip, and dependencies automatically
python ui/setup.py

# 2. Launch NoEyes
python ui/launch.py

ui/launch.py walks you through starting a server or connecting to one.


Option B - If Python isn't installed yet

PlatformRun this first
Linux / macOS / Termux / iSHsh install/install.sh
Windowsinstall\install.bat

Both scripts install Python if missing, then hand off to setup.py automatically.


Option C - Manual

root@kitploit:~
# 1. Install dependencies
pip install cryptography PyNaCl

# 2. On the server machine — generate the access key
python noeyes.py --generate-access-key
# Prints an access code hex string — share with clients via USB

# 3. On a client machine — generate chat.key from the access code
python noeyes.py --generate-chat-key <ACCESS_CODE_HEX> --key-file ./chat.key
# Distribute chat.key to all other clients via USB. Never put it on the server.

# 4. Start the server (does NOT need the key file)
python noeyes.py --server --port 5000

# Start without bore tunnel (LAN / static IP / custom tunnel)
python noeyes.py --server --port 5000 --no-bore

# Start without adding a firewall rule (not needed when using bore tunnel)
python noeyes.py --server --port 5000 --no-firewall

# 5. Connect clients - each person needs their own identity file
python noeyes.py --connect SERVER_IP --port 5000 --username alice --key-file ./chat.key --identity-path ~/.noeyes/identity_alice.key
python noeyes.py --connect SERVER_IP --port 5000 --username bob   --key-file ./chat.key --identity-path ~/.noeyes/identity_bob.key

Important: Every user must have their own identity file. Two clients sharing the same identity file get the same inbox token and the server will reject the second one as a duplicate session. The identity file is auto-generated on first run, just pass a unique --identity-path per user.


Running on Termux (Android)

Download Termux from F-Droid (recommended): https://f-droid.org/packages/com.termux/

Keep the session alive - install tmux so NoEyes keeps running when you switch apps:

root@kitploit:~
pkg install tmux -y
tmux
python ui/launch.py
# Press Volume Down + D to detach (keeps running in background)
# tmux attach   to come back

Storage permissions - file transfer will fail without this:

root@kitploit:~
termux-setup-storage

In-Chat Commands


TUI Keyboard Shortcuts

Sidebar panel

  • Top half - ROOMS - all rooms joined this session. Active room highlighted with ▶.
  • Bottom half - USERS - everyone currently in your active room.

Each half scrolls independently. Press ^P to hide the panel for a full-width chat view.


Message Tags

Prefix any message with a !tag to color it for everyone and trigger a notification sound. Tags travel inside the encrypted payload, the server never sees them.

Examples:

root@kitploit:~
!danger server is going down in 5 minutes
!ok     deployment successful
!req    can someone review my PR?

Sounds play from sfx/ folder. Drop in .wav, .mp3, .ogg, .aiff, .flac, or .m4a files named after the tag (e.g. sfx/danger.wav). Falls back to terminal bell if not found. Use /notify off to disable all sounds.


Architecture

🗺️ Live Interactive Security Map — Visual breakdown of the full encryption architecture, threat model, and zero-metadata routing in an interactive diagram.

root@kitploit:~
┌──────────────────────────────────────────────────────────────────────┐
│  Alice ──────────────────────────────────────────── Bob              │
│    │          Encrypted payload (opaque)              │              │
│    │                      │                           │              │
│    └────────────► SERVER ─┴◄──────────────────────────┘              │
│                      │                                               │
│            Zero-metadata blind forwarder:                            │
│            routes by opaque inbox tokens only                        │
│            { "to": "3f9a1c...", "type": "privmsg" }                  │
│            forwards encrypted bytes verbatim                         │
└──────────────────────────────────────────────────────────────────────┘

WHAT THE SERVER SEES:              WHAT THE SERVER NEVER SEES:
  · Encrypted bytes it can't read    · Usernames or display names
  · Opaque inbox tokens (blake2s)    · Room names
  · Opaque room tokens (blake2s)     · Who is messaging whom
  · Frame byte length                · Message content
  · Connection timing                · File contents
                                     · Ed25519 public keys
                                     · DH key exchange values

Zero-metadata routing model

Every client computes two opaque tokens locally before connecting:

root@kitploit:~
inbox_token = blake2s(identity_vk_bytes, digest_size=16)
room_token  = blake2s((room_name + group_key_hex).encode(), digest_size=16)

The server routes all frames by these tokens only. It never stores display names, room names, or public keys. Sender identity travels inside the encrypted payload (sealed sender), not in the routing header.

Key derivation chain

root@kitploit:~
chat.key (shared secret)
    │
    ├─ BLAKE2b("general") ──► room_key["general"]   (isolated per room)
    ├─ BLAKE2b("dev")     ──► room_key["dev"]
    └─ BLAKE2b("ops")     ──► room_key["ops"]

X25519 DH (per user pair, automatic on first /msg)
    alice_ephemeral + bob_ephemeral ──► shared_secret
                                              │
                                           BLAKE2b
                                              │
                                       pairwise_key    (private messages)
                                              │
                                  BLAKE2b(transfer_id) ──► chacha20_key   (files)

Identity key derivation

root@kitploit:~
password + random_salt (32 bytes, os.urandom)
    │
    └─ BLAKE2b(password, key=salt, person="identity_v2")
              │
         derived_key  ──► encrypts Ed25519 signing key at rest

Every identity file gets a unique random salt, rainbow tables are useless.


Security Summary

Threat model

NoEyes is designed for small trusted groups. It provides strong protection against:

  • Passive network observers - all traffic is TLS + E2E encrypted
  • Compromised bore.pub relay - relay sees only encrypted bytes and connection timing
  • Compromised server machine - server is zero-knowledge, nothing useful in RAM
  • MITM on connection - TLS cert pinning + Ed25519-signed DH keys
  • Someone stealing your device - identity key is password-encrypted at rest
  • Replay attacks - MID-based per-room replay protection

Running a Server Online (bore pub)

When you start a NoEyes server at home, your machine gets a local IP. For someone outside your network to connect you would normally need to forward a port on your router, which often fails due to CGNAT or carrier-level blocking.

bore pub solves this with a secure tunnel from your machine to a public relay, giving your server an instant public address without touching your router.

bore is an open-source TCP tunnel tool by Eric Zhang (@ekzhang). When you run the NoEyes server it automatically starts:

root@kitploit:~
bore local 5000 --to bore.pub

The relay assigns a random port and prints an address like bore.pub:12345. Share that with your group:

root@kitploit:~
python noeyes.py --connect bore.pub --port 12345 --key-file ./chat.key --username alice --identity-path ~/.noeyes/identity_alice.key

Everything is still end-to-end encrypted, bore only forwards raw bytes.

Automatic reconnect across bore port changes

bore.pub assigns a random port on every server restart. Normally this would mean resharing the address with everyone each time. NoEyes handles this automatically with three recovery layers:

1. Migrate event (instant) When bore reassigns a port, the server broadcasts a signed migrate event to all connected clients with the new port number. Clients silently disconnect, update their port, and reconnect automatically. A 15-second quiet window suppresses join/leave noise so the chat screen doesn't flash.

2. Discovery service (clients who missed the migrate) If a client was offline when the port changed, it polls a free anonymous key-value service (keyvalue.immanuel.co) on every reconnect attempt. The server posts the new bore port there automatically each time bore restarts. The lookup key is derived from your group key, no account or registration needed, fully anonymous.

3. Port in auth_ok (crash recovery) If a client missed everything (server crashed, migrate broadcast never sent), the server includes the current bore port in the auth_ok handshake response. The client self-corrects on the next successful connect.

bore.pub port changes are transparent to users. Chat continues automatically within seconds, and file transfers pause and resume from where they left off.

To disable discovery (air-gapped setup or private relay):

root@kitploit:~
python noeyes.py --connect bore.pub --port 12345 --key-file ./chat.key --no-discovery

bore pub limitations

LimitationDetails
No uptime guaranteebore.pub is a volunteer service, it can go down
Port is randomEach server start gets a different port, reshare the address
Not for productionFor a permanent setup, use a VPS with --no-bore

When to use a VPS instead

For more than ~10 users, 24/7 uptime, or a stable hostname, run on a cheap VPS (Hetzner €4/mo, DigitalOcean $4/mo, Oracle Cloud free tier):

root@kitploit:~
python noeyes.py --server --port 5000 --no-bore

Firewall notes

You do not need a firewall rule when using bore tunnel. You only need one for direct connections (LAN, static IP, manual port forwarding):

root@kitploit:~
python noeyes.py --server --port 5000 --no-firewall        # bore tunnel, skip firewall rule
python noeyes.py --server --port 5000 --no-bore --no-firewall  # VPS, manage firewall separately

Key Management

root@kitploit:~
# On the SERVER machine — generate the access key (server.key)
python noeyes.py --generate-access-key
# Prints an access code — share it with clients out-of-band (USB only)

# On a CLIENT machine — generate chat.key from the access code
python noeyes.py --generate-chat-key <ACCESS_CODE_HEX> --key-file ./chat.key
# Distribute this chat.key to all other clients via USB
# NEVER put chat.key on the server machine

# Or use the guided launcher (recommended)
python ui/launch.py   # → Generate Key

# Backup your identity key
cp ~/.noeyes/identity.key /backup/identity.key

# View who you currently trust (TOFU store)
cat ~/.noeyes/tofu_pubkeys.json

Project Structure

root@kitploit:~
NoEyes/
├── noeyes.py              Entry point and CLI argument parser
├── requirements.txt       pip dependencies (just: cryptography)
│
├── core/
│   ├── encryption.py      All crypto: XSalsa20-Poly1305, ChaCha20-Poly1305, X25519, Ed25519, BLAKE2b
│   ├── ratchet.py         Sender Keys forward secrecy: SenderChain + RatchetState
│   ├── animation.py       CRT boot and ratchet activation animations with SFX
│   ├── sounds.py          Cross-platform sound playback (WAV/MP3, Linux/macOS/Windows)
│   ├── identity.py        Ed25519 keypair generation and TOFU pubkey store
│   ├── utils.py           Terminal output, ANSI colours, TUI chrome
│   └── config.py          Configuration loading and CLI parsing
│
├── network/
│   ├── server.py          Async zero-metadata blind-forwarder server
│   ├── client.py          Terminal chat client (E2E, DH, TOFU, file transfer)
│   ├── client_ratchet.py  RatchetMixin — /ratchet command flow, migration wait
│   ├── client_dh.py       X25519 DH handshake mixin
│   ├── client_send.py     Outgoing message encryption (static + ratchet paths)
│   ├── client_recv.py     Incoming frame routing and decryption
│   └── client_commands.py Input loop, command dispatch, help
│
├── ui/
│   ├── launch.py          Guided launcher, arrow-key menu UI
│   └── setup.py           Dependency wizard, auto-installs what's needed
│
├── install/
│   ├── install.sh         Bootstrap for Linux / macOS / Termux / iSH
│   ├── install.bat        Bootstrap for Windows (CMD and PowerShell)
│   ├── install.py         Cross-platform Python installer
│   └── uninstall.py       Remove all NoEyes dependencies for clean reinstall
│
├── docs/
│   ├── README.md          This file
│   └── CHANGELOG.md       Version history
│
├── update.py              Self-updater, pulls latest from GitHub
└── sfx/                   Notification sounds

Tech Stack

  • Language: Python 3.9+
  • Encryption: PyNaCl (XSalsa20-Poly1305, BLAKE2b) + cryptography (ChaCha20-Poly1305, X25519, Ed25519, TLS)
  • Networking: Raw TCP sockets with a custom length-prefixed framing protocol
  • Concurrency: threading (recv + input + sender threads per client), asyncio on the server
  • Terminal: ANSI escape codes, termios for raw keypress input

Supported Platforms


⚠️ Research & Educational Use Only - experimental project.

Download Tool
FeatureDetails
Zero-metadata serverServer never sees usernames, room names, or public keys, only opaque tokens
Sealed senderSender identity lives inside the encrypted payload, never in the routing header
Blind-forwarder serverZero decryption, server forwards encrypted blobs it cannot read
Forward secrecy/ratchet start — Sender Keys protocol, each message encrypted with a unique derived key, past messages safe even if current key leaks
Group chatPer-room XSalsa20-Poly1305 keys derived via BLAKE2b, rooms cryptographically isolated
Private messagesX25519 DH handshake on first contact, pairwise key only the two parties hold
File transferChaCha20-Poly1305 streaming, any size, low RAM usage, pause/resume across reconnects
Ed25519 identityAuto-generated signing key, all messages and files are signed
TOFUFirst-seen keys trusted; key mismatches trigger a visible security warning
Random PBKDF2 saltEach deployment gets a unique random salt, rainbow tables are useless
TLS + cert pinningTransport encrypted, server cert pinned on first contact via TOFU
Replay protectionPer-room message ID deque, replayed frames silently dropped
Split sidebar panelRooms (top) and users (bottom) always visible, each half scrolls independently
CRT boot animationFull-screen phosphor effect with sound on startup
Ratchet activation animationFull-screen CRT effect with braille gear art, glitch flicker, spotlight sweep, synced SFX, and TUI chrome transition to red
Guided launcherArrow-key menu UI, no command-line experience needed
Auto dependency installerDetects your platform, installs what's missing, asks before changing anything
CommandDescription
/helpShow all commands
/quitDisconnect and exit
/clearClear messages from screen
/usersList users in current room
/join <room>Switch to a room (warns if in active ratchet)
/leaveReturn to the general room (warns if in active ratchet)
/msg <user> <text>Send an E2E-encrypted private message
/send <user> <file>Send an encrypted file
/whoamiShow your identity fingerprint
/trust <user>Trust a user's new key after they reinstall
/notify on|offToggle notification sounds
/ratchet startPropose forward-secrecy rolling keys to all room members (all must confirm)
/ratchet invite <u>Re-invite a user to the ratchet after they rejoin (triggers full restart — no chain keys forwarded)
/proceedDuring migration wait, vote to drop an offline peer and resume
KeyAction
↑ / ↓Scroll chat up / down
PgUp / PgDnScroll chat one page
^P (Ctrl+P)Show / hide the sidebar panel
^CQuit
TagColorUse for
!ok <msg>🟢 GreenSuccess, confirmed, done
!warn <msg>🟡 YellowWarning, heads up
!danger <msg>🔴 RedCritical, urgent, emergency
!info <msg>🔵 BlueStatus update, FYI
!req <msg>🟣 PurpleRequest, needs action
!? <msg>🩵 CyanQuestion, asking for input
LayerMechanismNotes
Forward secrecy (ratchet)Sender Keys — BLAKE2b chain KDF + XSalsa20-Poly1305 per messagePer-message unique key, fast-forward for missed messages
Group chatXSalsa20-Poly1305 (PyNaCl secretbox)Per-room key via BLAKE2b
Private messagesXSalsa20-Poly1305 with X25519 pairwise keyEd25519 signed, TOFU verified
File transferChaCha20-Poly1305Per-transfer key via BLAKE2b, Ed25519 signed, pause/resume across reconnects
Sender identitySealed senderUsername + sig inside encrypted payload, never in routing header
IdentityEd25519 keypairPer-user identity file, password-encrypted with BLAKE2b + random salt
Key derivationBLAKE2b (PyNaCl)Domain-separated via personalisation parameter, no rainbow tables
Server routingOpaque blake2s tokensServer never stores usernames, room names, or public keys
TransportTLS (on by default)TOFU cert pinning, fingerprint mismatch aborts connection
DH integrityEd25519-signed DH pubkeysPrevents MITM on pairwise key exchange
Replay protectionPer-room message ID dequeReplayed frames silently dropped
DoS protectionConnection cap + join timeout + rate limitingMax 200 connections, 10s join timeout
Room isolationBLAKE2b(master_key, room_name)Cryptographically isolated per room
PlatformPackage manager used
Ubuntu / Debian / Mintapt-get
Fedora / RHEL / CentOSdnf / yum
Arch / Manjaropacman
Alpine / iSH (iOS)apk
openSUSEzypper
Void Linuxxbps-install
macOSHomebrew (auto-installed if missing)
Android (Termux)pkg
Windowswinget / Chocolatey / Scoop