Security
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.
At any time, you can request an attestation document from Vault. This attestation document is signed by AWS (independently verifiable).
The attestation document allows you to verify 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.
The code running inside a nitro enclave is an Enclave Image File (EIF). The EIF has unique PCR values which will change upon tampering.
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
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.
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.
Chain of Trust Verification
Armed with proof that the Vault service is running untampered code, you can audit the code to ensure Vault behaves as expected.
For example: how can you verify that Vault is not lying about who can access it’s keys?
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.
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.
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.
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.
End to End Encryption
Every sensitive request to Vault is made to the /v1/enclave/post
endpoint with a payload that looks like this:
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.
Vault uses the xChaCha20Poly1305 cryptographic cipher, combined with the x25519dalek for zero round trip key-exchange.
The client queries the Vault’s xChaCha20Poly1305 public-key from the GET api/v1/enclave
endpoint.
The client generates a random 32 byte ephemeral secret key (and stores it to decrypt the response too)
The client derives a shared secret using xChaCha20Poly1305:
The client derives an encryption key from the shared_secret
using HKDF
The client generates a random 24 byte nonce
The client generates the ciphertext
using xChaCha20Poly1305 with the random nonce, and the derives encryption key
The generated ciphertext, nonce, and the public key to the ephemeral secret are all hex encoded and sent as the payload
The response also arrives in the same payload format. We just perform the steps in reverse now.
- Use
x25519dalek
diffie_hellman
to derive ashared_secret
from the:- private key we used for sending the request
- the public key returned in the response
- HKDF the
shared_secret
to get theencryption_key
- Use the
nonce
in the response (which Vault randomly generates) + theshared_secret
with xChaCha20Poly1305 to decrypt your payload.