| | |
| | | # RendezVous: PRUDP Protocol |
| | | |
| | | PRUDP probably stands for: "**P**rotected **R**eliable **U**ser **D**atagram **P**rotocol", as it is designed for adding connections, reliability, encryption and compression to UDP. To do this, it adds [connections](#connections), [ordering](#ordering), [fragmentation](#fragmentation) and [checksums](#checksums). |
| | | PRUDP probably stands for **P**rotected **R**eliable **U**ser **D**atagram **P**rotocol, as it is designed for adding reliability, encryption and compression to UDP. To do this, it adds [connections](#connections), [acknowledgements](#acknowledgements), [ordering](#ordering), [fragmentation](#fragmentation), [compression](#compression), [encryption](#encryption) and [checksums](#checksums). |
| | | |
| | | ## Packets |
| | | |
| | | ### Base Packet |
| | | **Every** packet, sent by both the client and the server, has the following base information: |
| | | |
| | | | Name | Description | Type | |
| | | |------------------|-----------------------------------------------------------------------------------------------------------------------|-----------------------------------------------| |
| | | | Source | The [virtual stream](#connections) that the packet is being sent from. | [`Stream`](#structure-stream) | |
| | | | Destination | The [virtual stream](#connections) that the packet is being sent to. | [`Stream`](#structure-stream) | |
| | | | Type and Flags | Type of the packet, and flags indicating how the client should treat this packet. | [`Type and Flags`](#structure-type-and-flags) | |
| | | | Session ID | Unknown. | `u8` | |
| | | | Packet Signature | Unknown. | `u32` | |
| | | | Sequence ID | A strictly monotonically increasing integer used for [acknowledgements](#acknowledgements) and [ordering](#ordering). | `u16` | |
| | | |
| | | ### Packet: `SYN` |
| | | This packet establishes a connection with the server. |
| | | |
| | | #### Client->Server Payload |
| | | | Name | Description | Type | |
| | | |----------------------|-------------|-------| |
| | | | Connection Signature | Unknown. | `u32` | |
| | | |
| | | #### Server->Client Payload |
| | | | Name | Description | Type | |
| | | |----------------------|-------------|-------| |
| | | | Connection Signature | Unknown. | `u32` | |
| | | |
| | | ### Packet: `CONNECT` |
| | | This stage is used to execute a Diffie-Hellman key exchange, and then derive a shared secret key. |
| | | |
| | | The key exchange operation is $S = d \times Q$, where $S$ is the resulting key, $d$ is the server's private key, and $Q$ is the client's public key. The resulting `y` co-ordinate of this exchange is discarded. |
| | | |
| | | The shared key, used for `DATA` packet encryption and decryption, is derived using the first `16` bytes of a `SHA1` hash on the Diffie-Hellman exchange result. |
| | | |
| | | The server may also use this stage to affirm the client's [connection signature](#connections). |
| | | |
| | | #### Client->Server Payload |
| | | | Name | Description | Type | |
| | | |----------------------|----------------------------|------------------------------------------------------| |
| | | | Connection Signature | Unknown. | `u32` | |
| | | | Public Key | The client's _public key_. | [`Public Key`](03_structure.md#structure-public-key) | |
| | | |
| | | #### Server->Client Payload |
| | | | Name | Description | Type | |
| | | |----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------| |
| | | | Connection Signature | Unknown. | `u32` | |
| | | | Public Key Signature | The server's _public key_ signed by the server's _certification private key_. | [`Buffer`](03_structure.md#structure-buffer) | |
| | | | Public Key | The server's _public key_. | [`Public Key`](03_structure.md#structure-public-key) | |
| | | | Tag | A HMAC-SHA256 signature on both the [client's key](03_structure.md#structure-public-key) and the [server's key]([client's key](03_structure.md#structure-public-key)) concatenated, signed using the Diffie-Hellman exchange result (NOT the shared key). | [`Buffer`](03_structure.md#structure-buffer) | |
| | | |
| | | ### Packet: `DATA` |
| | | The whole data is _first_ fragmented, _then_ compressed, _then_ encrypted. |
| | | |
| | | This means that the data in this packet, if fragmented, should be [decrypted first](#encryption), then [de-compressed](#compression) (if applicable), and then re-assembled. |
| | | |
| | | The **compressed payload** (before encryption) is prefixed with a single byte indicating the compression ratio. `0` means that the remaining data is **not** compressed. The client appears to only ever use `0x02` for this byte, however. |
| | | |
| | | The **fragmented payload** (before compression) is suffixed with the 2-byte **sequence id** of the data packet being sent. |
| | | |
| | | #### Client->Server, Server->Client Payload |
| | | | Name | Description | Type | |
| | | |-------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------|-------| |
| | | | Fragment ID | Used to re-assemble [fragmented](#fragmentation) data packets, starting from `1` (if multiple fragments exist), and ending in `0` to indicate a final fragment. | `u32` | |
| | | | ... | Encrypted and compressed data | `any` | |
| | | |
| | | ### Packet: `DISCONNECT` |
| | | ### Packet: `PING` |
| | | |
| | | ## Connections |
| | | |
| | | |
| | | ## Acknowledgements |
| | | |
| | | ## Ordering |
| | | |
| | | ## Compression |
| | | |
| | | ## Encryption |
| | | |
| | | ## Fragmentation |
| | | |
| | | ## Checksums |
| | | |
| | | ## Packet Format |
| | | ## Packet Format |
| | | |
| | | ## Structures |
| | | |
| | | ### Structure: `Public Key` |
| | | An **uncompressed** `SEC1` formatted key, **without** the preceeding compression tag (`0x04`). |
| | | |
| | | ### Structure: `Stream` |
| | | A packed `u8` containing |
| | | | Name | Description | Type | |
| | | |------|---------------------------------------------------|------------------------------------| |
| | | | Port | The [virtual port](#connections) for this stream. | `u4` | |
| | | | Port | The type of stream that the connection is using. | [`Stream Type`](#enum-stream-type) | |
| | | |
| | | ### Structure: `Type and Flags` |
| | | A packed `u8` containing |
| | | | Name | Description | Type | |
| | | |-----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------| |
| | | | Type | The type of packet that is being sent. | [`Packet Type`](#enum-packet-type) | |
| | | | Ack | This packet is an [acknowledgement](#acknowledgements) packet for a reliable packet sent by the recipient. | `bool` | |
| | | | Reliable | This packet **must** be acknowledged by the recipient, or it will be re-sent. | `bool` | |
| | | | Need Ack | The sender is expecting an acknowledgement for this packet. | `bool` | |
| | | | Has Size | The packet contains a `u16` size following the packet header (or, for [`SYN`](#packet-syn) and [`CONNECT`](#packet-connect), after the connection signature, and for [`DATA`](#packet-data), after the fragment ID). | `bool` | |
| | | | Multi Ack | Unknown, doesn't appear to be supported, but if a packet flagged with `Need Ack` has this flag, the recipient should send an `Ack` with this flag set too. | `bool` | |
| | | |
| | | ### Enum: `Stream Type` |
| | | A `u4` containing these values: |
| | | |
| | | | Name | Value | |
| | | |-----------------------|-------| |
| | | | `RV Authentication` | `2` | |
| | | | `RV Secure` | `3` | |
| | | | `Sandbox Management` | `4` | |
| | | | `NAT` | `5` | |
| | | | `Session Discovery` | `6` | |
| | | | `Nat Echo` | `7` | |
| | | |
| | | > [!IMPORTANT] |
| | | > Hyperscape appears to exclusively use the `RV Secure` (`3`) type. |
| | | |
| | | ### Enum: `Packet Type` |
| | | A `u3` containing these values: |
| | | |
| | | | Name | Value | |
| | | |-----------------------|-------| |
| | | | [`SYN`](#packet-syn) | `0` | |
| | | | [`CONNECT`](#packet-connect) | `1` | |
| | | | [`DATA`](#packet-data) | `2` | |
| | | | [`DISCONNECT`](#packet-disconnect) | `3` | |
| | | | [`PING`](#packet-ping) | `4` | |
| | | | [`USER`](#packet-user) | `6` | |