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

# Encryption Key Storage

> Build recovery flows with risk separation between your infrastructure and Turnkey.

export const SolutionCard = ({title, description, icon, href}) => {
  return <a href={href} className="not-prose font-normal group ring-0 ring-transparent cursor-pointer block rounded-lg border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-transparent p-5 no-underline hover:border-primary/40 transition-colors">
      <div style={{
    display: 'flex',
    alignItems: 'flex-start',
    gap: '16px'
  }}>
        <img src={`/images/solutions/light/${icon}.svg`} className="tk-card-icon-img block dark:hidden" alt="" />
        <img src={`/images/solutions/dark/${icon}.svg`} className="tk-card-icon-img hidden dark:block" alt="" />
        <div>
          <div className="font-semibold text-sm text-zinc-950 dark:text-white group-hover:text-primary transition-colors">
            {title}
          </div>
          <div className="text-sm text-zinc-500 dark:text-zinc-400 mt-1">
            {description}
          </div>
        </div>
      </div>
    </a>;
};

export const FeatureCard = ({title, description, icon, logo, href}) => {
  return <a href={href} className="not-prose font-normal group ring-0 ring-transparent cursor-pointer block rounded-lg border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-transparent p-5 no-underline hover:border-primary/40 transition-colors">
      <div className="tk-card-row">
        <span className="tk-card-icon-wrap">
          {logo ? <img src={`/images/networks/${logo}.svg`} className="tk-card-network-logo" alt="" /> : <span className="tk-card-icon" style={{
    maskImage: `url(/images/icons/${icon}.svg)`,
    WebkitMaskImage: `url(/images/icons/${icon}.svg)`
  }} />}
        </span>
        <div>
          <div className="font-semibold text-sm text-zinc-950 dark:text-white group-hover:text-primary transition-colors">
            {title}
          </div>
          {description && <div className="text-sm text-zinc-500 dark:text-zinc-400 mt-1">
              {description}
            </div>}
        </div>
      </div>
    </a>;
};

Store and retrieve encryption keys from Turnkey's secure enclave with policy-controlled access. Your infrastructure holds encrypted data and Turnkey holds the encryption key. Neither party alone can access plaintext. For an overview of Turnkey's key management capabilities, see the [Key Management Overview](/solutions/key-management/overview).

## Powered by Turnkey

