N variant - jedisct1/libhydrogen GitHub Wiki

Key exchange using the N variant

  • What the client needs to know about the server: the server's public key
  • What the server needs to know about the client: nothing

This variant is designed to anonymously send messages to a recipient using its public key.

Example

Server: generate a long-term key pair

hydro_kx_keypair server_static_kp;

hydro_kx_keygen(&server_static_kp);

Client: generate session keys and a packet with an ephemeral public key to send to the server

hydro_kx_session_keypair session_kp;

if (hydro_kx_n_1(&session_kp, packet1, NULL, server_static_kp.pk) != 0) {
  // abort
}
// Done! session_kp.tx is the key for sending data to the server,
// and session_kp.rx is the key for receiving data from the server.

Server: process the initial request from the client, and compute the session keys

hydro_kx_session_keypair session_kp;

if (hydro_kx_n_2(&session_kp, packet1, NULL, &server_static_kp) != 0) {
  // abort
}
// Done! session_kp.tx is the key for sending data to the client,
// and session_kp.rx is the key for receiving data from the client.
// The session keys are the same as those computed by the client, but swapped.

Annex: declarations

uint8_t packet1[hydro_kx_N_PACKET1BYTES];

Usage

Generating static keys

void hydro_kx_keygen(hydro_kx_keypair *static_kp);

The hydro_kx_keygen() function generates a long-term key pair.

kp->pk contains the public key (hydro_kx_PUBLICKEYBYTES bytes) and kp->sk contains the secret key (hydro_kx_SECRETKEYBYTES bytes).

The client creates a new ephemeral key for every session, providing forward secrecy for all messages sent by the client. However, if the server's secret key ever gets compromised, sessions keys can be recovered.

For that reason, and while long-term keys could be reused indefinitely, rotating them from time to time remains highly recommended.

First message (client->server)

int hydro_kx_n_1(hydro_kx_session_keypair *kp, uint8_t packet1[hydro_kx_N_PACKET1BYTES],
                 const uint8_t psk[hydro_kx_PSKBYTES],
                 const uint8_t peer_static_pk[hydro_kx_PUBLICKEYBYTES]);

The hydro_kx_n_1() function computes a key pair kp using the server's public key peer_static_pk, and builds a packet packet that has to be sent to the server. It returns 0 on success, and -1 on error.

Processing the packet received from the client (on the server)

int hydro_kx_n_2(hydro_kx_session_keypair *kp, const uint8_t packet1[hydro_kx_N_PACKET1BYTES],
                 const uint8_t psk[hydro_kx_PSKBYTES], const hydro_kx_keypair *static_kp);

The hydro_kx_n_2() function computes a key pair kp using the packet packet1 received from the client. It returns 0 on success, and -1 on error.