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
punchline — Peer-to-peer encrypted messenger in Rust with Noise IK and UDP NAT hole punching | Kitploit
Tools/GitHubGitHub/michal-pielka/punchline
Encryption/Decryption ToolsNetwork SecurityPrivacyUtilities & FrameworksAuthentication
GitHubmichal-pielka/punchline

punchline

Peer-to-peer encrypted messenger in Rust with Noise IK and UDP NAT hole punching

View Repository
1924 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

punchline

End-to-end encrypted peer-to-peer chat over UDP. No accounts, no central server relaying/storing messages, no middleman. Just two peers, a direct connection, and Noise protocol encryption.

https://github.com/user-attachments/assets/939e96d3-45e3-4484-9a27-28c3a0457b05

Table of Contents

  • What It Does
  • Quick Start
  • How It Works
  • CLI Reference
  • Usage
    • Configuration
    • Managing Peers
    • Status Check
    • Server Options
    • Theming
    • Shell Completions
  • Cryptography
    • IK Handshake
    • Initiator Determination
    • Key Storage
  • Wire Protocol
    • Hole Punch Protocol
    • Transport Protocol
    • Signal Protocol
    • STUN Protocol
  • Project Structure
  • Installation
    • From crates.io
    • Building from Source
  • Running Tests
  • Tech Stack
  • License

What It Does

Two people run punchline connect <peer> on their machines. Punchline punches through their NATs, performs an encrypted handshake, and drops them into a private chat - all in a few milliseconds. The included STUN and signal servers handle discovery, then get out of the way. convo


Quick Start

root@kitploit:~
cargo build --release

Start the servers (on a machine both peers can reach), or use my public ones hosted at 64.225.107.28 (STUN: port 3478, signaling: port 8743):

root@kitploit:~
punchline-stund                  # STUN server - tells peers their public IP
punchline-signald                # Signal server - matches peers who want to talk
servers

On each peer's machine:

root@kitploit:~
# Generate your identity (X25519 keypair)
punchline keygen

# Share your public key with your peer
punchline pubkey

# Save their key
punchline peers add alice a1b2c3d4...64_hex_chars

# Connect (both peers run this, targeting each other)
punchline connect alice --stun <server>:3478 --signal <server>:8743

The TUI launches with a live connection progress view:

  1. STUN discovery - resolving your external address via punchline-stund

  2. Signal server - connecting to punchline-signald

  3. Waiting for peer - signal server matches both peers

  4. Hole punch - establishing the direct UDP path

  5. Noise handshake - encrypted key exchange

    dashboard

Once complete, you're in the chat. Type and press Enter. Press Esc to quit.


How It Works

The entire system consists of three binaries, all included in this repo:

BinaryRoleWhen used

After the initial setup, the STUN and signal servers are no longer contacted. Everything flows directly peer-to-peer.


CLI Reference

punchline

Global flags:

FlagDescription
-vIncrease log verbosity (-v = debug, -vv = trace).
-q, --quietSuppress all log output.

punchline-stund

punchline-signald


Usage

Configuration

Instead of passing --stun and --signal every time, create ~/.config/punchline/config.toml:

root@kitploit:~
stun_server = "203.0.113.10:3478"
signal_server = "203.0.113.10:8743"

Managing Peers

root@kitploit:~
punchline peers                              # list all
punchline peers add alice a1b2c3d4...        # add
punchline peers remove alice                 # remove

Aliases are stored in ~/.punchline/known_peers.toml. You can also connect with a raw 64-char hex key directly.

Status Check

root@kitploit:~
punchline status

Shows your identity, config, server reachability (sends a real STUN probe and TCP connect), and peer count.

Server Options

Both servers support -v (debug), -vv (trace), -q (quiet), --address, and --port:

root@kitploit:~
punchline-stund -v --port 3478
punchline-signald -v --port 8743

Theming

Customize the TUI via ~/.config/punchline/style.toml Styles used in the video:

root@kitploit:~
[colors]
my_text = "#ebdbb2"
peer_text = "#bdae93"
input_text = "#ebdbb2"
border = "#ebdbb2"
sidebar_key = "#ebdbb2"
sidebar_value = "#bdae93"

[padding]
chat_horizontal = 2
chat_vertical = 1

All colors are hex RGB. If the file is absent, the terminal's default colors are used.

Shell Completions

root@kitploit:~
punchline completions bash > ~/.local/share/bash-completion/completions/punchline
punchline completions zsh > ~/.zfunc/_punchline
punchline completions fish > ~/.config/fish/completions/punchline.fish

Cryptography

Full protocol name: Noise_IK_25519_ChaChaPoly_SHA256

ComponentRole
Noise IK

IK Handshake

The IK pattern means the initiator knows the responder's static public key before the handshake begins. Both peers already have each other's keys (exchanged out-of-band or via the peer registry), so no trust-on-first-use is required.

  1. Initiator -> Responder: Sends an encrypted message containing its static public key, encrypted under the responder's known key. Provides identity hiding against passive observers.
  2. Responder -> Initiator: Decrypts, verifies, and replies. Both sides transition to transport mode with shared session keys.

