Back to Articles

Magic Wormhole: Secure File Transfer Using Password-Authenticated Cryptography

[ View on GitHub ]

Magic Wormhole: Secure File Transfer Using Password-Authenticated Cryptography

Hook

You can securely transfer gigabytes between two computers you've never configured before using nothing but a phrase like '7-guitarist-revenge'—no accounts, no SSH keys, no USB drives.

Context

The problem of ad-hoc file transfer has plagued computing since networks existed. Need to send a file to a colleague? You could email it (size limits, security concerns), set up SSH keys (configuration overhead), use a cloud service (account requirements, privacy implications), or resort to USB drives (physical proximity required). Corporate environments often lock down these options entirely. The traditional solutions all require either pre-configuration, trust in third parties to handle unencrypted data, or compromise on security.

Magic Wormhole emerged from this frustration to solve a deceptively simple question: how do two computers that have never communicated before establish a secure connection using only a short code that humans can easily speak or type? The answer lies in Password-Authenticated Key Exchange (PAKE), a cryptographic protocol that was theoretical for decades but rarely implemented in user-facing tools. By combining PAKE with thoughtful UX decisions and pragmatic networking fallbacks, Magic Wormhole created something genuinely novel—a secure file transfer tool that requires zero setup and zero pre-shared secrets beyond an ephemeral, single-use code.

Technical Insight

Data Transfer

Key Exchange

1. Generate wormhole code
2. Publish SPAKE2 message
3. User shares code
4. Retrieve SPAKE2 message
5. SPAKE2 protocol
5. SPAKE2 protocol

6a. Direct P2P connection

6b. NAT traversal

6c. Relay fallback

Encrypted data

Sender Client

Receiver Client

Rendezvous/Mailbox Server

Transit Relay Server

Code: 7-guitarist-revenge

Shared Session Key

System architecture — auto-generated

At its core, Magic Wormhole implements SPAKE2 (Simple Password-Authenticated Key Exchange), a protocol that allows two parties to derive a strong shared encryption key from a weak shared secret—in this case, a short human-readable code. The brilliance is in how it handles the fundamental tension in key exchange: the code must be short enough for humans to easily communicate, but the resulting encryption must be strong enough to protect sensitive data.

The protocol flow works in three phases. First, the sender runs wormhole send filename.zip and receives a wormhole code like 7-guitarist-revenge. This code contains a channel ID (the number) and a password component (the words). The sender's client connects to a rendezvous server (mailbox) and publishes its SPAKE2 message encrypted with this code. When the receiver runs wormhole receive 7-guitarist-revenge, their client retrieves the sender's message from the same mailbox channel, performs the SPAKE2 exchange, and both sides derive identical session keys. The beauty of SPAKE2 is that even though the mailbox server sees all messages, it cannot decrypt them or derive the session keys without knowing the complete wormhole code. An attacker would need to guess the exact code, and the wordlist is designed to provide sufficient entropy (typically 2^16 or 65,536 possibilities) while remaining memorable.

Here's what the basic sending workflow looks like:

# Simplified version of the send operation
from wormhole import wormhole

w = wormhole.create(
    appid="lothar.com/wormhole/text-or-file-xfer",
    relay_url="ws://relay.magic-wormhole.io:4000/v1"
)

# Generate and display the code
code = w.get_code()
print(f"Wormhole code is: {code}")
print("On the other computer, run: wormhole receive {code}")

# Send the file - this handles PAKE, connection negotiation, and transfer
w.send_file("document.pdf")
result = w.wait()

The receiving side is equally straightforward:

w = wormhole.create(
    appid="lothar.com/wormhole/text-or-file-xfer",
    relay_url="ws://relay.magic-wormhole.io:4000/v1"
)

# Enter the code received from sender
w.set_code("7-guitarist-revenge")

# Receive the file - PAKE happens automatically
data = w.receive_file()
with open("received_document.pdf", "wb") as f:
    f.write(data)

The second architectural insight is the connection negotiation system. Once the cryptographic handshake completes, both peers need to actually transfer data. Magic Wormhole doesn't assume anything about network topology. It simultaneously attempts multiple connection strategies: direct TCP connection (if both peers have public IPs or are on the same network), NAT traversal using techniques similar to WebRTC's ICE protocol, and finally fallback to a transit relay server that proxies encrypted data between peers. This multi-path approach is why Magic Wormhole consistently works across different network configurations—corporate firewalls, home NAT routers, cellular networks—without requiring users to understand their network topology.

The wordlist selection reveals careful security and UX thinking. The default wordlist contains 256 words chosen for phonetic distinctness (no 'bear/bare' confusion), appropriate content (no profanity), and cross-cultural pronounceability. Two words provide 2^16 combinations (65,536), which is sufficient because codes are single-use and short-lived. An attacker has perhaps a few minutes to guess a code before the transfer completes and the code expires. With rate limiting on the mailbox server, brute-forcing becomes impractical. This is fundamentally different from passwords, which must resist offline attacks and long-term guessing.

The protocol's extensibility is worth noting. The core wormhole protocol is application-agnostic—it establishes an encrypted channel, but what you send through it is flexible. The default implementation transfers files, but the same protocol can send text snippets, directory trees, or arbitrary data structures. The appid parameter namespaces different applications so a file-transfer wormhole code won't accidentally connect to a text-transfer client. This has enabled a small ecosystem of compatible implementations in Go (wormhole-william), Rust, and even web-based clients, all interoperating because the protocol is well-specified and transport-independent.

Gotcha

The synchronous nature is Magic Wormhole's most significant limitation. Both sender and receiver must be online simultaneously, actively running the command, and the receiver must obtain the code from the sender through some out-of-band channel (verbal communication, chat message, etc.). If you walk away from your terminal mid-transfer, or if the receiver takes 30 minutes to type in the code, the connection will fail. There's no 'upload now, download later' model like traditional cloud storage. This makes it poorly suited for time-shifted workflows or automated systems where human interaction to exchange codes isn't feasible.

The dependency on centralized infrastructure is another concern. While the data transfer itself is end-to-end encrypted and the mailbox server cannot read your files, the rendezvous and relay servers are centralized points of failure and metadata leakage. If the public mailbox server goes down, wormhole transfers break (though you can self-host). The servers see IP addresses, connection timing, and transfer sizes—metadata that could be sensitive in adversarial contexts. For users with strict threat models (journalists, activists), this metadata exposure might be unacceptable. You can run your own relay infrastructure, but that defeats the zero-configuration appeal. There's also the trust question: you're trusting that the public infrastructure isn't malicious and hasn't been modified to weaken the PAKE implementation, though the code is open source and auditable.

Verdict

Use Magic Wormhole if you need to transfer files between devices without pre-configured trust relationships—perfect for sending files to colleagues across organizations, moving data between your personal machines when you're away from cloud sync, or helping less-technical family members receive files without walking them through account creation. It excels in scenarios where security matters but setup time matters more. Skip it if you need asynchronous transfers where sender and receiver aren't online simultaneously, require completely offline/air-gapped operation without any server dependencies, or need to automate transfers in scripts without human code exchange. For repeated transfers between the same machines, traditional tools like rsync or Syncthing with one-time setup provide better ergonomics. Magic Wormhole's sweet spot is the intersection of 'needs to be secure' and 'needs to happen right now without preparation.'

// ADD TO YOUR README
[![Featured on Starlog](https://starlog.is/api/badge/developer-tools/magic-wormhole-magic-wormhole.svg)](https://starlog.is/api/badge-click/developer-tools/magic-wormhole-magic-wormhole)