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

# Encryption and key hierarchy

> Understand the customer-owned keys that protect credentials at ingress, storage, and use.

export const KeyHierarchyDiagram = () => <figure className="keyring-diagram key-hierarchy">
    <svg className="kh" viewBox="0 0 640 350" role="img" aria-label="Your KMS root key sits at the top. Keyring-generated data-encryption keys, one per project, hang below it wrapped by the root key, and each project's credentials are encrypted under that project's key.">
      <g className="kh__build">
                <line className="kh__link kh__link--ra" x1="320" y1="67" x2="190" y2="157" pathLength="1" />
        <line className="kh__link kh__link--rb" x1="320" y1="67" x2="450" y2="157" pathLength="1" />
        <line className="kh__link kh__link--a1" x1="190" y1="195" x2="130" y2="285" pathLength="1" />
        <line className="kh__link kh__link--a2" x1="190" y1="195" x2="190" y2="285" pathLength="1" />
        <line className="kh__link kh__link--a3" x1="190" y1="195" x2="250" y2="285" pathLength="1" />
        <line className="kh__link kh__link--b1" x1="450" y1="195" x2="420" y2="285" pathLength="1" />
        <line className="kh__link kh__link--b2" x1="450" y1="195" x2="480" y2="285" pathLength="1" />

        <g className="kh__dek kh__dek--a">
          <circle className="kh__disc" cx="190" cy="176" r="19" />
          <g className="kh__dek-key"><g transform="translate(179.2 165.2) scale(0.9)"><circle cx="8" cy="12" r="3.2" /><path d="M11.2 12h9.3m-3 0v2.8m-3-2.8v2" /></g></g>
          <g className="kh__badge">
            <circle cx="204" cy="163" r="7.5" />
            <g transform="translate(198.96 157.96) scale(0.42)"><rect x="5.5" y="10.5" width="13" height="8.5" rx="2" /><path d="M8.5 10.5V8.2a3.5 3.5 0 0 1 7 0v2.3" /><path d="M12 13.6v2" /></g>
          </g>
          <text className="kh__label" x="190" y="212">DEK · Project A</text>
          <text className="kh__caption" x="190" y="226">wrapped by your root key</text>
        </g>
        <g className="kh__dek kh__dek--b">
          <circle className="kh__disc" cx="450" cy="176" r="19" />
          <g className="kh__dek-key"><g transform="translate(439.2 165.2) scale(0.9)"><circle cx="8" cy="12" r="3.2" /><path d="M11.2 12h9.3m-3 0v2.8m-3-2.8v2" /></g></g>
          <g className="kh__badge">
            <circle cx="464" cy="163" r="7.5" />
            <g transform="translate(458.96 157.96) scale(0.42)"><rect x="5.5" y="10.5" width="13" height="8.5" rx="2" /><path d="M8.5 10.5V8.2a3.5 3.5 0 0 1 7 0v2.3" /><path d="M12 13.6v2" /></g>
          </g>
          <text className="kh__label" x="450" y="212">DEK · Project B</text>
          <text className="kh__caption" x="450" y="226">wrapped by your root key</text>
        </g>

                <g className="kh__leaf kh__leaf--a1">
          <circle className="kh__disc" cx="130" cy="300" r="15" />
          <g transform="translate(121.6 291.6) scale(0.7)"><rect x="5.5" y="10.5" width="13" height="8.5" rx="2" /><path d="M8.5 10.5V8.2a3.5 3.5 0 0 1 7 0v2.3" /><path d="M12 13.6v2" /></g>
        </g>
        <g className="kh__leaf kh__leaf--a2">
          <circle className="kh__disc" cx="190" cy="300" r="15" />
          <g transform="translate(181.6 291.6) scale(0.7)"><rect x="5.5" y="10.5" width="13" height="8.5" rx="2" /><path d="M8.5 10.5V8.2a3.5 3.5 0 0 1 7 0v2.3" /><path d="M12 13.6v2" /></g>
        </g>
        <g className="kh__leaf kh__leaf--a3">
          <circle className="kh__disc" cx="250" cy="300" r="15" />
          <g transform="translate(241.6 291.6) scale(0.7)"><rect x="5.5" y="10.5" width="13" height="8.5" rx="2" /><path d="M8.5 10.5V8.2a3.5 3.5 0 0 1 7 0v2.3" /><path d="M12 13.6v2" /></g>
        </g>
        <g className="kh__leaf kh__leaf--b1">
          <circle className="kh__disc" cx="420" cy="300" r="15" />
          <g transform="translate(411.6 291.6) scale(0.7)"><rect x="5.5" y="10.5" width="13" height="8.5" rx="2" /><path d="M8.5 10.5V8.2a3.5 3.5 0 0 1 7 0v2.3" /><path d="M12 13.6v2" /></g>
        </g>
        <g className="kh__leaf kh__leaf--b2">
          <circle className="kh__disc" cx="480" cy="300" r="15" />
          <g transform="translate(471.6 291.6) scale(0.7)"><rect x="5.5" y="10.5" width="13" height="8.5" rx="2" /><path d="M8.5 10.5V8.2a3.5 3.5 0 0 1 7 0v2.3" /><path d="M12 13.6v2" /></g>
        </g>

        <text className="kh__caption kh__row-caption" x="320" y="342">credentials · AES-256-GCM under their project DEK</text>
      </g>

      <g className="kh__root">
        <circle className="kh__disc" cx="320" cy="46" r="21" />
        <g className="kh__root-key"><g transform="translate(308 34) scale(1)"><circle cx="8" cy="12" r="3.2" /><path d="M11.2 12h9.3m-3 0v2.8m-3-2.8v2" /></g></g>
        <text className="kh__label" x="320" y="84">Root key</text>
        <text className="kh__caption" x="320" y="98">your KMS · never leaves</text>
      </g>
    </svg>
  </figure>;

