Skip to content

Latest commit

Β 

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ”’ Secure-Drop

Build Platform Encryption Zero Relay License

Zero-relay, end-to-end encrypted peer-to-peer file transfer β€” from any device to any device.
No cloud upload. No accounts. No file size limits imposed by a server. Files travel directly between browsers, encrypted before they leave the sender.


✨ Features

  • True P2P β€” WebRTC DataChannel transfers files device-to-device; the signaling server is only a matchmaker and never sees file content
  • AES-256-GCM encryption β€” every chunk encrypted independently before leaving the sender's machine
  • ECDH P-256 key exchange β€” ephemeral keys negotiated per session; no pre-shared secrets
  • HKDF-SHA-256 key derivation β€” raw ECDH bits stretched into a 256-bit AES key
  • SHA-256 integrity verification β€” full file hash checked on receipt
  • MITM fingerprint β€” 8-character session fingerprint both peers can read aloud to verify no interception
  • Drag & Drop + Click to browse β€” always-active file zone, ⌘O keyboard shortcut
  • QR code join β€” scan to connect a second device instantly; URL encodes the signaling server
  • Dark / Light mode β€” sci-fi dark (default) + clean light theme
  • Real-time transfer stats β€” speed (MB/s), progress bar, CPU %, memory, uptime
  • Transfer history β€” completed and failed transfers with details
  • Editable device name β€” personalise your node label
  • Platform independent β€” runs in any modern browser on Mac, Windows, Linux, iOS, Android
  • LAN mode β€” single ./start-lan.sh launches everything, zero config
  • Internet mode β€” deploy frontend to Netlify + signaling to Railway (both free)

πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        Browser  A                                β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚SignalingCβ”‚  β”‚PeerConnect β”‚  β”‚ChunkTransferβ”‚  β”‚CryptoSvc  β”‚  β”‚
β”‚  β”‚  (WS)   β”‚  β”‚ (WebRTC)   β”‚  β”‚ (DataChannelβ”‚  β”‚AES-256-GCMβ”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β”‚ WebSocket    β”‚ ICE/SDP        β”‚ Encrypted chunks (P2P)
        β–Ό              β–Ό                β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”             β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Signaling Srv β”‚             β”‚             Browser  B              β”‚
β”‚  (Python WS)  β”‚             β”‚  (same stack, receiving side)       β”‚
β”‚  matchmaker   β”‚             β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚  only β€” no    β”‚
β”‚  file data    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Data path:   File ──► Encrypt (AES-256-GCM) ──► Chunk ──► WebRTC P2P ──► Decrypt ──► File
Server path: Register ──► Exchange SDP/ICE ──► (server done, P2P begins)

πŸ› οΈ Tech Stack

Layer Technology
Frontend framework React 18 + TypeScript + Vite
Styling Tailwind CSS + inline design tokens
Fonts Space Grotesk (UI) Β· JetBrains Mono (technical values)
P2P transport WebRTC DataChannel
Signaling Python websockets (async WebSocket server)
Encryption Web Crypto API β€” ECDH P-256, HKDF-SHA-256, AES-256-GCM
QR code qrcode.react
Toasts sonner
Theme next-themes
State management useSecureDrop custom hook (no external store)
Frontend hosting Netlify (free tier)
Signaling hosting Railway (free tier) / ngrok / LAN
NAT traversal Google STUN + Open Relay TURN (free)

πŸš€ Quick Start

Option A β€” Same Wi-Fi (LAN, zero config)

# 1. Install Python deps (once)
pip3 install websockets zeroconf

# 2. Start everything
./start-lan.sh

# 3. Open on other devices
# β†’ http://192.168.X.X:8080  (printed by the script)
# β†’ Or scan the QR code inside the app

Option B β€” Internet (any device, anywhere)

# 1. Deploy signaling server to Railway
#    railway.app β†’ New Project β†’ GitHub β†’ set Root Dir = server
#    Copy your Railway URL, e.g. wss://secure-drop-xyz.railway.app

# 2. Set env var in Netlify dashboard
VITE_SIGNALING_URL=wss://secure-drop-xyz.railway.app

# 3. Deploy frontend to Netlify
#    netlify.com β†’ New site β†’ GitHub β†’ build: npm run build, publish: dist

# 4. Open your Netlify URL on any device worldwide

Development

npm install
npm run dev          # frontend at http://localhost:8080
python server/main.py  # signaling at ws://localhost:8765

πŸ“Έ Screenshots

Main Interface β€” Dark Mode

Take screenshot: open http://localhost:8080 β†’ ⌘+Shift+4

Main dark mode UI


File Selected + Peer Chosen β†’ Send Button

Drag a file into the drop zone and click a peer card to activate the Send button

File selected with peer


Active Transfer with Progress

Transfer in progress showing speed, percentage, and progress bar

Active transfer


Incoming Transfer Request Modal

The receiving device sees a modal with file info, sender fingerprint, and Accept/Reject buttons

Incoming request


QR Code Panel

Click the QR button in the header to generate a join URL β€” scan it on another device

QR connect panel


Light Mode

Toggle with the β˜€οΈ button in the header

Light mode


πŸ” Security Model

Property Implementation
Key exchange ECDH P-256 β€” ephemeral per session
Key derivation HKDF-SHA-256 (salt + "secure-drop-v1" info)
Encryption AES-256-GCM β€” per-chunk, unique 96-bit IV each chunk
Integrity SHA-256 hash of full file, verified on receipt
MITM detection 8-char hex fingerprint derived from raw ECDH shared secret β€” read aloud to verify
Server trust Signaling server sees only peer IDs + encrypted SDP; never sees keys or file data
Forward secrecy Ephemeral ECDH keys β€” compromise of one session reveals nothing about others

πŸ“ Project Structure

secure-drop/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ engine/
β”‚   β”‚   β”œβ”€β”€ SignalingClient.ts    # WebSocket connection + reconnect backoff
β”‚   β”‚   β”œβ”€β”€ PeerConnection.ts    # WebRTC offer/answer + ICE negotiation
β”‚   β”‚   β”œβ”€β”€ ChunkTransfer.ts     # File chunking, backpressure, reassembly
β”‚   β”‚   β”œβ”€β”€ CryptoService.ts     # ECDH + HKDF + AES-256-GCM + SHA-256
β”‚   β”‚   └── IntegrityVerifier.ts # SHA-256 file hash verification
β”‚   β”œβ”€β”€ hooks/
β”‚   β”‚   β”œβ”€β”€ useSecureDrop.ts     # Central app state + logic orchestrator
β”‚   β”‚   β”œβ”€β”€ useSystemMonitor.ts  # CPU / memory / network metrics
β”‚   β”‚   └── useTheme.ts          # Dark/light mode
β”‚   β”œβ”€β”€ pages/
β”‚   β”‚   └── LandingPage.tsx      # Full UI β€” all components inline
β”‚   └── lib/
β”‚       └── constants.ts         # ICE servers, chunk sizes, crypto params
β”œβ”€β”€ server/
β”‚   β”œβ”€β”€ main.py                  # LAN server (WebSocket + mDNS discovery)
β”‚   β”œβ”€β”€ cloud_main.py            # Cloud server (Railway/Fly.io)
β”‚   β”œβ”€β”€ signaling.py             # Peer registry + message relay
β”‚   └── discovery.py             # mDNS advertisement (zeroconf)
β”œβ”€β”€ start-lan.sh                 # One-command LAN launcher
β”œβ”€β”€ netlify.toml                 # Netlify deploy config
└── server/railway.toml          # Railway deploy config

Deployment and security notes

The signaling server binds to 127.0.0.1 by default and accepts localhost browser origins. LAN or internet deployments must explicitly choose a bind address and pass each trusted web origin with --origin; do not disable origin validation as a convenience.

The signaling layer relays connection metadata and encrypted-session setup messages. It does not authenticate users, prevent malicious peers from connecting, or guarantee that a peer is honest. Verify the displayed session fingerprint out of band when the threat model requires protection against an active man-in-the-middle. Use TLS (wss://) for internet deployments, apply network access controls, and keep the server dependency set current.

πŸ“„ License

MIT β€” free to use, modify, and distribute.

Why star this repository

Star Secure-Drop if private peer-to-peer file transfer, WebRTC data channels, browser cryptography, or local-first privacy tooling is useful to you. Feedback on threat models, deployment hardening, and interoperability is especially welcome.

About

Local-first peer-to-peer file exchange with WebRTC data channels and a hardened signaling server.

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages