Skip to content
3 changes: 2 additions & 1 deletion docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,8 @@
"solutions/key-management/encryption-key-storage",
"solutions/key-management/enterprise-disaster-recovery",
"solutions/key-management/programmable-credential-access",
"solutions/key-management/high-security-api-key-storage"
"solutions/key-management/api-key-storage",
"solutions/key-management/mpc-keyshare-storage"
]
}
]
Expand Down
26 changes: 14 additions & 12 deletions features/secrets.mdx
Original file line number Diff line number Diff line change
@@ -1,27 +1,28 @@
---
title: "Secret Storage"
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'

<Info>
**Closed beta**: the Secrets API is currently in closed beta. [Contact us](https://www.turnkey.com/contact-us) to get onboarded.
</Info>
<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. Turnkey's coordinator, database, and public API only ever see ciphertext.

## How it works

**Import**: Turnkey mints a single-use ingress target key inside the enclave, signed by the enclave's quorum key. Your client verifies that signature, encrypts the secret to the target key using HPKE, and submits the ciphertext. The enclave decrypts it, re-encrypts it for storage at rest under a quorum-key-derived key, and deletes the ingress key.
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.

**Export**: the export request carries an ephemeral P-256 target public key, and after policy evaluation approves the request, the enclave decrypts the stored secret and re-encrypts it to that key. The target 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 private half can decrypt the result. The export payload is useless to anyone else, including the approvers themselves.
What is specific to Secrets:

For a batch export, the request succeeds only if every policy evaluation returns `ALLOW`. A `DENY`, or any evaluation without an `ALLOW` outcome, rejects the entire batch. Turnkey never exports part of a batch.
- **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

Expand All @@ -32,7 +33,7 @@ Secrets are created with optional **static properties**: string key-value pairs
"policyName": "Only the payments agent can export credit cards",
"effect": "EFFECT_ALLOW",
"consensus": "approvers.any(u, u.tags.contains('payment-agent'))",
"condition": "activity.type == 'ACTIVITY_TYPE_EXPORT_SECRETS' && secret.static_properties['kind'] == 'creditCard'"
"condition": "secret.static_properties['kind'] == 'creditCard' && activity.type == 'ACTIVITY_TYPE_EXPORT_SECRETS'"
}
```

Expand Down Expand Up @@ -65,7 +66,7 @@ const plaintext = await turnkey.apiClient().exportSecret({
});
```

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).
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

Expand All @@ -84,7 +85,7 @@ Because export is an activity, it composes with everything the policy engine sup
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, with the organization, secret ID, and cipher suite bound into the authenticated data, so no one can substitute ciphertext across secrets or organizations.
- **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.
Expand All @@ -93,7 +94,8 @@ Turnkey is a signing and encryption platform running inside secure enclaves, ori
## 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="High Security API Key Storage" icon="high-security-api-key-storage" href="/solutions/key-management/high-security-api-key-storage" description="Programmatically store and gate access to your most sensitive API keys." />
<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>
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.
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.
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