mirror of
https://git.numenor-labs.us/dsfx.git
synced 2025-04-29 08:10:34 +00:00
refactor(docs): add handshake docs
This commit is contained in:
parent
330fa5dd37
commit
8328cab7a6
@ -1 +1,12 @@
|
||||
# Internals
|
||||
# DSFX Internals
|
||||
|
||||
Welcome, friend! You are viewing the DSFX internal documentation. If you want to _use_
|
||||
DSFX, you don't need to read this and could head straight to our user-level docs at
|
||||
|
||||
<https://koti.casa/numenor-labs/dsfx/src/branch/main/docs>
|
||||
|
||||
If you want to learn how DSFX works inside, here's what we got:
|
||||
|
||||
- [TigerStyle](../TIGER_STYLE.md) is _the_ style guide, and more. This is the philosophy underlining
|
||||
all the code here!
|
||||
- [handshake](./handshake.md) is the protocol for establishing a secure connection between two parties.
|
||||
|
161
docs/internals/handshake.md
Normal file
161
docs/internals/handshake.md
Normal file
@ -0,0 +1,161 @@
|
||||
# Handshake Protocol Documentation
|
||||
|
||||
This document describes the handshake protocol implemented in the DSFX library. The protocol establishes a secure, authenticated channel between two parties over a network connection. It uses a combination of ephemeral Diffie–Hellman key exchange, symmetric encryption, and digital signatures to both derive a shared secret and verify the identities of the communicating parties.
|
||||
|
||||
> Note: The protocol relies on several subcomponents:
|
||||
> • The key exchange mechanisms (using ECDH with the X25519 curve and HKDF for key derivation)
|
||||
> • Encryption and decryption using AES-GCM
|
||||
> • Digital signatures with ED25519
|
||||
> • Transport framing using length-prefixed buffers
|
||||
|
||||
## Overview
|
||||
|
||||
The handshake protocol involves two roles:
|
||||
|
||||
- **Initiator (Client):** Starts the handshake, sends its ephemeral public key, performs client authentication, and verifies the server’s signature.
|
||||
- **Acceptor (Server):** Waits for the client’s initiation, sends its own ephemeral public key, verifies the client’s authentication, and responds with its signed authentication message.
|
||||
|
||||
Both parties, after successful authentication, derive an identical shared secret that is used to secure subsequent communication.
|
||||
|
||||
## Protocol Steps
|
||||
|
||||
### Step 1: Ephemeral Key Exchange
|
||||
|
||||
**Purpose:**
|
||||
Each party generates an ephemeral ECDH key pair to perform a Diffie–Hellman key exchange. This key exchange enables both parties to derive a shared symmetric key while providing forward secrecy.
|
||||
|
||||
**Actions:**
|
||||
|
||||
- **Initiator:**
|
||||
|
||||
- Generates an ephemeral ECDH key pair.
|
||||
- Exports its ephemeral public key into a length-prefixed buffer (using the `buffer.NewLenPrefixed` function).
|
||||
- Sends the ephemeral public key over the connection.
|
||||
|
||||
- **Acceptor:**
|
||||
- Waits for the client's ephemeral public key.
|
||||
- Reads and imports the client’s key from the length-prefixed payload (using `buffer.ReadLenPrefixed` and `keyexchange.ImportPublicKey`).
|
||||
- Generates its own ephemeral key pair.
|
||||
- Exports its ephemeral public key.
|
||||
- Sends its ephemeral public key (again using a length-prefixed buffer).
|
||||
|
||||
### Step 2: Shared Secret Derivation
|
||||
|
||||
**Purpose:**
|
||||
Using the exchanged ephemeral keys, both parties compute a shared secret. This shared secret is derived via ECDH and then processed with HKDF (using SHA-256) to produce a symmetric session key for message encryption.
|
||||
|
||||
**Actions:**
|
||||
|
||||
- Both parties call the `keyexchange.ComputeDHSecret()` method with their private ephemeral key and the other party’s public ephemeral key.
|
||||
- An AES-GCM ciphersuite is used in the `encryption.Encrypt()` and `encryption.Decrypt()` functions to protect subsequent authentication messages.
|
||||
|
||||
### Step 3: Authentication of Long-Term Identity
|
||||
|
||||
**Purpose:**
|
||||
To bind the ephemeral keys (used for the session) with each party’s long-term identity (represented by an ED25519 key pair), the protocol uses digital signatures. This step prevents man-in-the-middle attacks by ensuring that both parties are in possession of their respective long-term private keys.
|
||||
|
||||
**Actions (Client/Initiator):**
|
||||
|
||||
1. **Export Signing Keys:**
|
||||
|
||||
- The client exports its long-term public signing key.
|
||||
- It also exports the server’s public signing key (provided as a parameter to the handshake).
|
||||
|
||||
2. **Build Authentication Message:**
|
||||
|
||||
- A helper function (`buildMessage`) constructs an authentication message that binds the ephemeral keys:
|
||||
- First, both ephemeral public keys (client and server) are exported.
|
||||
- The message is built by concatenating these keys and appending a SHA-256 checksum of the concatenated key values.
|
||||
- Notably, the final authentication message is defined as:
|
||||
`authMessage = serverEphemeralPublicKey || SHA256(clientEphemeralPublicKey || serverEphemeralPublicKey)`
|
||||
|
||||
3. **Sign the Message:**
|
||||
|
||||
- The client signs the constructed authentication message with its long-term ED25519 private key using the `identity.Sign()` function.
|
||||
|
||||
4. **Encrypt and Send Authentication Data:**
|
||||
- The client builds a plaintext message that contains:
|
||||
- Its exported long-term public key.
|
||||
- Its signature over the authentication message.
|
||||
- This plaintext is encrypted using the derived session key (from Step 2) via AES-GCM.
|
||||
- The encrypted block is sent using a length-prefixed transmission.
|
||||
|
||||
**Actions (Server/Acceptor):**
|
||||
|
||||
1. **Receive and Decrypt Client Authentication Message:**
|
||||
|
||||
- The server reads the client’s authentication message (which was sent as a length-prefixed encrypted message).
|
||||
- It decrypts the message with the derived session key, retrieving:
|
||||
- The client’s long-term public signing key.
|
||||
- The client’s signature.
|
||||
|
||||
2. **Build the Authentication Message:**
|
||||
|
||||
- Similarly to the client side, the server constructs an authentication message with the exchanged ephemeral keys using the `buildMessage` function (note the parameter order is reversed).
|
||||
|
||||
3. **Verify the Client’s Signature:**
|
||||
|
||||
- The server verifies the client’s signature against the built authentication message using `identity.Verify()`.
|
||||
|
||||
4. **Sign and Send the Server Authentication Response:**
|
||||
- The server signs the same authentication message with its own long-term private key.
|
||||
- It then encrypts the signed message with the derived session key.
|
||||
- This encrypted signature is sent back to the client as a length-prefixed buffer.
|
||||
|
||||
### Step 4: Finalizing the Handshake
|
||||
|
||||
**Purpose:**
|
||||
Both parties confirm that the handshake is complete and that the authentication was successful.
|
||||
|
||||
**Actions:**
|
||||
|
||||
- **Acceptor (Server):** After sending its authentication response, the server waits for a final "handshake complete" message from the client.
|
||||
|
||||
- **Initiator (Client):**
|
||||
|
||||
- After verifying the server’s authentication response (by decrypting and checking the server’s signature), the client sends a final handshake completion message. This is a simple length-prefixed payload containing a one-byte flag (0x01).
|
||||
|
||||
- **Both Parties:**
|
||||
- On reception of this handshake completion message, the handshake process is finalized.
|
||||
- At this point, both sides share the same derived symmetric session key which will be used for all subsequent encrypted communication.
|
||||
|
||||
## Message Framing and Transport
|
||||
|
||||
All messages (ephemeral keys, authentication messages, handshake completion flag) are transmitted using a length-prefixed framing mechanism. The `buffer` package is responsible for:
|
||||
|
||||
- Prepending a 2-byte big-endian length prefix to each message.
|
||||
- Reading and validating the length prefix before consuming the payload.
|
||||
|
||||
This ensures that the message boundaries are clearly established over the TCP stream.
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- **Ephemeral Keys:**
|
||||
The use of ephemeral ECDH keys ensures forward secrecy; even if long-term keys are compromised later, past session keys remain secure.
|
||||
|
||||
- **Authentication Binding:**
|
||||
By signing a message that binds the ephemeral keys with the long-term identities, the protocol guarantees that the established session is authenticated. Any tampering in the handshake will cause signature verification to fail.
|
||||
|
||||
- **Encryption:**
|
||||
All sensitive handshake messages (including public keys and signatures) are encrypted with the derived symmetric key using AES-GCM. This mode provides both confidentiality and integrity.
|
||||
|
||||
- **Length Prefixing:**
|
||||
The fixed-length (2-byte) prefix before each message fragment ensures that only complete messages are processed, reducing the risk of framing errors and injection attacks.
|
||||
|
||||
## Summary of the Handshake Flow
|
||||
|
||||
1. **Initiate (Client):**
|
||||
- Generate ephemeral DH key and send it.
|
||||
2. **Accept (Server):**
|
||||
- Receive client’s ephemeral key.
|
||||
- Generate its own ephemeral key and send it.
|
||||
3. **Client Authentication:**
|
||||
- Client builds and signs an authentication message.
|
||||
- Encrypts with derived key and sends to the server.
|
||||
4. **Server Authentication:**
|
||||
- Server decrypts and verifies the client’s authentication message.
|
||||
- Signs the same authentication message and sends it back.
|
||||
5. **Handshake Completion:**
|
||||
- Client verifies server’s signature.
|
||||
- Client sends a final “handshake complete” flag.
|
||||
- Both sides now share the session key for secure communication.
|
Loading…
x
Reference in New Issue
Block a user