Skip to content

Commit f05bfa9

Browse files
committed
vault docs complete
1 parent 99f34b4 commit f05bfa9

File tree

7 files changed

+210
-5
lines changed

7 files changed

+210
-5
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { Details } from "@doc";
2+
3+
# Vault FAQs
4+
5+
<Details summary="Why does thirdweb offer me the ability to backup my recovery code?">
6+
***thirdweb vault is entirely non-custodial.***
7+
8+
This means that if you lose your keys and your recovery code, *you have no means of recovering any of your EOAs, any funds stored in them, or any smart accounts or other contracts your EOAs might own.*
9+
10+
thirdweb *cannot* help you in such a scenario.
11+
12+
While storing all keys with yourself is the most secure way to use thirdweb vault, the lack of recovery options might be inconvenient or scary. As a compromise, when used with Engine Cloud, thirdweb allows you to store a backup of your rotation code with us. This way if you ever lose your admin key, we can let you rotate it as long as you can access the project this vault was initialised for.
13+
14+
***is this still non-custodial?***
15+
16+
yes.
17+
18+
thirdweb cannot access any of your wallets or created entities with your rotation code alone.
19+
20+
a “rotation-code” only allows the “service account rotate” operation, which will invalidate your admin key and all existing access tokens.
21+
22+
There is no way for thirdweb to “silently” access your vault without your knowledge with only the recovery code.
23+
24+
Rotating your engine’s vault account through a thirdweb-stored rotation code requires a signature from your wallet. You will also be able to see rotation history, the thirdweb account which initiated this rotation, and their wallet signature.
25+
</Details>

apps/portal/src/app/vault/get-started/page.mdx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,10 @@ import { createMetadata } from "@/components/Document";
66
<Callout variant="info" title="Engine Vault">
77
Vault is currently in beta as a part of Engine Cloud and will expand into more products. [Learn how to setup and manage your Vault with thirdweb Engine.](/engine/get-started)
88

9-
</Callout>
9+
</Callout>
10+
11+
## Manage Vault
12+
13+
To manage your Vault, navigate to **Engine > Vault** in your project dashboard.
14+
15+
Here you can create and manage access tokens and rotate your admin key.
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { Callout } from "@doc";
2+
3+
# Understanding Vault Keys
4+
5+
## Vault Admin Key
6+
7+
This is an admin key that grants access to every operation on every server wallet. It is also used to create access tokens.
8+
9+
Keep the admin key securely and distribute it only between trusted team members (who you would consider admins, and need to perform administrative functions). Do not send this key to external services, only send it directly to vault (via E2E encryption), or use it in the thirdweb dashboard where it's always securely stored in your browser memory and only used to communicate with the vault through e2e encryption. Your admin keys are never revealed to anyone other than vault itself, and you.
10+
11+
## Access Tokens
12+
13+
Access Tokens are created using the admin key. Access tokens support flexible policies that allow you to restrict what it can do. It can be scoped by:
14+
15+
1. operation type (eg signMessage or createEoa)
16+
2. operation payload (only allow specific types of transactions to be signed like restricting by chainId, toAddress, or max value)
17+
3. entity, ie, which EOAs can this access token perform operations with. Access to entities like EOAs can be scoped in 2 ways:
18+
1. **allowlist**: if you have a short list (1/2) EOAs that an access token should be able to access, you can use the allowlist
19+
2. metadata: if you have lots of entities and complex requirements for different users to access different groups of entities, you can scope by metadata. Metadata allows you to represent implicit grouping of resources and user. As an example:
20+
1. you can create multple EOAs with metadata `team: "trading-floor"`
21+
2. If you then create an access token with
22+
`metadataPatterns: { key: "team", pattern: "^trading-floor$"}` ,
23+
this access token will only be able to access EOAs with that specific metadata parameter set.
24+
3. This allows you to create different access tokens for different sets of EOAs, where each set is grouped together with a metadata pattern. Groups can overlap. If you want multiple groups of users with your org to have access to the same EOA, you can instead use metadata: `{ teams: "trading-floor, compliance" }`
25+
And now use:
26+
for trading floor:
27+
`metadataPatterns: { key: "teams", pattern: "trading-floor"}`
28+
for compliance:
29+
`metadataPatterns: { key: "team", pattern: "compliance"}`
30+
31+
This is just an example of how flexible vault’s policies can be. Patterns can be regex operators or numeric comparisons. Metadata supports arbitrary key-value as well, so you can also create other metadata fields like `purpose` or `teamId` (if you want to map it to an internal team identifier)
32+
4. An access token can be revoked instantly with your admin key.
33+
5. You can share access tokens with all members of your team. There are multiple ways you should be sharing these, depending on your team and organisation structure:
34+
1. If you have distinct teams within your org that don't have overlapping needs to access EOAs, you can create team specific access tokens. Every member of a team within your org will get the same access token. If a member leaves and you want to remove their access, you can revoke the existing team access tokens, create a new access token with the same policies, and share the new token with remaining team members.
35+
2. if you have a small org, where members have large overlapping needs, you can create a single access token (scoped as minimally as possible) and share it with everyone. If a member leaves, you can revoke the existing token, create a new one, and share it with your members again.
36+
3. for the most granular permissioning, you can create a distinct access token for every member of your team with policies restricted to exactly what they need. This way the token can also be revoked individually without any side-effects to the other tokens.
37+
38+
<Callout variant="info" title="Access Tokens vs Admin Key">
39+
Access tokens are for using with external services or for non-adminstrative team members. Adminstrative team members might want the ability to create new access tokens, so sharing the admin key with them is more appropriate.
40+
</Callout>
41+
42+
## Rotation code
43+
44+
The rotation code can be used to "rotate" your account. Rotating your account will:
45+
46+
1. invalidate your old admin key, returning you a new key
47+
2. invalidate the rotation code used, returning a new rotation code
48+
3. invalidate all existing access tokens that were previously created.
49+
50+
The rotation code should only be stored with the "organisation owner".
51+
52+
It can be used in disaster scenarios when you suspect you might have leaked a key.
53+
54+
It can also be used when an "administrative" team member who had access to your admin key leaves your org, and you want to revoke their access.
55+
56+
After the rotation code is used, all exsting access tokens need to be recreated and shared with your team, and the newly received admin key must be shared with your "team admins".

