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

# Cryptographic Implementation

> Cryptographic requirements and best practices for AgentVault integrations.

AgentVault provides end-to-end encryption for all agent-owner communications. The server never
sees plaintext -- all encryption and decryption happens client-side. **MLS (RFC 9420) is the
primary encryption protocol** for all conversation types, with Double Ratchet + X3DH retained
as a fallback for legacy 1:1 sessions. This guide covers the cryptographic primitives, key
handling requirements, and forward secrecy guarantees that every integration must follow.

<Note>
  AgentVault's crypto library (`@agentvault/crypto`) implements all of these requirements.
  If you are building a custom integration, follow this guide to ensure compatibility.
</Note>

## Cryptographic Primitives

AgentVault uses a carefully chosen set of modern primitives via libsodium.

| Purpose              | Algorithm                | Notes                                                                    |
| -------------------- | ------------------------ | ------------------------------------------------------------------------ |
| Group key agreement  | MLS (RFC 9420)           | Primary protocol -- scalable ratchet tree with per-epoch forward secrecy |
| Symmetric encryption | XChaCha20-Poly1305       | AEAD cipher with 192-bit nonce (used by both MLS and Double Ratchet)     |
| Key exchange         | X25519 (Curve25519 ECDH) | Used in X3DH handshake (Double Ratchet fallback)                         |
| Digital signatures   | Ed25519                  | Identity keys, MLS credentials, message authentication                   |
| Hashing              | BLAKE2b                  | Invite token hashing, KDF inputs                                         |
| Key derivation       | HKDF-SHA-256             | Ratchet chain key derivation                                             |

<Warning>
  AgentVault does **not** use AES-GCM. The 192-bit nonce in XChaCha20-Poly1305 eliminates
  nonce reuse risk that plagues AES-GCM's 96-bit nonce, which is critical for high-throughput
  messaging where random nonce collisions become statistically significant.
</Warning>

## Key Exchange: X3DH (Double Ratchet Fallback)

For legacy 1:1 sessions that have not migrated to MLS, AgentVault uses the Extended Triple
Diffie-Hellman (X3DH) protocol to establish shared secrets between an owner and an agent
device. New sessions use MLS group creation instead.

<Steps>
  <Step title="Identity key generation">
    Each device generates a long-term Ed25519 identity key pair stored in OS secure storage
    (Keychain on iOS, Keystore on Android, `expo-secure-store` cross-platform).
  </Step>

  <Step title="Ephemeral key generation">
    The initiating device generates a one-time X25519 ephemeral key pair for the handshake.
  </Step>

  <Step title="Triple DH computation">
    Three DH computations produce the shared secret:

    * DH(identity\_A, ephemeral\_B)
    * DH(ephemeral\_A, identity\_B)
    * DH(ephemeral\_A, ephemeral\_B)

    The results are concatenated and passed through HKDF to derive the initial root key.
  </Step>

  <Step title="Double Ratchet initialization">
    The shared secret seeds the Double Ratchet algorithm for ongoing message encryption.
  </Step>
</Steps>

<Tip>
  AgentVault's X3DH implementation uses synchronous enrollment (both parties are online),
  so signed prekeys and one-time prekeys are not required. This is acceptable for the
  agent use case where devices enroll in real-time.
</Tip>

## Double Ratchet Protocol (Fallback)

For legacy 1:1 sessions, the Double Ratchet algorithm provides forward secrecy and break-in
recovery after the X3DH handshake. New conversations use MLS as the primary protocol.

### How It Works

The Double Ratchet combines two ratcheting mechanisms:

1. **Symmetric-key ratchet (chain keys)** -- Derives a new message key for each message using
   HKDF. Old keys are deleted after use, providing forward secrecy.

2. **Diffie-Hellman ratchet** -- Periodically performs a new DH key exchange to provide
   break-in recovery. If a key is compromised, future messages remain secure after the
   next DH ratchet step.