* [**World App**](https://www.turnkey.com/blog/turnkey-announces-integration-tools-for-humanitys-world-app) (by Tools for Humanity) -- encrypts each user's recovery bundle on-device and stores the encryption key in Turnkey's secure enclave, gated by user authentication via OAuth. [View on GitHub](https://github.com/worldcoin/backup-service).

## Key implementation decisions

| Decision                   | What to consider                                                                                                                                                                               | Learn more                                                                               |
| :------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------- |
| **Export controls**        | Gate key export through policies. Require quorum approval, restrict which users can trigger export, or scope export to specific key IDs.                                                       | [Policy Engine](/features/policies/overview), [Root Quorum](/features/users/root-quorum) |
| **Authentication method**  | Choose how users authenticate to access keys: API keys, passkeys, social logins, email, or SMS OTP. Match the method to your security and UX requirements.                                     | [Authentication Overview](/features/authentication/overview)                             |
| **Encrypted data storage** | Store encrypted bundles wherever you control: client-side (localStorage, IndexedDB), mobile secure enclave, your database, or object storage (S3, GCS). Turnkey only holds the encryption key. |                                                                                          |

## Example: backup and recovery

A common pattern for applications: encrypt recovery bundles, store them in your infrastructure, and authenticate through Turnkey to decrypt when needed. No single party holds both the encrypted data and the decryption key.

<Frame>
  <img src="https://mintcdn.com/turnkey-0e7c1f5b/FhUFGc4MKWWumTgP/images/key-management/encryption-key-escrow-example.png?fit=max&auto=format&n=FhUFGc4MKWWumTgP&q=85&s=49c5fe387c92378def93df664cebb1a7" alt="2-of-2 security model diagram showing encrypted data in your infrastructure and encryption key in Turnkey secure enclave" width="2880" height="1620" data-path="images/key-management/encryption-key-escrow-example.png" />
</Frame>

| Need                                                    | How Turnkey solves it                                                                                               |
| :------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------ |
| Risk separation between platforms                       | Turnkey never sees the encrypted data; your infrastructure never sees the encryption key. Both must be compromised. |
| Decrypt recovery bundles without managing keys directly | Encryption key lives in the enclave; authenticate to export it on demand                                            |
| Caller retains control                                  | Only the caller's authenticator (passkey, email, social login) can trigger key export                               |
| Policy-gated access for sensitive operations            | Quorum approval, scoped export policies, and audit trails for every key operation                                   |

### Implementation steps

<Note>
  Explore the complete implementation in the [GitHub encryption-key-escrow example](https://github.com/tkhq/sdk/tree/main/examples/key-management/encryption-key-escrow).
</Note>

<Steps>
  <Step title="Create encryption keypair">
    Generate a P-256 keypair in Turnkey using [createPrivateKeys](/api-reference/activities/create-private-keys). The private key is stored in Turnkey's [secure enclave](/security/secure-enclaves) and never exposed.

    ```typescript theme={"system"}
    const { privateKeys } = await turnkey.apiClient().createPrivateKeys({
      privateKeys: [{
        privateKeyName: "escrow-encryption-key",
        curve: "CURVE_P256",
        addressFormats: [],
      }],
    });
    ```
  </Step>

  <Step title="Retrieve public key">
    Fetch the public key to use for encryption:

    ```typescript theme={"system"}
    const { privateKey } = await turnkey.apiClient().getPrivateKey({
      privateKeyId: encryptionKeyId,
    });
    const publicKey = privateKey.publicKey;
    ```
  </Step>

  <Step title="Encrypt data locally">
    Use the public key to encrypt sensitive data on your side. Turnkey never sees the plaintext or the encrypted result:

    ```typescript theme={"system"}
    // Using P-256 ECIES encryption
    const encryptedBundle = await encryptWithPublicKey(publicKey, sensitiveData);

    // Store in YOUR infrastructure
    await saveToYourStorage(encryptedBundle);
    ```
  </Step>

  <Step title="Authenticate and export decryption key">
    Authenticate the user through your normal auth flow, then request the encryption private key from Turnkey using [exportPrivateKey](/api-reference/activities/export-private-key):

    ```typescript theme={"system"}
    const targetKeyPair = generateP256KeyPair();

    const { exportBundle } = await turnkey.apiClient().exportPrivateKey({
      privateKeyId: encryptionKeyId,
      targetPublicKey: targetKeyPair.publicKeyUncompressed,
    });

    const decryptionKey = await decryptExportBundle({
      exportBundle,
      embeddedKey: targetKeyPair.privateKey,
      organizationId,
    });
    ```

    Use Turnkey's [policy engine](/features/policies/overview) to add controls on key export:

    ```json theme={"system"}
    {
      "policyName": "Escrow-Key-Export-Policy",
      "effect": "EFFECT_ALLOW",
      "condition": "activity.type == 'ACTIVITY_TYPE_EXPORT_PRIVATE_KEY' && private_key.id == '<ENCRYPTION_KEY_ID>'",
      "consensus": "approvers.count() >= 2"
    }
    ```

    This example requires two approvers for any export of the encryption key, adding human oversight to sensitive operations.
  </Step>

  <Step title="Decrypt and use locally">
    Decrypt your stored bundles and use them locally, with no further Turnkey calls:

    ```typescript theme={"system"}
    const plaintext = await decryptWithPrivateKey(decryptionKey, encryptedBundle);
    // Use the decrypted data (sign transactions, access credentials, etc.)
    ```

    When done, clear the decryption key and any decrypted data from memory:

    ```typescript theme={"system"}
    secureWipe(decryptionKey);
    secureWipe(decryptedData);
    ```
  </Step>
</Steps>

## Next steps

<div style={{display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '12px'}}>
  <FeatureCard title="Secure Enclaves" icon="cpu-chip-01" href="/security/secure-enclaves" description="How Turnkey protects key material inside hardware-backed enclaves." />

  <FeatureCard title="Policy Engine" icon="file-shield-02" href="/features/policies/quickstart" description="Define granular access controls and approval requirements for key operations." />

  <FeatureCard title="Export Private Keys" icon="download-01" href="/features/wallets/export-wallets" description="API documentation for key export flows." />

  <SolutionCard title="Enterprise Disaster Recovery" icon="enterprise-disaster-recovery" href="/solutions/key-management/enterprise-disaster-recovery" description="Import and recover wallets with quorum approval and a cryptographic audit trail." />
</div>
