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
- 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
+-------------------+
| 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 |
|---|---|---|---|
/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 tests:
go test ./...Run tests with verbose output:
go test -v ./...Test 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 testsinternal/reputation/reputation_test.go— Reputation system tests
.
├── main.go # Main entry point
├── metadata_protection.go # Filename obfuscation
├── 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
│ ├── cache/ # MessageCache + TTL, FIFO
│ ├── crypto/ # DH key exchange + HMAC auth
│ ├── onion/ # Onion routing (types, routing, control, crypto)
│ ├── pool/ # ConnectionPool + KeepalivePools (32 ch/node)
│ └── reputation/ # Reputation system with voting
├── onion/ # Onion routing interface
│ ├── init.go # Connection init, node startup
│ ├── types.go # Node interface types
│ ├── shared.go # TCP connection handling
│ ├── routing.go # Channel setup and routing
│ ├── crypto.go # Encryption (CIP, MDC)
│ └── control.go # Session control messages
├── 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