### Ratchet Advancement

```
Root Key ──► DH Ratchet Step ──► New Chain Key
                                      │
                                      ├──► Message Key 1 (deleted after use)
                                      ├──► Message Key 2 (deleted after use)
                                      └──► Message Key 3 (deleted after use)
```

<Warning>
  The ratchet **must** advance on every message. Reusing a message key breaks forward secrecy
  and exposes all messages encrypted under that key.
</Warning>

## Device Key Handling

Proper key storage is critical to the security model.

### Requirements

| Requirement         | Implementation                                              |
| ------------------- | ----------------------------------------------------------- |
| Private key storage | OS secure storage (Keychain, Keystore, `expo-secure-store`) |
| Key logging         | Never log private key material under any circumstances      |
| Session state       | Encrypt local ratchet state at rest                         |
| Key deletion        | Delete message keys immediately after decryption            |
| Debug logging       | Disable all crypto debug logs in production builds          |

### Key Types and Lifecycle

<Accordion title="Identity Key Pair (Ed25519)">
  * Generated once per device during enrollment
  * Stored permanently in OS secure storage
  * Used to sign messages and derive DH shared secrets
  * Survives app updates; lost only on device wipe or explicit revocation
</Accordion>

<Accordion title="Ephemeral Key Pair (X25519)">
  * Generated during X3DH handshake
  * Used once to establish the initial shared secret
  * Deleted after the Double Ratchet is initialized
</Accordion>

<Accordion title="Chain Keys (HKDF-derived)">
  * Derived from the root key via HKDF after each DH ratchet step
  * Used to derive individual message keys
  * Advanced (replaced) after each message
</Accordion>

<Accordion title="Message Keys (XChaCha20-Poly1305)">
  * Derived from the current chain key
  * Used to encrypt/decrypt exactly one message
  * Deleted immediately after use to ensure forward secrecy
</Accordion>

## Library Choices

### Recommended: `@agentvault/crypto`

The `@agentvault/crypto` npm package provides a complete implementation of AgentVault's
cryptographic protocols (MLS and Double Ratchet fallback).

```bash theme={null}
npm install @agentvault/crypto
```

<Note>
  The examples below show the Double Ratchet fallback API. For new integrations, the MLS
  group API is used automatically by the `SecureChannel` and `AgentVaultClient` classes.
  These lower-level APIs are relevant for custom implementations or legacy session support.
</Note>

<CodeGroup>
  ```typescript Encrypt a message (Double Ratchet fallback) theme={null}
  import { DoubleRatchet } from "@agentvault/crypto";

  // After X3DH handshake, initialize the ratchet
  const ratchet = DoubleRatchet.initSender(sharedSecret, remotePublicKey);

  // Encrypt a message
  const { header, ciphertext } = await ratchet.encrypt(
    new TextEncoder().encode("Hello, agent!")
  );

  // Send header + ciphertext to the server (server sees only ciphertext)
  ```

  ```typescript Decrypt a message (Double Ratchet fallback) theme={null}
  import { DoubleRatchet } from "@agentvault/crypto";

  // After X3DH handshake, initialize the ratchet
  const ratchet = DoubleRatchet.initReceiver(sharedSecret, localKeyPair);

  // Decrypt an incoming message
  const plaintext = await ratchet.decrypt(header, ciphertext);
  const message = new TextDecoder().decode(plaintext);
  ```
</CodeGroup>

### Custom Implementations

If you are building a custom integration in a language other than TypeScript, use any
libsodium binding that provides:

* `crypto_aead_xchacha20poly1305_ietf_encrypt` / `decrypt`
* `crypto_scalarmult` (X25519)
* `crypto_sign_ed25519` keypair generation and signing
* `crypto_generichash` (BLAKE2b)
* `crypto_kdf_hkdf_sha256_extract` / `expand` (or equivalent HKDF)

