Peer-to-Peer Encrypted File Transfer: Technical Guide
Build peer-to-peer encrypted file transfer systems. NAT traversal, signaling servers, and end-to-end encryption implementation.
Peer-to-peer file transfer sends bytes directly between two browsers or devices without the file ever touching a server. WebRTC, standardized in RFCs 8825 through 8837, provides the transport: encrypted data channels over UDP with DTLS 1.3, NAT traversal via ICE, STUN, and TURN, and signaling over WebSocket or HTTP. Tools like Snapdrop, Wormhole.app, and Magic Wormhole prove the model works. Here's how to build it: the signaling handshake, NAT traversal pitfalls, encryption layering, and what you gain or lose compared to cloud-relay transfer services.
Why P2P for File Transfer
The appeal is simple: no server stores your file, no bandwidth bill for the transfer service, and the sender's upload IS the recipient's download with no intermediate copy. For a 10 GB transfer between two users on the same gigabit LAN, P2P can finish in 80 seconds while a cloud relay would upload to a distant server and download again, doubling the bandwidth usage and latency. Privacy is also a selling point, the file bytes exist only on sender and recipient devices. The tradeoffs: both parties must be online simultaneously, NAT traversal fails occasionally, and the connection is as fast as the slower participant's upload link.
WebRTC Data Channels as the Transport
WebRTC started as a video/audio protocol but RTCDataChannel gives arbitrary binary message transport with either reliable ordered (like TCP) or unreliable unordered (like UDP) delivery. Under the hood, data channels run over SCTP over DTLS 1.3 over UDP. The DTLS layer provides confidentiality and authenticated integrity via AES-128-GCM or ChaCha20-Poly1305, negotiated during the handshake. For file transfer, create a reliable ordered channel, chunk the file into 16 KB or 64 KB messages (Chrome has historically limited message size to 256 KB), and send them sequentially with flow control via the buffered amount threshold.
The Signaling Server Role
WebRTC needs a signaling server to exchange connection info (SDP offers and answers, ICE candidates) between peers. The signaling server doesn't relay file bytes, just ~5 KB of connection metadata. A WebSocket-based signaling service in Node.js, Python, or Go handles this in a few hundred lines of code. Firebase Realtime Database, Supabase Realtime, and Pusher all work as signaling backends. The signaling server sees who's talking to whom and when, but never the file contents. Most P2P file transfer services run their signaling free because the bandwidth is trivial.
NAT Traversal: STUN, TURN, and ICE
Most devices sit behind NAT, making direct IP connections impossible. ICE (Interactive Connectivity Establishment, RFC 8445) tries multiple connection paths. STUN (RFC 8489) lets a peer discover its public IP and port via a public STUN server; Google runs stun.l.google.com free. If both peers have reasonable NATs (full-cone or restricted-cone), direct UDP connection works, perhaps 70 percent of attempts. For symmetric NATs, corporate firewalls, and CGNAT, TURN (RFC 8656) relays traffic through a server. TURN servers are expensive because they carry the actual file bytes. Self-hosted coturn, twilio.com/stun, or Cloudflare Calls provide options. Expect 10 to 30 percent of P2P transfers to fall back to TURN in the wild.
Encryption Layering on Top of DTLS
DTLS already encrypts WebRTC data, so additional application-layer encryption is belt-and-suspenders. The DTLS handshake authenticates peer certificates, but WebRTC typically uses self-signed certificates that don't verify identity, they verify the connection is to the same peer that signed the SDP. Application-layer encryption with AES-256-GCM and a shared secret derived from the signaling rendezvous adds identity assurance. Magic Wormhole's SPAKE2 PAKE (Password-Authenticated Key Exchange) derives a strong key from a short human-readable phrase, so even a compromised signaling server can't decrypt.
Chunking Strategy for P2P File Transfer
WebRTC data channels have a message size limit (256 KB in most browsers, with fragmentation of larger messages working but unreliable). Chunk files at 16 KB to 64 KB per message for compatibility. Track buffered amount via bufferedAmount and bufferedAmountLowThreshold to implement backpressure, pause sending when buffer exceeds 1 MB, resume when it drops below 256 KB. For integrity, hash each chunk with SHA-256 and include the hash in a manifest sent first. The receiver reassembles, verifies hashes, and writes to disk via the File System Access API or a Blob download.
Mobile and Cross-Device Considerations
Desktop-to-desktop P2P works well. Mobile-to-desktop introduces complications: mobile browsers enforce aggressive tab suspension, so the sender must keep the browser tab in the foreground. iOS Safari's data channel implementation has historically been less reliable than Chromium. Background uploads on mobile require app-backed implementations (Snapdrop Relay, ShareDrop). Battery impact matters too, sustained WebRTC sessions drain batteries faster than HTTPS downloads. For mobile-to-mobile transfers on the same Wi-Fi, AirDrop (iOS/macOS) and Nearby Share (Android) outperform browser P2P by using direct device protocols.
Peer Discovery Without Central Accounts
How do two strangers connect without an account-based system? Several patterns work. A short code like Magic Wormhole's "4-truck-roger" serves as both rendezvous address and password; the signaling server maps codes to sessions. QR codes encoding a session URL work for in-person transfers. NFC tap-to-connect on Android connects via proximity. For larger networks, a DHT like BitTorrent's Mainline DHT can bootstrap peer discovery without a central server, but DHT lookups take seconds and don't suit casual file sharing.
Security Threats Specific to P2P
P2P introduces threats cloud relays don't have. IP address disclosure: direct connections reveal each peer's public IP to the other, potentially doxxing users in privacy-sensitive contexts (whistleblowing, activism). Some P2P services force TURN relay to hide IPs at the cost of performance. Malware distribution is harder to moderate because the service operator never sees file contents. Denial-of-service via connection exhaustion on the signaling server needs rate limiting. For extra-sensitive transfers, a Tor onion service can front the signaling to hide both IPs at heavy latency cost.
Performance Reality Check
P2P speed is bounded by the slower peer's upload bandwidth and the round-trip latency. On residential connections, upload caps are often 20 to 50 Mbps even when download is gigabit. A 10 GB P2P transfer from a 20 Mbps home upload to a gigabit recipient takes 68 minutes minimum. Cloud relay with a fast uplink and CDN-backed download can beat that by uploading once to a well-connected server. P2P wins for same-LAN transfers (gigabit or faster), sensitive data where no server-side copy is acceptable, and cost optimization when bandwidth bills would be painful.
When Cloud Relay Still Wins
For async transfers where sender and recipient aren't online simultaneously, P2P fails entirely, there's no peer to receive. For large transfers that exceed the session window (mobile browser tabs close, laptops sleep), cloud relay's "upload and share a link" model is simply more practical. For one-to-many distribution, a single upload plus CDN fanout beats running N simultaneous P2P sessions. HexaTransfer uses the cloud relay model with client-side AES-256-GCM encryption, getting most of the privacy benefit of P2P with much better async and multi-recipient support.
Try it at hexatransfer.com — free, no account, 10 GB max.
Send large files securely with end-to-end encryption
Transfer files up to 10 GB for free with end-to-end encryption. No account required. Your files are encrypted in your browser before upload — no one else can read them.
Send a file