Session Rekey
On this page
Session rekey allows mid-session symmetric key rotation to prevent sequence counter overflows and limit the cryptographic exposure window of long-lived connections.
Source Mapping
src/Nalix.SDK/Transport/Extensions/RekeyExtensions.cs— Client SDK extensionsrc/Nalix.Runtime/Handlers/SystemControlHandlers.cs— Server-side control handler
How It Works
Key Rotation Flow
sequenceDiagram
participant C as Client (SDK)
participant S as Server (Runtime)
C->>C: Derive new key: newKey = HandshakeX25519.DeriveRekeySecret(currentSecret)
C->>S: Control (Type = SESSION_REKEY, SequenceId = seq, encrypted under K_n)
C->>C: Switch session.State.Secret = newKey (K_{n+1}) and reset sequence counters
S->>S: Validate handshake, connection.Secret = HandshakeX25519.DeriveRekeySecret(connection.Secret) (K_{n+1})
S->>S: Reset TCP/UDP send+receive sequence counters
S->>C: Control (Type = SESSION_REKEY_ACK, SequenceId = seq, encrypted under K_{n+1})When to Rekey
- Sequence counter overflow: 16-bit sequence counters wrap after 65,535 frames. Rekey resets them.
- Exposure window reduction: Rotating keys limits the data encrypted under a single key.
- Long-lived sessions: Game servers, IoT connections, and persistent dashboards should rekey periodically.
Client-Side Usage
The SDK provides RekeyAsync() on TransportSession:
using Nalix.SDK.Transport;
// Rekey after every 50,000 packets or on a timer
await session.RekeyAsync();
The extension method:
- Derives the new session key (
K_{n+1}) from the current secret (K_n) using HKDF. - Sends a
Controlpacket withType = SESSION_REKEYencrypted underK_n. - Immediately switches
session.State.SecrettoK_{n+1}and resets local sequence counters so it can decrypt the server’sSESSION_REKEY_ACK(which is encrypted underK_{n+1}). - Awaits
SESSION_REKEY_ACKfrom the server (correlated bySequenceId).
Server-Side Behavior
The SystemControlHandlers.HandleSessionRekey handler:
- Confirms the handshake has been established (
connection.GetRuntimeState().HandshakeEstablished) and the control packet arrived encrypted (context.EncryptedOnWire). - Computes the next key generation:
connection.Secret = HandshakeX25519.DeriveRekeySecret(connection.Secret). - Resets TCP and (if applicable) UDP send/receive sequence counters.
- Responds with
Control(SESSION_REKEY_ACK)using the sameSequenceIdfor correlation.
Protocol Packet
| Packet | OpCode | Direction | Fields |
|---|---|---|---|
Control | SYSTEM_CONTROL | Client → Server | Type = SESSION_REKEY, SequenceId |
Control | SYSTEM_CONTROL | Server → Client | Type = SESSION_REKEY_ACK, SequenceId matches request |
Security Notes
- The control packet travels encrypted (
[PacketEncryption(true)]on connection) — it travels under the current session cipher. - Both parties derive the new key using HKDF-Expand with a static label
nalix-session/rekey. No keys are sent directly over the wire, providing perfect forward secrecy for session rekeying. - Only reliable (TCP) transport is accepted for Rekey signals.
- If the handshake has not been established, the connection is disconnected immediately.
- Sequence counter reset prevents stale or replayed frames from the previous key period from being accepted.