export const DekFlowDiagram = ({mode}) => {
  const labels = {
    mint: "Composio sends Keyring a request for a new data-encryption key. Keyring generates it, your KMS wraps it with the root key, and the wrapped DEK envelope travels back to Composio, which stores it in its database.",
    cache: "Composio sends three decrypt requests with the same DEK envelope. The first makes Keyring ask your KMS to unwrap the DEK; the next two are served from Keyring's in-memory cache without a KMS call.",
    revoke: "KMS access is revoked. Composio sends a decrypt request with a DEK envelope, Keyring asks your KMS to unwrap it, the KMS refuses, and the credential stays locked."
  };
  const dbCaptions = {
    mint: "DEK envelopes",
    cache: "DEK envelopes",
    revoke: "DEK envelopes"
  };
  return <figure className={`keyring-diagram simple-request-flow dek-flow dek-flow--${mode}`}>
      <div className="simple-request-flow__stage" role="img" aria-label={labels[mode]}>
        <div className="dek-flow__track" aria-hidden="true" />

        <div className="simple-request-flow__nodes dek-flow__nodes">
          <div className="simple-request-flow__node dek-flow__node--composio">
            <span className="simple-request-flow__node-mark simple-request-flow__node-mark--composio" aria-hidden="true" />
            <b>Composio</b>
          </div>
          <div className="simple-request-flow__node dek-flow__node--keyring">
            <span className="simple-request-flow__node-mark simple-request-flow__node-mark--keyring">
              <svg viewBox="0 0 24 24" aria-hidden="true">
                <path d="M12 3 5 6v5c0 4.5 2.8 7.5 7 9.5 4.2-2 7-5 7-9.5V6L12 3Z" />
                <circle cx="12" cy="11" r="2" />
                <path d="M12 13v3" />
              </svg>
            </span>
            <b>Keyring</b>
            <span className="simple-request-flow__node-caption">Your Cloud</span>
          </div>
        </div>

        <div className="simple-request-flow__kms-link dek-flow__db-link" aria-hidden="true" />
        <div className="simple-request-flow__kms-packet dek-flow__db-packet" aria-hidden="true" />
        <div className="simple-request-flow__kms dek-flow__db">
          <span className="simple-request-flow__node-mark dek-flow__node-mark--db">
            <svg viewBox="0 0 24 24" aria-hidden="true">
              <ellipse cx="12" cy="6" rx="7" ry="2.7" />
              <path d="M5 6v12c0 1.5 3.1 2.7 7 2.7s7-1.2 7-2.7V6" />
              <path d="M5 12c0 1.5 3.1 2.7 7 2.7s7-1.2 7-2.7" />
            </svg>
          </span>
          <b>Composio DB</b>
          <span className="simple-request-flow__node-caption">{dbCaptions[mode]}</span>
          <span className="dek-flow__stored" aria-hidden="true">
            <svg viewBox="0 0 24 24">
              <rect x="3" y="5.5" width="18" height="13" rx="2" />
              <path d="M4.5 7.5 12 13l7.5-5.5" />
              <circle cx="12" cy="15.4" r="1.4" />
            </svg>
          </span>
        </div>

        <div className="simple-request-flow__kms-link dek-flow__kms-link" aria-hidden="true" />
        <div className="simple-request-flow__kms-packet dek-flow__kms-packet" aria-hidden="true" />
        <div className="simple-request-flow__kms dek-flow__kms">
          <span className="simple-request-flow__node-mark simple-request-flow__node-mark--kms dek-flow__kms-mark">
            <svg viewBox="0 0 24 24" aria-hidden="true">
              <circle cx="7.5" cy="12" r="3.5" />
              <path d="M11 12h10m-3 0v3m-3-3v2" />
            </svg>
            <svg className="dek-flow__kms-slash" viewBox="0 0 24 24" aria-hidden="true">
              <path d="M5 19 19 5" pathLength="1" />
            </svg>
          </span>
          <b>KMS</b>
          <span className="simple-request-flow__node-caption dek-flow__kms-note">
            {mode === "revoke" ? "access revoked" : "unwrapped once"}
          </span>
        </div>

        <div className="dek-flow__packet" aria-hidden="true">
          <div className="dek-flow__payload dek-flow__payload--request">
            {mode === "mint" ? <svg viewBox="0 0 24 24" aria-hidden="true">
                <path d="M4.5 12 19.5 4.5l-4 15-4.5-6.5-6.5-1Z" />
                <path d="m11 13 8.5-8.5" />
              </svg> : <svg viewBox="0 0 24 24" aria-hidden="true">
                <rect x="5.5" y="10.5" width="13" height="8.5" rx="2" />
                <path d="M8.5 10.5V8.2a3.5 3.5 0 0 1 7 0v2.3" />
                <path d="M12 13.6v2" />
              </svg>}
            <span>Request</span>
            {mode === "cache" ? <small className="dek-flow__counter" /> : <small>{mode === "mint" ? "POST /keys/dek · project A" : "decrypt credential 1 + DEK envelope"}</small>}
          </div>
          <div className="dek-flow__payload dek-flow__payload--dek">
            <svg viewBox="0 0 24 24" aria-hidden="true">
              <path d="M12 4.5 13.2 8l3.5 1.2-3.5 1.2L12 13.9l-1.2-3.5L7.3 9.2l3.5-1.2Z" />
              <path d="M18.5 14.2l.7 1.9 1.9.7-1.9.7-.7 1.9-.7-1.9-1.9-.7 1.9-.7Z" />
              <path d="M6.2 15.7l.6 1.5 1.5.6-1.5.6-.6 1.5-.6-1.5-1.5-.6 1.5-.6Z" />
            </svg>
            <span>DEK · AES-256</span>
            <small>generated by Keyring</small>
          </div>
          <div className="dek-flow__payload dek-flow__payload--envelope">
            <svg viewBox="0 0 24 24" aria-hidden="true">
              <rect x="3" y="5.5" width="18" height="13" rx="2" />
              <path d="M4.5 7.5 12 13l7.5-5.5" pathLength="1" />
              <circle cx="12" cy="15.4" r="1.4" />
            </svg>
            <span>DEK envelope</span>
            <small>wrapped by your root key</small>
          </div>
          <div className="dek-flow__payload dek-flow__payload--open">
            <svg viewBox="0 0 24 24" aria-hidden="true">
              <rect x="5.5" y="10.5" width="13" height="8.5" rx="2" />
              <path d="M15.5 10.5V8.2a3.5 3.5 0 0 0-6.5-1.7" />
              <path d="M12 13.6v2" />
            </svg>
            <span>Decrypted</span>
            <small className="dek-flow__open-note" />
          </div>
          <div className="dek-flow__payload dek-flow__payload--denied">
            <svg viewBox="0 0 24 24" aria-hidden="true">
              <rect x="5.5" y="10.5" width="13" height="8.5" rx="2" />
              <path d="M8.5 10.5V8.2a3.5 3.5 0 0 1 7 0v2.3" />
              <path d="M12 13.6v2" />
            </svg>
            <span>Still locked</span>
            <small>nothing opens without your KMS</small>
          </div>
        </div>
      </div>
    </figure>;
};

