> ## Documentation Index
> Fetch the complete documentation index at: https://docs.redpill.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# End-to-End Encryption (E2EE)

> Field-level encryption between your client and the attested gateway, on top of TLS.

End-to-end encryption (E2EE) encrypts selected request and response fields between your client and
the attested gateway. It sits on top of TLS: TLS still protects the HTTP connection, and E2EE adds
field-level encryption whose key is published in the gateway's
[attested keyset](/confidential-ai/attestation-report). This page explains the model. For setup and
code, see the [E2EE encryption guide](/guides/e2ee-encryption).

## What E2EE adds

* **Key provenance.** The encryption key (`X-Model-Pub-Key`) comes from the attested keyset, so you
  can prove the field is encrypted to a key bound to a genuine TEE, not an arbitrary endpoint.
* **Field-level encryption.** Selected request fields and response fields are encrypted, with the
  ciphertext bound by AEAD associated data to the request context (listed under
  [Ciphertext format](#ciphertext-format)), so it cannot be replayed or moved to another field.

The gateway reports E2EE support in the attestation report:
`service_capabilities.supported_e2ee_versions` includes `"2"`.

## What E2EE does not change

E2EE is decrypted **inside** the attested gateway so the gateway can process your request. It does not
hide the request from the attested gateway; it proves the decryption key belongs to that gateway.
This is the same boundary described in [Trust boundary](/confidential-ai/trust-boundary). Use a
[confidential model](/confidential-ai/confidential-models) when the upstream that runs the model must
also be attested.

## Request headers

| Header             | Value                                                 |
| ------------------ | ----------------------------------------------------- |
| `X-E2EE-Version`   | `2`                                                   |
| `X-Client-Pub-Key` | Your secp256k1 public key, hex encoded.               |
| `X-Model-Pub-Key`  | The gateway E2EE public key from the attested keyset. |
| `X-E2EE-Nonce`     | A unique per-request nonce.                           |
| `X-E2EE-Timestamp` | Unix seconds, close to gateway time.                  |

Do not send `X-Signing-Algo` with E2EE; that header selects the legacy compatibility path.

## Ciphertext format

Each encrypted field is the lowercase hex encoding of:

```text theme={null}
ephemeral_uncompressed_secp256k1_public_key || aes_gcm_nonce || ciphertext_tag
```

The AEAD associated data binds the ciphertext to the protocol version, direction, algorithm, model,
field path, nonce, timestamp, and response identity. Any mismatch fails decryption, so use the
official client helpers rather than assembling the bytes by hand.

## Receipts with E2EE

Receipts attach to E2EE requests exactly as they do to plain TLS requests. The
`request.received.body_hash` is the hash of the gateway-observed **decrypted** body, not the encrypted
bytes you sent. When you [verify a response](/guides/verify-a-response), compare request hashes
against the decrypted body your client holds.

## Next

<CardGroup cols={2}>
  <Card title="E2EE encryption guide" icon="key" href="/guides/e2ee-encryption">
    Headers, key exchange, and code.
  </Card>

  <Card title="Trust boundary" icon="shield-halved" href="/confidential-ai/trust-boundary">
    Where plaintext is visible.
  </Card>
</CardGroup>
