# Key encapsulation

## Example

```c
unsigned char pk[crypto_kem_PUBLICKEYBYTES];
unsigned char sk[crypto_kem_SECRETKEYBYTES];
unsigned char ciphertext[crypto_kem_CIPHERTEXTBYTES];
unsigned char client_key[crypto_kem_SHAREDSECRETBYTES];
unsigned char server_key[crypto_kem_SHAREDSECRETBYTES];

crypto_kem_keypair(pk, sk);

if (crypto_kem_enc(ciphertext, client_key, pk) != 0) {
    /* error */
}
if (crypto_kem_dec(server_key, ciphertext, sk) != 0) {
    /* error */
}
```

## Purpose

A key encapsulation mechanism creates a shared secret for a recipient using the public key of that recipient.

The sender obtains the shared secret directly during encapsulation. The recipient obtains the same shared secret by decapsulating the ciphertext with the secret key.

This is useful for bootstrapping session keys or building hybrid encryption schemes.

For most applications, the high-level `crypto_kem_*()` API should be preferred. In libsodium, it uses X-Wing, a hybrid post-quantum KEM combining ML-KEM768 and X25519.

## Usage

```c
int crypto_kem_keypair(unsigned char *pk, unsigned char *sk);
```

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

```c
int crypto_kem_seed_keypair(unsigned char *pk, unsigned char *sk,
                            const unsigned char *seed);
```

The `crypto_kem_seed_keypair()` function computes a deterministic key pair from `seed` (`crypto_kem_SEEDBYTES` bytes).

```c
int crypto_kem_enc(unsigned char *ct, unsigned char *ss,
                   const unsigned char *pk);
```

The `crypto_kem_enc()` function creates a ciphertext `ct` for the recipient public key `pk` and stores the shared secret into `ss`.

It returns `0` on success and `-1` on failure.

```c
int crypto_kem_dec(unsigned char *ss, const unsigned char *ct,
                   const unsigned char *sk);
```

The `crypto_kem_dec()` function verifies and decapsulates the ciphertext `ct` using the recipient secret key `sk`, and stores the shared secret into `ss`.

It returns `0` on success and `-1` on failure.

## Using the shared secret

The shared secret is `crypto_kem_SHAREDSECRETBYTES` bytes long.

In many protocols, the shared secret is immediately fed to a KDF in order to derive multiple context-specific keys. [HKDF](/doc/key_derivation/hkdf.md) is a good fit for this.

## Algorithm details

The high-level `crypto_kem_*()` API uses X-Wing and reports `"xwing"` via `crypto_kem_PRIMITIVE`.

X-Wing combines ML-KEM768 with X25519 in order to provide protection against both classical and quantum adversaries.

For libsodium applications, it should be the default choice.

## Constants

* `crypto_kem_PUBLICKEYBYTES`
* `crypto_kem_SECRETKEYBYTES`
* `crypto_kem_CIPHERTEXTBYTES`
* `crypto_kem_SHAREDSECRETBYTES`
* `crypto_kem_SEEDBYTES`
* `crypto_kem_PRIMITIVE`

## Notes

Unlike traditional Diffie-Hellman style key exchange, encapsulation is asymmetric: only the recipient needs a long-term key pair, and the sender does not need to publish a public key in order to create a shared secret.

If the application needs sender authentication in addition to confidentiality, combine key encapsulation with a signature scheme or an authenticated key exchange.

This API was introduced in libsodium 1.0.22.


---

# 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/public-key_cryptography/key_encapsulation.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.