Keyring uses envelope encryption so Composio can store encrypted credentials without holding the keys
that make them readable. Your KMS root key never leaves your KMS. Keyring generates the data-encryption
keys (DEKs) that do the actual encryption and decryption, and your root key is the only thing that can
unwrap them.

## Key hierarchy

<KeyHierarchyDiagram />

1. **Root key** — lives in your AWS KMS, GCP Cloud KMS, or HashiCorp Vault. It only ever wraps and
   unwraps DEKs; it never touches a credential directly.
2. **Data-encryption keys** — generated by Keyring on request, wrapped by your root key, and stored by
   Composio as wrapped DEK envelopes. Composio currently requests one DEK per project.
3. **Credentials** — encrypted with AES-256-GCM under their project's DEK. Composio stores only the
   resulting credential envelopes, each tagged with the ID of the DEK that protects it.

## How a data key is created

<DekFlowDiagram mode="mint" />

1. Composio asks your Keyring for a new DEK for a scope. Keyring generates a random 256-bit key and a
   DEK ID.
2. Keyring asks your KMS to wrap that key with the active root key, packages the wrapped key into a DEK
   envelope, and returns the envelope to Composio. The plaintext DEK is discarded immediately.
3. Composio stores the wrapped DEK envelope. It cannot unwrap it: only your KMS root key can.

