# Key exchange

## Example (client-side)

```c
unsigned char client_pk[crypto_kx_PUBLICKEYBYTES], client_sk[crypto_kx_SECRETKEYBYTES];
unsigned char client_rx[crypto_kx_SESSIONKEYBYTES], client_tx[crypto_kx_SESSIONKEYBYTES];

/* Generate the client's key pair */
crypto_kx_keypair(client_pk, client_sk);

/* Prerequisite after this point: the server's public key must be known by the client */

/* Compute two shared keys using the server's public key and the client's secret key.
   client_rx will be used by the client to receive data from the server,
   client_tx will be used by the client to send data to the server. */
if (crypto_kx_client_session_keys(client_rx, client_tx,
                                  client_pk, client_sk, server_pk) != 0) {
    /* Suspicious server public key, bail out */
}
```

## Example (server-side)

```c
unsigned char server_pk[crypto_kx_PUBLICKEYBYTES], server_sk[crypto_kx_SECRETKEYBYTES];
unsigned char server_rx[crypto_kx_SESSIONKEYBYTES], server_tx[crypto_kx_SESSIONKEYBYTES];

/* Generate the server's key pair */
crypto_kx_keypair(server_pk, server_sk);

/* Prerequisite after this point: the client's public key must be known by the server */

/* Compute two shared keys using the client's public key and the server's secret key.
   server_rx will be used by the server to receive data from the client,
   server_tx will be used by the server to send data to the client. */
if (crypto_kx_server_session_keys(server_rx, server_tx,
                                  server_pk, server_sk, client_pk) != 0) {
    /* Suspicious client public key, bail out */
}
```

## Purpose

Using the key exchange API, two parties can securely compute a set of shared keys using their peer’s public key and their own secret key.

This API was introduced in libsodium 1.0.12.

## Usage

```c
int crypto_kx_keypair(unsigned char pk[crypto_kx_PUBLICKEYBYTES],
                      unsigned char sk[crypto_kx_SECRETKEYBYTES]);
```

The `crypto_kx_keypair()` function creates a new key pair. It puts the public key into `pk` and the secret key into `sk`.

```c
int crypto_kx_seed_keypair(unsigned char pk[crypto_kx_PUBLICKEYBYTES],
                           unsigned char sk[crypto_kx_SECRETKEYBYTES],
                           const unsigned char seed[crypto_kx_SEEDBYTES]);
```

The `crypto_kx_seed_keypair()` function computes a deterministic key pair from the seed `seed` (`crypto_kx_SEEDBYTES` bytes).

```c
int crypto_kx_client_session_keys(unsigned char rx[crypto_kx_SESSIONKEYBYTES],
                                  unsigned char tx[crypto_kx_SESSIONKEYBYTES],
                                  const unsigned char client_pk[crypto_kx_PUBLICKEYBYTES],
                                  const unsigned char client_sk[crypto_kx_SECRETKEYBYTES],
                                  const unsigned char server_pk[crypto_kx_PUBLICKEYBYTES]);
```

The `crypto_kx_client_session_keys()` function computes a pair of shared keys (`rx` and `tx`) using the client’s public key `client_pk`, the client’s secret key `client_sk`, and the server’s public key `server_pk`.

It returns `0` on success and `-1` if the server’s public key is not acceptable.

These keys can be used by any functions requiring secret keys up to `crypto_kx_SESSIONKEYBYTES` bytes, including `crypto_secretbox_*()` and `crypto_aead_*()`.

The shared secret key `rx` should be used by the client to receive data from the server, whereas `tx` should be used for data flowing in the opposite direction.

`rx` and `tx` are both `crypto_kx_SESSIONKEYBYTES` bytes long. If only one session key is required, either `rx` or `tx` can be set to `NULL`.

```c
int crypto_kx_server_session_keys(unsigned char rx[crypto_kx_SESSIONKEYBYTES],
                                  unsigned char tx[crypto_kx_SESSIONKEYBYTES],
                                  const unsigned char server_pk[crypto_kx_PUBLICKEYBYTES],
                                  const unsigned char server_sk[crypto_kx_SECRETKEYBYTES],
                                  const unsigned char client_pk[crypto_kx_PUBLICKEYBYTES]);
```

The `crypto_kx_server_session_keys()` function computes a pair of shared keys (`rx` and `tx`) using the server’s public key `server_pk`, the server’s secret key `server_sk`, and the client’s public key `client_pk`.

It returns `0` on success and `-1` if the client’s public key is not acceptable.

The shared secret key `rx` should be used by the server to receive data from the client, whereas `tx` should be used for data flowing in the opposite direction.

`rx` and `tx` are both `crypto_kx_SESSIONKEYBYTES` bytes long. If only one session key is required, either `rx` or `tx` can be set to `NULL`.

## Constants

* `crypto_kx_PUBLICKEYBYTES`
* `crypto_kx_SECRETKEYBYTES`
* `crypto_kx_SEEDBYTES`
* `crypto_kx_SESSIONKEYBYTES`
* `crypto_kx_PRIMITIVE`

## Algorithm details

Let `p.n` be the `crypto_scalarmult_curve25519_BYTES` byte output of the X25519 key exchange operation. The 512-bit output of `BLAKE2B-512` is split into two 256-bit keys `client_rx` and `client_tx`.

`client_rx = server_tx` and `client_tx = server_rx`.

`client_rx || client_tx = BLAKE2B-512(p.n || client_pk || server_pk)`

## Notes

For earlier versions of the library that didn’t implement this API, the X25519 function is accessible directly using the `crypto_scalarmult_*()` API.

Having different keys for each direction allows counters to be safely used as nonces without having to wait for an acknowledgment after every message.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://libsodium.gitbook.io/doc/key_exchange.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
