Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
4e10c0a
Add Secret Storage feature page and Programmable Credential Manager s…
emostov Aug 10, 2026
e0ad8e8
Rename Programmable Credential Manager to Programmable Credential Acc…
emostov Aug 11, 2026
3ffe2ad
Add Beta sidebar tag to secrets feature and solutions pages
emostov Aug 11, 2026
abb5fc6
Apply STE plain-writing pass to secrets pages
emostov Aug 11, 2026
f411d24
Remove client-side encryption comparison paragraph
emostov Aug 11, 2026
b9a5043
Reword High Security API Key Storage description
emostov Aug 11, 2026
296a96b
Add Secret storage link to front page features section
emostov Aug 11, 2026
ec26bc8
Add Programmable Credential Access link to Key Management solution card
emostov Aug 11, 2026
66e1c6e
Add new secrets solutions to Key Management section of solutions over…
emostov Aug 11, 2026
481ba84
Trim next steps on new solution pages to Secret Storage and Policy En…
emostov Aug 11, 2026
a58136f
Add bespoke icons for new solution pages and quantum resistance note …
emostov Aug 11, 2026
290cfe3
Correct cipher suite agility claim on secrets page
emostov Aug 11, 2026
513d661
Remove emojis from solution pages
emostov Aug 11, 2026
a465f64
Move Secret storage link to Manage wallets and keys column
emostov Aug 11, 2026
0aa3c61
Remove Under the hood sections from solution pages
emostov Aug 11, 2026
babf2da
Add Under the hood section to secrets feature page
emostov Aug 11, 2026
ab70221
Fold platform framing into Security model and drop Under the hood
emostov Aug 11, 2026
8c0b1a6
Say only policies and tags are mutable
emostov Aug 11, 2026
7bc0936
Apply review feedback: sentence case titles, rename API key storage, …
emostov Aug 11, 2026
e403815
Add MPC keyshare storage solution page
emostov Aug 11, 2026
ee5e63e
Clarify API key plaintext exposure
emostov Aug 11, 2026
a641d1e
Apply review feedback: drop MPC keyshare provider mentions and tighte…
emostov Aug 12, 2026
9ce9757
Add non-custodial delegated access variant for trading on behalf of u…
emostov Aug 13, 2026
b23d07c
Cross-link solutions in Next steps instead of enclave secure channels…
emostov Aug 13, 2026
5332235
Remove remaining code comments from solution snippets
emostov Aug 13, 2026
f424a5d
Revert "Remove remaining code comments from solution snippets"
emostov Aug 13, 2026
6e053b9
Drop Opaque by design section from MPC keyshare storage page
emostov Aug 13, 2026
4d31e77
Frame dynamic policies as allow once then allow always
emostov Aug 13, 2026
03474b9
Drop coordinator ciphertext sentence from secrets overview
emostov Aug 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,10 @@
"group": "Solution",
"pages": [
"solutions/key-management/encryption-key-storage",
"solutions/key-management/enterprise-disaster-recovery"
"solutions/key-management/enterprise-disaster-recovery",
"solutions/key-management/programmable-credential-access",
"solutions/key-management/api-key-storage",
"solutions/key-management/mpc-keyshare-storage"
]
}
]
Expand Down Expand Up @@ -359,7 +362,8 @@
},
"features/wallets/pregenerated-wallets",
"features/wallets/claim-links",
"features/wallets/aa-wallets"
"features/wallets/aa-wallets",
"features/secrets"
]
},
{
Expand Down
100 changes: 100 additions & 0 deletions features/secrets.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
---
title: "Secret storage"
description: "Import, store, and export arbitrary secrets (passwords, credit cards, API keys) with policy-gated, end-to-end encrypted access."
tag: "Beta"
---

import { FeatureCard } from '/snippets/feature-card.mdx'
import { SolutionCard } from '/snippets/solution-card.mdx'
import { SecretsBetaCallout } from '/snippets/secrets-beta-callout.mdx'

<SecretsBetaCallout />

Turnkey Secrets lets you store arbitrary sensitive data (passwords, credit card details, API keys, SSNs) encrypted end-to-end between your client and Turnkey's [secure enclaves](/security/secure-enclaves). The [policy engine](/features/policies/overview) evaluates every export, so you control exactly who can retrieve a secret, under what conditions, and with how many approvals. We designed the secret storage API for flexibility and programmability.

Plaintext only ever exists inside the enclave and on the client that imported or exported it.
## How it works

The Secrets methods use the same enclave secure-channel pattern as [wallet import](/features/wallets/import-wallets) and [wallet export](/features/wallets/export-wallets). Every transfer is HPKE-encrypted to a single-use target key, so plaintext appears only inside the enclave and on the client holding the matching private key. See [Enclave secure channels](/security/enclave-secure-channels) for the canonical protocol details.

What is specific to Secrets:

- **Import**: your client encrypts the secret to a single-use ingress target key minted inside the enclave and submits only ciphertext. The enclave re-encrypts it for storage at rest and deletes the ingress key.
- **Export**: the export request carries an ephemeral P-256 target public key. After policy evaluation approves the request, the enclave re-encrypts the secret to that key. The recipient key is fully configurable: it can belong to the requester, to another agent or service, or to a party that isn't an approver at all. Only the holder of the matching private key can decrypt the result; the payload is useless to anyone else, including the approvers themselves.
- **Batch export is all-or-nothing**: the request succeeds only if every policy evaluation returns `ALLOW`. A `DENY`, or any evaluation without an `ALLOW` outcome, rejects the entire batch. Turnkey fails closed and never exports part of a batch.

## Static properties

Secrets are created with optional **static properties**: string key-value pairs that are immutably bound to the secret and visible to the policy engine. They let you write export policies against classes of secrets instead of individual IDs:

```json
{
"policyName": "Only the payments agent can export credit cards",
"effect": "EFFECT_ALLOW",
"consensus": "approvers.any(u, u.tags.contains('payment-agent'))",
"condition": "secret.static_properties['kind'] == 'creditCard' && activity.type == 'ACTIVITY_TYPE_EXPORT_SECRETS'"
}
```

## Importing a secret

The `importSecret` method in [`@turnkey/sdk-server`](/sdks/typescript-sdk) and [`@turnkey/core`](/sdks/typescript-sdk) handles the full flow. It initializes the ingress key, verifies the enclave signature, encrypts the secret, and submits the ciphertext:

```typescript
const secretId = await turnkey.apiClient().importSecret({
plaintext: JSON.stringify({ number: "4242...", exp: "11/29", cvv: "123" }),
name: "corporateVisa",
staticProperties: {
kind: "creditCard",
requiresConsensus: "true",
},
});
```

For sensitive material you want wiped from memory after encryption, pass a `Uint8Array` instead of a string. The SDK zeroizes the buffer after it produces the ciphertext.

Under the hood this calls [init_import_secrets](/api-reference/activities/init-import-secrets) and [import_secrets](/api-reference/activities/import-secrets).

## Exporting a secret

`exportSecret` generates the ephemeral keypair, submits the export activity, decrypts the result, and zeroizes the key. It is a single call when policy allows the caller to export unilaterally:

```typescript
const plaintext = await turnkey.apiClient().exportSecret({
secretId,
});
```

If the export requires additional approvals, `exportSecret` throws a consensus-needed error. For multi-party flows, including multiple agent instances that co-sign the same export with session keys, use the proposal SDK helpers described in [Programmable credential access](/solutions/key-management/programmable-credential-access).

## Listing secrets

[list_secrets](/api-reference/queries/list-secrets) returns metadata: IDs, names, static properties, and creation timestamps:

```typescript
const { secrets } = await turnkey.apiClient().listSecrets({});
```

## Multi-party approval

Because export is an activity, it composes with everything the policy engine supports: [consensus](/features/policies/overview) across durable users, tag-based approver requirements, and [root quorum](/features/users/root-quorum). Model browser and payment agent roles as separate Turnkey users, then use session keys to authenticate their ephemeral instances. Policy can require both roles to approve before a credit card leaves the enclave, while the payload stays encrypted to only one instance. This makes credential delegation easy to model without treating each ephemeral agent instance as a separate user.

## Security model

Turnkey is a signing and encryption platform running inside secure enclaves, originally built to secure billions of dollars in digital assets. Secret storage is built from the same primitives:

- **End-to-end encryption**: plaintext exists only in enclave memory and on your client. Transport in both directions uses HPKE to single-use P-256 target keys.
- **Authenticated storage**: at-rest ciphertext is AES-256-GCM under a per-secret key derived from the enclave quorum key. The organization, secret ID, and cipher suite are bound into the authenticated data, so no one can substitute ciphertext across secrets or organizations.
- **Signed provenance**: the enclave quorum key signs every stored secret and ingress key. Enclaves refuse anything they didn't produce.
- **Quantum resistant internally, agile in transit**: secrets rest under AES-256-GCM, a quantum resistant cipher. The transport cipher suite is a field in import and export requests, designed to be extended over time, so Turnkey can adopt new transport protocols as they mature.
- **Forward secrecy**: ingress and egress target keys are single-use. Compromising one exposes at most one payload.
- **Full auditability**: every import, export, and approval is an activity that is attributed to the authenticating credential, logged, and queryable.

## Next steps

<div style={{display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '12px'}}>
<SolutionCard title="Programmable credential access" icon="programmable-credential-access" href="/solutions/key-management/programmable-credential-access" description="A password manager built for machines: policy-gated credential access for humans, services, and AI agents." />
<SolutionCard title="API key storage" icon="api-key-storage" href="/solutions/key-management/api-key-storage" description="Programmatically store and gate access to your most sensitive API keys." />
<SolutionCard title="MPC keyshare storage" icon="mpc-keyshare-storage" href="/solutions/key-management/mpc-keyshare-storage" description="Enclave-protected, policy-gated backup and recovery for MPC keyshare bundles." />
<FeatureCard title="Policy Engine" icon="file-shield-02" href="/features/policies/overview" description="Gate secret export on identity, static properties, approval counts, and tags." />
<FeatureCard title="Secure Enclaves" icon="cpu-chip-01" href="/security/secure-enclaves" description="How Turnkey protects secrets inside hardware-backed enclaves." /></div>
8 changes: 8 additions & 0 deletions images/solutions/dark/api-key-storage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions images/solutions/dark/mpc-keyshare-storage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions images/solutions/dark/programmable-credential-access.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions images/solutions/light/api-key-storage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions images/solutions/light/mpc-keyshare-storage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions images/solutions/light/programmable-credential-access.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions snippets/secrets-beta-callout.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const SecretsBetaCallout = () => (
<Warning>
The Secrets API is currently in closed beta.{" "}
<a href="https://www.turnkey.com/contact-us">Contact us</a> to get
onboarded.
</Warning>
);
Loading