<CodeGroup>
  ```python Python (PyNaCl) theme={null}
  from nacl.public import PrivateKey, Box
  from nacl.signing import SigningKey
  from nacl.utils import random

  # Generate identity key pair
  signing_key = SigningKey.generate()
  verify_key = signing_key.verify_key

  # Generate X25519 key pair for DH
  private_key = PrivateKey.generate()
  public_key = private_key.public_key

  # XChaCha20-Poly1305 encryption via Box
  box = Box(private_key, remote_public_key)
  ciphertext = box.encrypt(plaintext)
  ```

  ```typescript Node.js (libsodium-wrappers) theme={null}
  import sodium from "libsodium-wrappers";

  await sodium.ready;

  // Generate identity key pair
  const identityKeyPair = sodium.crypto_sign_keypair();

  // Generate X25519 key pair
  const dhKeyPair = sodium.crypto_kx_keypair();

  // XChaCha20-Poly1305 encryption
  const nonce = sodium.randombytes_buf(
    sodium.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
  );
  const ciphertext = sodium.crypto_aead_xchacha20poly1305_ietf_encrypt(
    plaintext,
    null,    // additional data
    null,    // nsec (unused)
    nonce,
    key,
  );
  ```
</CodeGroup>

## Forward Secrecy Guarantees

AgentVault's protocols provide multiple levels of forward secrecy:

| Property                                      | Mechanism                                         | Guarantee                                                                                |
| --------------------------------------------- | ------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| **Epoch forward secrecy (MLS)**               | Ratchet tree update on every Commit               | Compromising an epoch key does not reveal messages from other epochs                     |
| **Per-message forward secrecy (DR fallback)** | Symmetric ratchet (chain key advancement)         | Compromising a message key does not reveal past messages                                 |
| **Break-in recovery**                         | MLS tree update / DH ratchet (periodic re-keying) | Compromising a long-term key does not reveal future messages after the next key rotation |

### Ensuring Forward Secrecy in Your Integration

1. **Delete message keys after use.** Never cache or persist decrypted message keys.
2. **Advance the ratchet on every message.** Skipping ratchet steps weakens forward secrecy.
3. **Re-key on member removal.** When a device is revoked, all remaining sessions must re-key.
4. **Verify epoch consistency.** Ensure both parties agree on the current ratchet state.

## Validation Tests

Any custom cryptographic integration should pass these test categories before deployment.

<Accordion title="Required Test Cases">
  | Category                  | Test                                                                                |
  | ------------------------- | ----------------------------------------------------------------------------------- |
  | **Replay attacks**        | Reject messages with previously seen nonces or sequence numbers                     |
  | **Out-of-order delivery** | Correctly decrypt messages received out of order (within the skip window)           |
  | **Corrupt ciphertext**    | Reject tampered ciphertext (Poly1305 MAC verification failure)                      |
  | **Device revocation**     | Refuse to encrypt/decrypt after a device has been revoked                           |
  | **Key deletion**          | Verify that message keys are not recoverable after decryption                       |
  | **Ratchet advancement**   | Confirm that each message produces a unique ciphertext even for identical plaintext |
</Accordion>

## Operational Safeguards

<Warning>
  These safeguards are mandatory for production deployments.
</Warning>

| Safeguard                             | Rationale                                                                             |
| ------------------------------------- | ------------------------------------------------------------------------------------- |
| Disable debug logs in production      | Crypto debug logs may leak key material or plaintext                                  |
| Validate JWT before any DB access     | Prevents unauthorized access to encrypted message store                               |
| Rate limit enrollment endpoints       | Prevents brute-force attacks on the X3DH handshake (5 attempts per IP per 10 minutes) |
| Use BYTEA columns for crypto material | Never store keys or ciphertext as TEXT -- binary storage prevents encoding issues     |
| Generic error messages                | Auth and enrollment failures must not leak information about valid identities         |
