Handshake¶
Nalix implements an authenticated X25519-based handshake using the built-in Handshake signal packet, HandshakeHandlers on the server, and HandshakeExtensions on the SDK side.
Source Mapping¶
src/Nalix.Codec/DataFrames/SignalFrames/Handshake.cssrc/Nalix.Codec/Security/HandshakeX25519.cssrc/Nalix.Runtime/Handlers/HandshakeHandlers.cssrc/Nalix.SDK/Transport/Extensions/HandshakeExtensions.cs
1. Handshake Flow¶
The handshake consists of 4 stages managed by the Handshake packet and HandshakeHandlers.
| Stage | Description | Key Payload |
|---|---|---|
| CLIENT_HELLO | Client initiates and sends its ephemeral public key. | PublicKey, Nonce |
| SERVER_HELLO | Server responds with its key, a challenge, identity proof, and transcript hash. | PublicKey, Nonce, Proof, TranscriptHash |
| CLIENT_FINISH | Client verifies server identity and sends its final proof. | Proof, TranscriptHash |
| SERVER_FINISH | Server confirms and assigns a session token (Snowflake). | Proof, TranscriptHash, SessionToken |
2. Cryptographic Construction¶
HandshakeX25519 is the helper used to derive the master secret, transcript hash, proofs, and final session key used by the transport after a successful handshake.
Hashing Strategy (HandshakeX25519)¶
The protocol derives its master secret from:
- ephemeral-ephemeral agreement
- static-ephemeral agreement against the pinned server key
| Purpose | Label | Components |
|---|---|---|
| Master Secret | nalix-handshake/master-secret |
SharedSecret_EE, SharedSecret_SE |
| Server Proof | nalix-handshake/server-proof |
MasterSecret, TranscriptHash |
| Client Proof | nalix-handshake/client-proof |
MasterSecret, TranscriptHash |
| Server Finish | nalix-handshake/server-finish |
MasterSecret, TranscriptHash |
| Session Key | nalix-handshake/session |
MasterSecret, ClientNonce, ServerNonce, TranscriptHash |
3. Server Implementation¶
The server-side state machine is implemented in HandshakeHandlers. It tracks negotiation state through connection.Attributes, specifically ConnectionAttributes.HandshakeState during the handshake and ConnectionAttributes.HandshakeEstablished once the handshake completes.
Cryptographic Methods (HandshakeX25519)¶
ComputeMasterSecret(Bytes32, Bytes32): Combines ephemeral-ephemeral and static-ephemeral shared secrets into the master secret.ComputeServerProof(Bytes32, Bytes32): Generates the proof forSERVER_HELLO.ComputeClientProof(Bytes32, Bytes32): Generates the proof forCLIENT_FINISH.ComputeServerFinishProof(Bytes32, Bytes32): Generates the final acknowledgement proof forSERVER_FINISH.DeriveSessionKey(Bytes32, Bytes32, Bytes32, Bytes32): Derives the 32-byte session key from the shared secret, client nonce, server nonce, and transcript hash.ComposeTranscriptBuffer(Bytes32, Bytes32, Bytes32, Bytes32): Composes the raw transcript buffer from public keys and nonces. Callers should wipe the returned buffer after hashing.ComputeTranscriptHash(Bytes32, Bytes32, Bytes32, Bytes32): Computes the handshake transcript hash from public keys and nonces, securely clearing the temporary buffer.
Handling Logic¶
Upon CLIENT_FINISH verification, the handler:
- Derives the 32-byte session key.
- Sets
connection.Secretandconnection.Algorithm(ChaCha20Poly1305). - Marks the connection as established through the built-in connection attribute key.
- Persists resumable session state through
IConnectionHub.SessionStore.StoreAsync(connection)when a hub is available. - Returns a
SessionTokento the client inSERVER_FINISH.
4. Client SDK Usage¶
The Nalix.SDK provides an automated extension to perform the handshake after connection.
using Nalix.SDK.Transport;
using Nalix.SDK.Transport.Extensions;
await session.ConnectAsync("127.0.0.1", 5000);
// Executes the 4-stage X25519 flow
await session.HandshakeAsync(cancellationToken);
// Session is now transparently encrypted
await session.SendAsync(new SecurePacket());
5. Security Notes¶
- Identity Authentication: By configuring
ServerPublicKeyon the client and a server certificate path on the server, the handshake performs a key agreement that lets the client pin the server identity. Anonymous handshakes are strictly forbidden to prevent MitM attacks. - Mandatory Identity: The client must be configured with
TransportOptions.ServerPublicKeyto pin the server identity. On the server, the identity key is loaded fromcertificate.privatein the configuration directory by default, or from a custom path supplied through hosting configuration. - Structural Validation: All stages are strictly validated via
IPacketValidatableto prevent malformed packets or stage confusion attacks before any cryptography is performed. - Pooled packets: Both server replies are created through
PacketFactory<Handshake>.Acquire()insrc/Nalix.Runtime/Handlers/HandshakeHandlers.cs. - Transcript Integrity: Any modification to keys or nonces during transit will cause a
TranscriptHashmismatch, resulting in an immediateProtocolReason.CHECKSUM_FAILEDrejection. - Resume Token: The initial handshake finish sets
SessionToken = connection.ID.ToUInt64()insrc/Nalix.Runtime/Handlers/HandshakeHandlers.cs. Treat the token as resumable session state, not as a cryptographic secret by itself.