apps/portal/src/app/vault/page.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export const metadata = createMetadata({
1111

1212
# Vault
1313

14-
thirdweb vault is an open-source non-custodial key management service, secured with TEE architecture (AWS Nitro Enclaves) and designed for blockchain applications.
14+
Vault is an open-source non-custodial key management service, secured with TEE architecture (AWS Nitro Enclaves) and designed for blockchain applications.
1515

1616
## Features
1717

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# Security
2+
3+
## Non Custodiality
4+
5+
Vault guarantees non-custodiality through cryptography. All private and sensitive data is stored encrypted, and can only be decrypted within the secure enclave. The code running within the secure enclave is open-source, audited, and attested.
6+
7+
## Attestation
8+
9+
At any time, you can request an attestation document from Vault. This attestation document is signed by AWS (independently verifiable).
10+
11+
The attestation document allows you to [verify](https://aws.amazon.com/blogs/compute/validating-attestation-documents-produced-by-aws-nitro-enclaves/) that the code being run inside the secure enclave has not been tampered, and is the same as the open source code that you can access.
12+
13+
The code running inside a nitro enclave is an Enclave Image File (EIF). The EIF has unique PCR values which will change upon tampering.
14+
15+
In the context of AWS Nitro Enclaves, an Enclave Image File (EIF) measurement, specifically the Platform Configuration Register (PCR) values, are **cryptographic hashes that uniquely identify the enclave's image and its contents**. PCRs are used to verify that the enclave has been loaded and is running in a known, trusted state, ensuring its integrity and preventing unauthorized modification
16+
17+
The master key of the Vault can only be accessed by this exact code running inside the enclave. To verify this, you can query Vault to check the current AWS policy on the master key, and confirm that only nitro-enclaves with this specific PCR measurement have access to these resources.
18+
19+
## Verify, Don’t Trust
20+
21+
You can compile your own EIF from the Vault source-code, and retrieve PCR values. This allows you to compare the PCR values you received from Vault *against* the PCR measurements you generated yourself, proving that a hosted Vault service is running untampered code.
22+
23+
## Chain of ~~Trust~~ Verification
24+
25+
Armed with proof that the Vault service is running untampered code, you can audit the code to ensure Vault behaves as expected.
26+
27+
For example: how can you verify that Vault is not lying about who can access it’s keys?
28+
29+
You can look at the Vault code to confirm that it does indeed query the correct AWS APIs to fetch the current policies on it’s keys, and then returns it without modifications.
30+
31+
If you know the code is correct, and if you know that the service is running untampered code, then you can confirm that the correct data is being returned to you.
32+
33+
But how can you confirm that data from the Vault hasn’t been tampered by other non-enclave components your response might be coming through? To solve this, Vault uses an end to end encrypted communication protocol with perfect forward secrecy.
34+
35+
This same approach can be used to verify that all entities are always stored encrypted, and access is only granted to authorized requests. To further prevent data leakage, Vault uses HMAC hashes instead of raw identifiers to associate entities with each other in the encrypted database. This means Vault can not-only guarantee non-custodial access to entities, but also preserves privacy between entities and their owners. E2E encryption also means that all your operations and responses remain private and untampered.
36+
37+
# End to End Encryption
38+
39+
Every sensitive request to Vault is made to the `/v1/enclave/post` endpoint with a payload that looks like this:
40+
41+
```json
42+
43+
{
44+
"ephemeralPublicKey": "05d7deb3ef80f929ee6d1afdbf63d43e68ae9d1a045577cf6a2cbc29baaa5c5f",
45+
"nonce": "716d11684ed4a973ff401e9bc84db48608c1f78abdba59a2",
46+
"ciphertext": "ed0665497121ca59ef610f976f0a3beaa494c17b65ca127e72f286fa3464fde3f14e305d9fded6090bd5fd7fd2fd57d93d399619fe950d71790daec1b753d5b221d914e6e29c6734e6a38c7d237a91fea289f4812eeefae88281cc9cae8e7421ca1d81a5ac4181d889a9a082fbaf7cd5c650a2c8ccf61981d9fc3535a76733e0b00dbad4a2492c399b8a49c00f89d11283fe408754e470f5ec3579fac2aedc4c042eb75dd6804cf0fa331d5da039cfad6e36f5d00e7c6e78b5e0956a36af01761c31b0d85d90b3d15e0808a544c3f15ba1d3ae108efd36add25791ee6d27d58d9bf7c87903bbd5c54ed52c3b501eb9c67ff374308d95b7acabd7e02375fd0aab6668008583740f1883ed0c00731f732ecd4d46498939f223b1eba1c0c536cea12cf85370c17ef30fce992c129938e1f049c64c2cadafd1efc93692445c47923f6bb9ffbb8226fbf7f5bfa5a14060a2085c1df145294397a7035761c20fdac820a57ed4bdd591941a9d9804c3c92c1e5e0f60857a68516b330816c57e133b4dfcf492cdc1f9ab3d9097babd997552adbb90c871e82fbab041555f0ab4ae3fb93adf4a3ba2182d76787d58568275849595564eb10e601f7ede972f2c6d8429112f90ce4aa09177ca2811d7025100cd3621edcc8b091d2e943afdc44f91d2f60abb3daae1"
47+
}
48+
```
49+
50+
The communication protocol ensures that requests can only be decrypted by the Vault-enclave, and responses can only be decrypted by you. The protocol also provides perfect forward secrecy, meaning even if cryptographic keys for a previous request is exposed, future requests still remain non-compromised.
51+
52+
## Protocol
53+
54+
Vault uses the xChaCha20Poly1305 cryptographic cipher, combined with the x25519dalek for zero round trip key-exchange.
55+
56+
### Step 1
57+
58+
The client queries the Vault’s xChaCha20Poly1305 public-key from the `GET api/v1/enclave` endpoint.
59+
60+
### Step 2
61+
62+
The client generates a random 32 byte ephemeral secret key (and stores it to decrypt the response too)
63+
64+
### Step 3
65+
66+
The client derives a shared secret using xChaCha20Poly1305:
67+
68+
```json
69+
shared_secret = diffie_hellman(client_ephemeral_secret_key, vault_public_key)
70+
```
71+
72+
### Step 4
73+
74+
The client derives an encryption key from the `shared_secret` using HKDF
75+
76+
### Step 5
77+
78+
The client generates a random 24 byte nonce
79+
80+
The client generates the `ciphertext` using xChaCha20Poly1305 with the random nonce, and the derives encryption key
81+
82+
### Sending the Payload
83+
84+
The generated ciphertext, nonce, and the public key to the ephemeral secret are all hex encoded and sent as the payload
85+
86+
## Decrypting the Resposne
87+
88+
The response also arrives in the same payload format. We just perform the steps in reverse now.
89+
90+
1. Use `x25519dalek` `diffie_hellman` to derive a `shared_secret` from the:
91+
1. private key we used for sending the request
92+
2. the public key returned in the response
93+
2. HKDF the `shared_secret` to get the `encryption_key`
94+
3. Use the `nonce` in the response (which Vault randomly generates) + the `shared_secret` with xChaCha20Poly1305 to decrypt your payload.

apps/portal/src/app/vault/sidebar.tsx

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
import type { SideBar } from "@/components/Layouts/DocLayout";
2-
import { Key, Rocket, ShieldQuestion, Vault } from "lucide-react";
2+
import {
3+
Key,
4+
MessageCircleQuestionIcon,
5+
Rocket,
6+
ShieldQuestion,
7+
Vault,
8+
Wrench,
9+
} from "lucide-react";
310

411
export const sidebar: SideBar = {
512
name: "Vault",
@@ -18,6 +25,10 @@ export const sidebar: SideBar = {
1825
name: "Key Concepts",
1926
icon: <Key />,
2027
links: [
28+
{
29+
name: "Key Management",
30+
href: "/vault/key-concepts/key-management",
31+
},
2132
{
2233
name: "Entities",
2334
href: "/vault/key-concepts/entities",
@@ -28,7 +39,7 @@ export const sidebar: SideBar = {
2839
},
2940
{
3041
name: "Access Tokens",
31-
href: "/vault/key-concepts/accounts",
42+
href: "/vault/key-concepts/access-tokens",
3243
},
3344
{
3445
name: "Access Control",
@@ -38,8 +49,18 @@ export const sidebar: SideBar = {
3849
},
3950
{
4051
name: "Security",
41-
href: "/vault/key-concepts/security",
52+
href: "/vault/security",
4253
icon: <ShieldQuestion />,
4354
},
55+
{
56+
name: "Troubleshoot",
57+
href: "/vault/troubleshoot",
58+
icon: <Wrench />,
59+
},
60+
{
61+
name: "FAQs",
62+
href: "/vault/faqs",
63+
icon: <MessageCircleQuestionIcon />,
64+
},
4465
],
4566
};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Vault Troubleshoot Guide
2+
3+
More information coming soon.

0 commit comments

Comments
 (0)