How a Safety Code Proves You Are Connected to the Right Device
After a ShareDrop.org connection is established, both screens show a six-digit code. If you read them out and they match, something cryptographically meaningful has been proven: no third party sits between your devices. Here is why that works, and why “encrypted” alone would not be enough.
Encrypted to whom?
WebRTC encrypts every connection (details), but encryption only guarantees privacy with whoever is on the other end. The residual risk is a machine-in-the-middle: an attacker controlling the signaling path could try to establish one encrypted connection with the sender and another with the receiver, decrypting and re-encrypting in between. Both victims see a padlock; neither sees each other.
Fingerprints, and a code built from them
Every WebRTC endpoint has a session certificate whose fingerprint (a hash) is exchanged during negotiation and enforced by the DTLS handshake. The crucial observation: in an attacked connection, each victim negotiates with the attacker's certificate, so the fingerprint pairs on the two sides differ. A safety code exploits this asymmetry:
code = SHA-256( context ‖ sorted(fingerprint_local, fingerprint_remote) ‖ session-id )- Each device computes the code locally, from the fingerprints of the connection it actually negotiated. The server never distributes a “result” — a lying server is the very thing being tested for.
- Sorting the two fingerprints makes both honest devices produce the same input, hence the same code.
- Binding the session identifier prevents replaying a code across sessions.
- Under attack, each side hashes a different fingerprint pair → different codes. The ShareDrop.org test suite pins this behaviour with fingerprint-substitution vectors.
Why comparing must happen outside the app
If the app showed you “the other side's code” over the same possibly compromised connection, the attacker would simply relay codes. The comparison only has value over an independent channel: reading it aloud in person, over a phone call, or any medium the attacker does not control. This is the same reasoning behind Signal's safety numbers — the human is the out-of-band channel.
How ShareDrop.org presents it
- Until you confirm a match, the session is labeled identity not verified: transfers work, but the app never claims a verification that did not happen.
- If a connection is rebuilt after a network failure, new certificates mean a new code, and the verified state resets — honesty over convenience.
- Codes differ? Stop, end the session, and re-invite over a trusted channel. See troubleshooting.
What safety codes do not do
A matching code proves the endpoints hold the keys: it does not prove the person at the other endpoint is who you think, and it says nothing about what they do with the file after arrival. It closes the network-level gap; human trust remains yours to establish.
Where the six digits come from
Each browser generates its own certificate for the session and announces the certificate's SHA-256 fingerprint during setup — the a=fingerprint line in the session description. Once connected, each side holds two fingerprints: its own, and the one it received for the peer. The safety code is derived from both:
- Take the two fingerprints and put them in a fixed order (sorted), so both devices start from the same input regardless of who is sender and who is receiver.
- Hash the combined string with SHA-256.
- Take enough of the result to produce six decimal digits.
Both devices do this independently, without exchanging anything further. If both hold the same pair of fingerprints (which is the case when they are genuinely connected to each other), they compute the same six digits. If an attacker sits in the middle, there are two sessions: your browser holds your fingerprint and the attacker's, the peer's browser holds the peer's and the attacker's. Different inputs, different codes. The attacker cannot fix this, because they cannot make their certificate's fingerprint equal yours.
How strong are six digits?
There are a million possible codes. An attacker who has substituted themselves into a session cannot choose the code the two victims will see; they get whatever the maths produces, and it matches the legitimate code with probability one in a million. They get exactly one attempt per session, because a failed comparison ends the session and the next one has fresh certificates. One in a million, once, checked by a human in real time, is more than enough.
Messaging apps show much longer codes (Signal's safety numbers are sixty digits), because they verify something different: a long-term identity that must stay valid across months of messages and can be attacked offline at leisure. A per-session code compared live has none of that exposure, which is why it can be short enough to read aloud.
Comparing the code in practice
- Same room: hold the screens together. Done.
- On a call: read it out. A voice call is hard to intercept at the same moment as a data session, and the person's voice is its own authentication.
- Over chat: acceptable if the chat is one you already trust: an existing thread with the person, not a channel the invite itself came through. If an attacker controls the introduction, do not let them control the comparison too.
- Never by asking “does yours say 953180?” in the same message as the invite. Read yours; have them read theirs.
What a mismatch actually means
Three things can produce different codes, in decreasing order of likelihood:
- The connection was rebuilt. A network change or a dropped link means new certificates on reconnect, which means a new code on both sides. If the two screens now agree with each other on the new code, that is what happened.
- You are looking at different sessions. One person is still on an old screen, or connected to a different room. Both start again from a fresh invite.
- Someone is in the middle. Both sides on fresh sessions, both comparing current screens, codes still differ. End the session, do not send the file, and re-invite through a channel you trust — ideally a different network.
The order matters: reconnects are routine, and a tool that raised an alarm on every one would train people to ignore it. ShareDrop.org resets the verified state and shows the new code without drama, and leaves the judgement to the two people who can actually see both screens.
Why the app does not verify this for you
Automatic verification needs something to verify against: a stored key for the other person, which needs an identity, which needs an account. ShareDrop.org has none of those on purpose, so there is nothing to pin the peer's certificate to — every session is between two strangers as far as the protocol is concerned. The safety code replaces the missing identity with the one thing two people always have: the ability to look at each other's screen. It is a deliberate trade (no accounts, one small manual step for the transfers that warrant it), and for most transfers between people who know each other, the step takes five seconds.
The same idea elsewhere
| System | What you compare | What it verifies |
|---|---|---|
| Signal safety number | 60 digits or a QR code, per contact | A long-term identity key, once, valid for all future messages |
| WhatsApp security code | 60 digits or QR, per chat | Same design as Signal |
| SSH host key fingerprint | A hash shown on first connection | The server's identity, pinned thereafter |
| ShareDrop.org safety code | Six digits, per session | That this session's two keys belong to these two devices |
The pattern is the same everywhere: cryptography establishes a secure channel to someone, and a short human comparison establishes that the someone is who you meant. The length of the code follows from how long it must stay valid and whether it can be attacked offline, which is why a per-session code compared live can be six digits and a per-contact key for years of messages is sixty.
How this is tested
The protocol test suite plays the attacker: it substitutes one side's DTLS certificate fingerprint during connection setup (exactly what a man-in-the-middle relaying two separate encrypted sessions would produce) and asserts that the two devices now derive different safety codes. A matching code with substituted fingerprints would be a broken build; the suite makes that state unshippable. The codes are derived from both endpoints' certificate fingerprints, so neither side can compute the code alone.
Standards referenced
- RFC 8827: WebRTC Security Architecture: certificate fingerprints, and why signaling is the trust gap that out-of-band comparison closes.
- RFC 8122: Connection-Oriented Media over TLS in SDP: the
a=fingerprintattribute the codes are anchored to. - NIST FIPS 180-4: Secure Hash Standard: the hash family used for certificate fingerprints.