Initiator Determination

Punchline deterministically selects the initiator by comparing the first 8 bytes of each peer's public key as a big-endian u64. The peer with the smaller value becomes the initiator. Both sides compute this independently.

Key Storage

The identity is a 32-byte X25519 secret key at ~/.punchline/id_x25519 with Unix permissions 0600. The public key is derived on load. Key generation uses x25519-dalek with OsRng.


Wire Protocol

The first byte of each UDP packet identifies its type:

Hole Punch Protocol

Both peers execute the same algorithm simultaneously:

  1. Send PROBE (0x00) every 200ms to the peer's external address.
  2. On receiving a PROBE, switch to sending ACK (0x01).
  3. On receiving an ACK, send one final ACK and declare success.
  4. Safety timeout: 2 seconds of sending ACKs without reply assumes the peer finished.

Transport Protocol

Messages (0x02) carry Noise-encrypted UTF-8 payloads. Keepalives (0x03) are encrypted empty payloads sent every 10 seconds to maintain cipher nonce synchronization. 30 seconds without any packet triggers disconnect.

Signal Protocol

JSON over WebSocket:

root@kitploit:~
// PairRequest (client -> server)
{ "external_addr": "203.0.113.5:48291", "public_key": "a1b2...", "target_public_key": "d4e5..." }

// PairResponse (server -> client)
{ "target_external_addr": "198.51.100.7:51003", "target_public_key": "d4e5..." }

STUN Protocol

Follows RFC 5389 (simplified): binding request/response with XOR-MAPPED-ADDRESS. IPv4 only.


Project Structure

Cargo workspace with four crates:

root@kitploit:~
crates/
├── proto/      # Shared library: crypto, STUN, signal types, transport trait
├── client/     # P2P client: CLI, TUI, connection logic, peer management
├── signald/    # Signal server: WebSocket peer matching
└── stund/      # STUN server: external address discovery

Installation

From crates.io

root@kitploit:~
cargo install punchline           # TUI client
cargo install punchline-signald   # Signal server
cargo install punchline-stund     # STUN server

Building from Source

Prerequisites: Rust 2024 edition (rustc 1.85+)

root@kitploit:~
git clone https://github.com/michal-pielka/punchline.git
cd punchline
cargo build --release

Binaries are placed in target/release/:

  • punchline
  • punchline-signald
  • punchline-stund

Running Tests

root@kitploit:~
cargo test

Tests cover cryptographic operations, STUN encoding/decoding, signal protocol serialization, config parsing, peer management, style theming, and the Noise IK handshake.


Tech Stack


License

MIT - see LICENSE.

Download Tool
punchline-stund
STUN server (UDP) - responds with the client's external IP:port
During setup only
punchline-signaldSignal server (WebSocket) - matches peers and exchanges addressesDuring setup only
punchlineThe messenger itself - CLI, TUI, crypto, hole punchingAlways
CommandDescription
keygen [--force] [-i path]Generate a new X25519 identity keypair. Use --force to overwrite without prompting. Use -i to specify output path.
pubkey [-i path]Print your public key (64 hex characters). Use -i to derive from a specific key file.
connect <peer> [-i path] [--stun addr] [--signal addr]Connect to a peer by alias or raw hex key. Use -i to specify identity key. Launches the TUI.
peersList all known peers.
peers add <name> <key>Save a peer's public key under a nickname.
peers remove <name>Remove a peer by nickname.
config pathPrint the config file path.
config showShow current configuration values.
statusShow identity, config, server reachability, and peer count.
completions <shell>Generate shell completions (bash, zsh, or fish).
FlagDescription
--address <addr>Bind address (default: 0.0.0.0).
--port <port>Bind port (default: 3478).
-v / -vvDebug / trace logging.
-qQuiet mode.
FlagDescription
--address <addr>Bind address (default: 0.0.0.0).
--port <port>Bind port (default: 8743).
-v / -vvDebug / trace logging.
-qQuiet mode.
Handshake pattern - initiator knows responder's public key. Completes in 2 messages.
X25519Elliptic-curve Diffie-Hellman key exchange (RFC 7748). 128-bit security, constant-time.
ChaCha20-Poly1305AEAD cipher for message encryption (RFC 8439). Same cipher used in TLS 1.3 and WireGuard.
SHA-256Used internally by Noise for key derivation and handshake hashing.
PrefixTypePhaseDescription
0x00PROBEHole punchSent every 200ms to open NAT pinhole
0x01ACKHole punchConfirms receipt of a PROBE
(none)HandshakeHandshakeRaw Noise-encrypted handshake payload
0x02MessageTransportEncrypted chat message
0x03KeepaliveTransportEncrypted empty payload (heartbeat)
CratePurpose
snowNoise protocol framework (handshake + transport encryption)
x25519-dalekX25519 key generation and derivation
ratatuiTerminal UI framework
crosstermTerminal event handling
clapCLI argument parsing + shell completions
tungsteniteWebSocket client/server
tracingStructured logging