From 7253dbe611fa15af474c72811d6e4289c985c674 Mon Sep 17 00:00:00 2001 From: Striven <sg.striven@cutecat.club> Date: Fri, 03 Apr 2026 19:09:17 +0000 Subject: [PATCH] Update PRUDP docs --- 04_rendezvous/04_prudp_protocol.md | 128 ++++++++++++++++++++++++++++++++++++++---- 1 files changed, 114 insertions(+), 14 deletions(-) diff --git a/04_rendezvous/04_prudp_protocol.md b/04_rendezvous/04_prudp_protocol.md index 1700c4a..d23076e 100644 --- a/04_rendezvous/04_prudp_protocol.md +++ b/04_rendezvous/04_prudp_protocol.md @@ -1,37 +1,137 @@ # 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` - -### Packet: `CONNECT` - -This stage is used to derive a shared secret key. +This packet establishes a connection with the server. #### Client->Server Payload -| Name | Description | Type | -|------|-------------|------| -| Public Key | The client's _public key_. | [`Buffer`](03_structure.md#structure-buffer) | +| Name | Description | Type | +|----------------------|-------------|-------| +| Connection Signature | Unknown. | `u32` | #### Server->Client Payload -| Name | Description | Type | -|------|-------------|------| -| Public Key Signature | Presumably, the client's _public key_ signed by the server's _private key_. | [`Buffer`](03_structure.md#structure-buffer) | -| Public Key | The server's _public key_. | [`Buffer`](03_structure.md#structure-buffer) | +| 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 \ No newline at end of file +## 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` | \ No newline at end of file -- Gitblit v1.10.0