## How a data key is used

When a credential must be encrypted or decrypted, Composio sends the DEK envelope along with the
request. Keyring asks your KMS to unwrap the DEK, then performs the AES-256-GCM operation inside the
Keyring process and returns only ciphertext or the approved provider response.

Composio stores the encrypted credential envelope next to the wrapped DEK envelope. A copy of the
Composio database therefore contains wrapped keys and ciphertext only — no plaintext DEK and no
readable credential.

## Scoping data keys

DEKs are cheap to create, so Keyring can issue as many as you want to narrow the blast radius of any
single key. Today Composio requests one DEK per project: every credential in a project is encrypted
under that project's DEK, and unwrapping it once lets Keyring serve many credential operations for that
project without another KMS round trip. Finer scopes, such as one DEK per connected account, use the
same mechanism.

## Three separate key purposes

| Key purpose        | What it protects                                                                  |
| ------------------ | --------------------------------------------------------------------------------- |
| Credential root    | Provider credentials and sensitive fields returned during token exchange          |
| Authorization gate | A second, outer envelope around a credential, tied to a grant or consent decision |
| Secret transfer    | Credentials encrypted by the Composio Dashboard before reaching the backend       |

Each purpose has its own KMS keys, and Keyring refuses a configuration that reuses a key across
purposes. This prevents material created for one security role from being accepted in another.

## Transfer keys

Transfer keys are asymmetric RSA keys used only when a credential first enters Keyring. Composio and
the Composio Dashboard receive the public key. The private key remains in your KMS and is available only
to the Keyring workload identity.

Keep an older transfer key configured during rotation until in-flight credential setup attempts have
expired. New credentials can start using the new public key immediately.

## In-process key cache

<DekFlowDiagram mode="cache" />

Keyring can cache unwrapped DEKs in process memory as non-extractable key handles, so one KMS unwrap
serves many credential operations for the same scope. The cache holds up to 256 keys for 10 minutes by
default, never writes keys to disk or an external store, and is disabled unless `dek_cache` is set.
Restarting or scaling Keyring only causes another authorized KMS unwrap; it does not affect stored
credentials.

## Rotation and revocation

Rotate a root key with overlapping configuration:

1. Add the new KMS key and grant the Keyring workload identity the minimum required access.
2. Make the new key active so newly generated DEKs are wrapped by it, while keeping the old key
   available for unwrapping existing DEKs.
3. Have Composio request a fresh DEK and re-encrypt existing credentials under it through Keyring's
   rekey operation. Plaintext exists only inside the Keyring process during the rekey.
4. Confirm that no stored DEK envelope references the old key, then remove its Keyring access.
5. Apply your KMS disablement or deletion policy only after the migration is complete.

For an immediate global kill switch, stop Keyring or revoke its KMS permissions. Without the root key,
no DEK can be unwrapped, so every credential Composio holds becomes unusable until you restore access.

<DekFlowDiagram mode="revoke" />

See [Encryption configuration](/configuration/encryption) and
[KMS and Vault adapters](/configuration/kms_adapters) for the exact fields and provider examples.
