Handshake
Overview
Every DFMailbox instance has an ed25519 public and private key. The public key is used as an identifier for an instance while the private key is used to verify that you own the identifier.
A public key and private key look almost identical: eSBGfP+sy5rCNGL3aqv2JSpgzdgYKjLkTY6CWTHA0us=
Example
In this example, there will be two instances named A and B.
Instance A owns a.com and instance B owns b.com.
This is what should happen when a user of instance A attempts to send a message to instance B when instance A and B never met.
Ainitiates a websocket connection tob.com.Baccepts the connectionBimmediately sends ahellopacket{ "type": "hello", // If A finds that this differs from what the user inputted, // then A knows that it isn't B's preferred host // and starts the connection process again "host": "b.com", // B's public key "pubkey": "t79om1HOBhZk0oP8S2cG1OOvhrx1rxS9/wEfw9F9k9w=", "protocol": { "send_max_length": 5, "receive_max_length": 2 } }Aimmediately sends ahellopacket. The actualsend_max_lengthis found by getting the lesser of these two, so in this case it would be5. The same withreceive_max_length; in this case it is2. More information on what this option does can be found in messages.{ "type": "hello", "host": "a.com", // A's public key "pubkey": "m5J/YoL14+z5wElTmMwoq388Jn7niIud684u10pw6n4=", "protocol": { "send_max_length": 10, "receive_max_length": 2 } }BreadsA'shelloand finds that it hasn't metAbefore.Bsends ahost_challengeto verify thatAactually ownsa.com. Remember,Aknows thatBownsb.combecause it connected toBwith a url likewss://b.com/instance.{ "type": "host_challenge", // 64 character (max) url safe token to be put in // /.well-known/dfmailbox-challenge/<HERE> "token": "2_qJtJ6LNjWj3h3r3IAM7SwtHWUEYYfU-7RRR5igcdQ" }Asets their/.well-known/dfmailbox-challenge/2_qJtJ6LNjWj3h3r3IAM7SwtHWUEYYfU-7RRR5igcdQto returnB's public key. To tellBto go check the url,Aresponds tohost_challengewithhost_ready.{ "type": "host_ready", "token": "2_qJtJ6LNjWj3h3r3IAM7SwtHWUEYYfU-7RRR5igcdQ" }-
Bsends a request to/.well-known/dfmailbox-challenge/2_qJtJ6LNjWj3h3r3IAM7SwtHWUEYYfU-7RRR5igcdQand finds it's own public key.Bsends ahost_verifiedpacket to indicate it's trust ofAowninga.com{ "type": "host_verified" } -
Asends aauth_challengepacket to make sure thatBreally is who they say they are. This is an example of challenge response authentication.{ "type": "auth_challenge", // A random base64 string up to 64 bytes "nonce": "DeE585tu4Pm78zvJKCi6IqCnl5mc5Y7yl5AdFPTvpJM=", "expires_at": 1767218400 } -
Bresponds toA'sauth_challengewith aauth_response{ "type": "auth_response", "nonce": "DeE585tu4Pm78zvJKCi6IqCnl5mc5Y7yl5AdFPTvpJM=", "sig": "2QNsu3Io9KIRmXdnMvfJoyl64TXX2x1HWSZiYRRBWRjHj8oGydnEiqJltFoUrBxeFZ19uUrgIyx73eUc/3oODQ==" } Achecks the signature and finds that it is correct. It responds with achallenge_verified.{ "type": "challenge_verified" }Bsends aauth_challengepacket to see ifAis who they say they are.{ "type": "auth_challenge", "nonce": "SULmMO+hWVeEG21fSHt1teyzwJ+WzclIvCb7cA6IpF4=", "expires_at": 1767218400 }Aresponds toB's challenge with aauth_response{ "type": "auth_response", "nonce": "SULmMO+hWVeEG21fSHt1teyzwJ+WzclIvCb7cA6IpF4=", "sig": "hMa24IWFDUI7lOkacfNU/SM06vUc8FCozszmRFkeT3j5vcQLpUyAWfP/UzlepUnqMoxvALZ9T9YkdlaFwc9HDA==" }Bchecks the signature and finds that it is correct. It responds with achallenge_verified.{ "type": "challenge_verified" }- Since both parties have sent a
challenge_verifiedpacket, messages can be sent.
Some notes about this example
- This series of messages usually isn't this organized and linear, the example follows a more linear form to make it less confusing.
- The
host_challengeonly needs to be done when the two instances haven't met before.
Protocols
These are the Sec-WebSocket-Protocol sub protocols that are available
- json.v1 - Communicate using JSON
- msgpack.v1 - Communicate using MessagePack