Skip to content
This repository has been archived by the owner on Feb 18, 2021. It is now read-only.

Latest commit

 

History

History
55 lines (30 loc) · 5.53 KB

handshake.md

File metadata and controls

55 lines (30 loc) · 5.53 KB

Handshake - Mutual Exchange Creation

A handshake is one or more encrypted messages sent between two endpoints in order to validate their identity and establish mutual exchange state to use for channels. At a minimum at least one handshake message must be both sent and received in order for the session to be created, with both endpoints verifying that it is always the most current one.

Applications may send or expect more than one handshake message for additional authentication and authorization requirements beyond the basic endpoint key exchange. New handshakes are also triggered automatically for existing sessions as needed by the transport(s) in use to verify that the network paths are still valid and/or maintain any NAT mappings.

The resulting size of encrypted handshake packets vary by which Cipher Sets are used combined with the type of inner packet, typically it ranges from ~70 to ~1100 bytes.

Resend/Timeout

After a new handshake is generated and delivered it should be resent verbatim at 1 second, 3 seconds, 7 seconds, and again at 15 seconds unless there is a valid handshake response. After 30 seconds with no response the exchange should be timed out, considered invalid and all related state removed.

At any point the transport being used to deliver packets may generate a keepalive handshake request which will start this process.

Message Types

Any decrypted handshake message is identified with a "type":"..." string value, that if not included in the header must be defaulted to the type of "link". Only one unique type may exist concurrently (same at value) with any handshake process.

Known types include:

  • link - to establish or keepalive a link
  • jwt - message BODY is a JSON Web Token encoded packet
  • uri - a URI was used to generate this handshake and it is included as the "uri":"..." value.
  • tx - message BODY is a raw bitcoin transaction

Sequencing with at

All decrypted handshake messages must contain an "at":123456 with a 64 bit positive unsigned integer value to determine the newest generated handshake from either endpoint. There is no requirement for the at value to be the current time, in sync, or accurate, only that it increases on all subsequent handshakes in the future from the last highest known value.

Multiple messages as part of one handshake must all have the same at value and different types, only one message per type with the highest at is used.

The at value determines if an incoming handshake is the most current and if the recipient needs to respond. The last bit in the at must always match the order value of the sender, if they are ODD it must be a 1 (and 0 if they are EVEN) to guarantee that no two endpoints can choose the same at independently.

When an at is received that is higher than one sent, new handshake message (or messages) must be returned with that matching highest at value in order to inform the sender that their handshake is confirmed. Upon receiving and confirming a new at, any pending channel packets that may have been waiting to send may be flushed/delivered.

When first creating a handshake, the sender should make every effort to always choose a higher at than any they may have sent in the past. Most can just use local 32-bit epoch as this value, but when not available (e.g., on embedded systems) they should locally store the last sent at and always increase it.

If the maximum at value is ever reached/used the two hashnames cannot send any more subsequent handshakes and will no longer be able to communicate. In this case, either side must generate a new hashname to start over.

## Routing Token

The handshake determines the exchange's ROUTING TOKEN value, generated by SHA-256 hashing the first 16 bytes of the encrypted outer message BODY, then using the first 16 bytes of the digest output. The ROUTING TOKEN is not used cryptographically and is only a unique value to assist the two endpoints and any routing parties on mapping to a known exchange session.

Each Cipher Set must structure their messages such that the first 16 bytes of the BODY are unique and remain stable for the lifetime of the exchange, typically being the exchange's ephemeral public key bytes.

Any handshake with a different ROUTING TOKEN and a higher at of an existing exchange for the same endpoint must clear any cached handshake messages or state stored for that exchange.

Handling Multiple Messages

Immediately upon receiving a valid higher or equal at for any handshake message type, that message should be cached and replace any previous matching type with a lower at only (messages with matching at and type values must be discarded). The message should also then be grouped with any other received messages with the same at and delivered to the application to process and validate.

If an application requires multiple message types it simply waits until the sufficient types arrive and then processes/validates them. Application-invalidated handshakes must never be responded to so that the endpoint does not advertise its existence except to explicitly trusted/validated endpoints.

At any point the application may provide updated handshake message types to be sent in a new handshake process. When the transport requests an updated handshake, the last known/provided message types are updated with a new at and re-sent.