Security model
A self-hosted VTA is only as trustworthy as the machine you run it on: whoever controls that host can, in principle, read its memory. An Affinidi-hosted VTA in Isolated mode, which runs in an AWS Nitro Enclave, reduces that dependency by running inside a Trusted Execution Environment (TEE), a hardware-isolated environment.
The other mode, Shared, runs on a shared network without an enclave, for evaluation and development purposes only, so the protections on this page apply to Isolated mode. For how the two compare, see Isolated and Shared modes.
In normal operation, the TEE keeps key material inside isolated memory the host cannot read, apart from the explicit export paths listed under Trust boundary, and its attestation lets you verify independently which software image is running. This is the same custody guarantee the VTI specification requires: a VTA performs key operations on a caller’s behalf rather than exporting the key for the caller to use.
Trusted Execution Environment (TEE)
In Isolated mode, the VTA runs inside an AWS Nitro Enclave. A Nitro Enclave is a hardware-isolated compute environment with no persistent storage, no interactive access, and no network interface of its own: the only way in or out is a narrow, defined channel to its parent instance. The hypervisor isolates enclave memory from the host, so key material held inside the enclave stays out of the host’s reach, even if the host is compromised.
DIDComm messages stay end-to-end encrypted all the way into the enclave.
This gives you these benefits over a conventional hosted service:
The master seed is encrypted at rest under a Key Management Service (KMS) key. In normal operation, the key’s policy releases the seed to an enclave with the correct attestation.
The software running inside the enclave is cryptographically measured at boot, so you can check which image is running yourself before you connect. See PCR0 pinning below.
PCR0 pinning
A Platform Configuration Register (PCR) is a cryptographic measurement the enclave produces at boot, covering the exact software image it is running. PCR0 measures the enclave image itself (the built software); PCR8 measures the signing certificate used to sign that image. Together they let you confirm, cryptographically, that the enclave you are about to trust is running the exact build you expect, not a substituted or tampered one.
Pinning means telling Personal Network Manager (PNM) the PCR0 value you expect before it connects. When you run the bootstrap command, PNM receives the enclave’s live attestation quote, compares its measurement against the value you pinned, and creates your Administrator DID and hands the administrator role to it only if they match exactly. The comparison happens after the VTA has accepted your one-time claim and enrolled your claim DID, so a mismatch is permanent for that VTA rather than retryable. This is a hardened Trust On First Use (TOFU) model. In plain TOFU a client records whatever identity answers first; here the first connection is additionally checked against the value you pinned, so an enclave you did not expect is refused rather than recorded as trusted.
Hardware isolation keeps the host out of enclave memory, with or without pinning. Pinning adds a check on which software image is running inside the enclave, so you know it is the build you expect rather than another image presenting the same interface.
See Bootstrap PNM against the VTA for the pinning step itself, including where to find your VTA’s PCR0 value and the exact command to run.
What the enclave guarantees
- Fail-closed on mismatch. When you pin PCR0 and the measured software does not match, PNM stops before it creates your Administrator DID, and that VTA’s one-time bootstrap stays used.
pnm bootstrap connectrequires--expect-pcr0, unless you pass the explicit--no-verify-pcr0opt-out, which prints a warning. With it, PNM still verifies the attestation quote, but accepts any genuine Nitro Enclave image. - Anti-rollback protection. When the anti-rollback anchor is configured, an external monotonic counter lets the enclave detect an older snapshot of its stored state, such as one that would restore a revoked admin, and refuse to boot from it. How far this extends against a compromised parent host depends on how the anchor is configured.
Trust boundary
A private key is never exported as a side effect of an operation, whether hosted or self-hosted: the VTA performs the operation and returns only its result. In normal operation, key material leaves the VTA only through an explicit request, for example:
- A sealed-transfer bundle, encrypted to the recipient’s key.
- A password-encrypted backup, which a super admin exports.
- A key export over DIDComm or TSP, which returns the private key itself to an admin holding the key-export capability. Keys are exportable by default, the VTA refuses to export a key marked non-exportable, and it keeps internal keys out of every export.
- On a self-hosted VTA that is not yet sealed, an operator with access to the host can export key material through the local
vtaCLI.
In Isolated mode, the master seed is generated inside the enclave on first boot. See Master seed for what this means across an enclave restart and when an encrypted backup matters.
Limits
A TEE and PCR0 pinning close specific gaps. Two limits worth knowing:
- Anti-rollback depends on configuration. It applies only when the anti-rollback anchor is configured, and it resists a parent host with root access only when the anchor also has its dedicated writer credential. See What the enclave guarantees above.
- Fully withdrawing a DID’s REST access takes two steps, not one. Deleting an access control list (ACL) entry stops the DID’s DIDComm and TSP messages and any new REST session right away, because the VTA checks each message against the ACL. A REST access token (JWT) the DID is already holding remains valid until it expires, per the session lifetime every access token has. Revoking the DID’s sessions as well closes that window on its next REST call. See Ending existing sessions immediately.
Related
Glad to hear it. Thanks for letting us know.
Sorry to hear that. Thanks for letting us know.