Decentralized P2P messaging protocol and application built with Go and libp2p. Designed for censorship resistance, metadata privacy, and traffic analysis evasion in hostile network environments.
- Overview
- Features
- Security Architecture
- Architecture
- Prerequisites
- Installation
- Configuration
- Usage
- API Reference
- Testing
- Project Structure
- Contributing
- License
28SP is a peer-to-peer distributed messaging application that implements real onion routing with message obfuscation using the OnionMsgData data structure. Built on top of libp2p, it provides three communication channels: an encrypted channel, a masking channel, and an onion channel for routing with obfuscation. The system features multi-layer encryption (mixnet), traffic analysis resistance, and a decentralized pub/sub architecture.
- Onion Routing — Real multi-hop encrypted routing through intermediate nodes
- Mixnet Encryption — Multi-layer AES-GCM encryption with differentiated keys
- P2P PubSub — Decentralized publish/subscribe via libp2p
- Binary Transfer — Upload/download files as encrypted key/value pairs
- JWT Authentication — Token-based auth for protected API endpoints
- WebSocket Support — Real-time bidirectional communication
- Reputation System — Community-driven trust escalation with voting
- mDNS Discovery — Automatic local network peer discovery
- DHT Routing — Global peer discovery via Distributed Hash Table
- Traffic Resistance — Random delays to break temporal correlation
- Web UI — Modern responsive interface with dark/light theme support
- WebRTC Relay — Browser-to-Go relay signaling with pion/webrtc and TURN fallback
- Playwright E2E Tests — End-to-end browser testing for the web client
- Hard E2EE: Data ingestion protected with symmetric AES-GCM encryption
- Mixnet Routing: Multiple encryption layers with differentiated keys to fragment packet traceability
- Identity Anonymity:
UserInfo-based data structure, eliminating all PII - Obfuscation: Native
gzippayload compression as a pre-send size obfuscation layer
- Local Discovery: mDNS for automatic local network node interconnection (Mesh)
- Global Discovery: Distributed Hash Table (DHT) for WAN peer routing, bypassing centralized blocks
- PubSub Paradigm: Decentralized publish/subscribe for efficient message propagation through thematic "tablones" (boards)
- Random Delay (
routeMessage): The routing engine injects random temporal delays in packets, breaking temporal correlation used by adversaries to identify communication patterns - Secure Access Control: JWT token integration for local API endpoint authentication without plaintext credential exposure
- Browser Client:
web/relay-client.jsuses the nativeRTCPeerConnectionAPI to connect to the Go relay. - Go Relay:
internal/api/handlers.goexposes/api/relay/signal/offerand/api/relay/turn-configfor SDP signaling and ICE configuration. - TURN Fallback: The client can fetch STUN/TURN server configuration from the relay when direct peer-to-peer connectivity fails.
+-------------------+
| User |
+---------^---------+
|
+---------v---------+
| Web UI |
| (localhost:8080) |
+---------+---------+
|
+---------v---------+
| HTTP API / WS |
| (mux.Router) |
+----+----------+---+
| |
+----------v+ +----v-----------+
| nodo | | novedades |
| (TCP P2P) | | (events) |
+-----+------+ +----------------+
|
+----------v----------+
| libp2p Network |
| (DHT + PubSub) |
+----------+----------+
|
+---------------v---------------+
| Node-1 <--> Node-2 <--> Node-N |
| (Onion Routing) |
+-------------------------------+
- Go 1.25+
- Python 3.x (for scripts)
- OpenSSL (for certificate generation)
git clone https://github.com/aratan/28SP.git
cd 28SPgo mod download# Generate RSA 2048-bit private key
openssl genrsa -out key.pem 2048
# Generate CSR
openssl req -new -key key.pem -out csr.pem -subj "/CN=localhost"
# Generate self-signed certificate (valid 365 days)
openssl x509 -req -days 365 -in csr.pem -signkey key.pem -out cert.pemOr use the Go generator:
go run generate_certs.goEdit config.yaml (see Configuration)
# Linux/macOS
go build -o nodo .
# Windows
go build -o nodo.exe .
# Termux (Android)
go build -ldflags="-checklinkname=0" -o nodo main.go./nodoWith custom config:
.\nodo.exe -config security_config.yamlSingle configuration file config.yaml at project root:
| Field | Type | Description | Default |
|---|---|---|---|
topicName |
string |
PubSub topic name | "p2p-network" |
encryptionKey |
string |
AES encryption key (32 bytes) | — |
logLevel |
string |
Log verbosity (debug, info) |
"debug" |
listenAddress |
string |
P2P listen address | "/ip4/0.0.0.0/tcp/0" |
webServerAddr |
string |
HTTP server address | ":8080" |
maxMessageSize |
int |
Max message size in MB | 4 |
retryInterval |
int |
Retry interval in ms | 2000 |
logFile |
string |
Log file path | "app.log" |
mdns.enabled |
bool |
Enable mDNS discovery | true |
mdns.serviceTag |
string |
mDNS service tag | "my-mdns-service" |
useSSL |
bool |
Enable SSL/TLS | false |
certFile |
string |
SSL certificate path | "cert.pem" |
keyFile |
string |
SSL private key path | "key.pem" |
users |
[]object |
List of {username, password} |
— |
Open http://localhost:8080 in your browser to access the web interface.
Send a message:
curl -X POST "http://localhost:8080/api/send?title=Hello&message=World&subtitle=test"Read boards (tablones):
curl http://localhost:8080/api/readTablonLogin:
curl -X POST http://localhost:8080/api/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"secret"}'Upload a file:
curl -X POST http://localhost:8080/api/sendBinary \
-F "file=@./myfile.pdf"send.py — Send/receive messages locally:
python send.pyfull-p2p-conexion.py — Establish P2P connections:
python full-p2p-conexion.py| Endpoint | Method | Description | Auth |
|---|---|---|---|
/health |
GET | Lightweight readiness probe | No |
Example:
curl http://localhost:8080/health
# {"status":"ok","nodeID":"..."}| Endpoint | Method | Description | Auth |
|---|---|---|---|
/api/login |
POST | Authenticate and receive JWT token | No |
/api/generateToken |
POST | Alias for /api/login |
No |
| Endpoint | Method | Description | Auth |
|---|---|---|---|
/api/send |
POST | Send a new message | No |
/api/recibe |
GET | Retrieve all received messages | No |
| Endpoint | Method | Description | Auth |
|---|---|---|---|
/api/createTablon |
POST | Create a new board | Yes |
/api/readTablon |
GET | List all boards | No |
/api/deleteTablon |
DELETE | Delete a board by id |
Yes |
/api/addMessage |
POST | Add message to board | No |
/api/deleteMessage |
DELETE | Delete message from board | Yes |
/api/likeMessage |
POST | Like a message | No |
| Endpoint | Method | Description | Auth |
|---|---|---|---|
/api/sendBinary |
POST | Upload a file (multipart) | No |
/api/receiveBinary |
POST | Receive binary data (JSON) | No |
| Endpoint | Method | Description | Auth |
|---|---|---|---|
/security |
GET | Security settings page | Yes |
/api/security/settings |
GET, POST | Read/update security config | Yes |
Run all Go tests:
go test ./...Run tests with verbose output:
go test -v ./...Run the relay-client Playwright tests:
npm run test:relayRun the full Playwright E2E suite (requires the dev server):
npm run server:dev # terminal 1
npm run test:e2e # terminal 2Test files:
p2p_test.go— P2P integration testsinternal/cache/message_cache_test.go— Cache testsinternal/crypto/dh_test.go— DH key exchange testsinternal/crypto/mac_test.go— HMAC testsinternal/onion/onion_test.go— Onion routing tests (key system, route selection, layered encryption)internal/reputation/reputation_test.go— Reputation system teststests/relay-client.spec.ts— Playwright tests for the WebRTC relay client
GitHub Actions workflow (.github/workflows/ci.yml):
- Go job:
go vet,go build, andgo test -raceacross Go 1.25 and 1.26. - Playwright E2E job: Builds the Go binary, starts two dev nodes on ports
8080and8081, runs the Playwright suite, and uploads reports and server logs on failure.
| Script | Description |
|---|---|
npm run test |
Run Go tests + Playwright E2E suite |
npm run test:go |
Run Go tests with race detector |
npm run test:relay |
Playwright tests for web/relay-client.js |
npm run test:e2e |
Full Playwright E2E suite |
npm run server:dev |
Start dev server on :8080 |
npm run server:node2 |
Start second dev node on :8081 |
.
├── main.go # Main entry point
├── generate_certs.go # SSL certificate generation
├── p2p_test.go # P2P integration tests
├── go.mod # Go module definition
├── go.sum # Dependency checksums
├── config.yaml # Configuration file
├── security_config.yaml # Security configuration
├── security_settings.html # Security settings UI
├── cert.pem / csr.pem / key.pem # SSL certificates
├── send.py # Python send/receive script
├── full-p2p-conexion.py # Python P2P connection script
├── internal/ # Core packages
│ ├── api/ # HTTP server + route handlers
│ │ ├── server.go # Server setup, DI, route registration
│ │ └── handlers.go # API endpoint handlers
│ ├── cache/ # MessageCache + TTL, FIFO
│ ├── crypto/ # DH key exchange + HMAC auth + RSA ops
│ ├── model/ # Message domain model
│ ├── onion/ # Onion routing (types, routing, control, crypto, init)
│ ├── p2p/ # libp2p host + GossipSub + discovery
│ │ ├── p2p.go # P2PHost, Config, NetworkAdapter
│ │ ├── discovery.go # mDNS + DHT peer discovery
│ │ └── message.go # P2P message subscription loop
│ ├── pool/ # ConnectionPool + KeepalivePools (32 ch/node)
│ ├── reputation/ # Reputation system with voting
│ └── serializer/ # Generic crypto serializer/deserializer
├── onion_keys/ # Generated PEM keys
│ ├── private_key.pem
│ └── public_key.pem
└── web/ # Web UI
├── index.html # Main HTML
├── main.js # Main JavaScript
├── file-handler.js # File upload/download handler
├── fetch-handler.js # API request handler
├── service-worker.js # Service Worker
└── *.css # Stylesheets (dark/light themes)
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the GNU General Public License v3.0 — see the LICENSE file for details.
Copyright (C) 2023 aratan — seed42.uk

