Verify

Enclave Verification Guide

This page explains how to verify that our treasury enclave is running exactly the code we claim. AWS Nitro Enclaves provide cryptographic proof — called remote attestation — that ties a running enclave to a specific, measurable code image. No one (including us) can modify code inside the enclave without changing its measurement hash.


What is an Enclave?

An AWS Nitro Enclave is an isolated virtual machine with no persistent storage, no network access, and no interactive login — not even for the server operator. The only way to communicate with it is through a narrow, predefined API. Private keys never leave the enclave's memory.

The enclave's code is measured at launch by the Nitro hypervisor, producing a PCR0 hash — a SHA-384 fingerprint of the entire enclave image. This hash is embedded in a cryptographically signed attestation document issued by AWS, which anyone can verify.


The Three Pillars of Verification

1. Source Code

Everything that runs inside the enclave is published below. There is no additional code — the Dockerfile copies only these files into the enclave image.

Dockerfile

The enclave image is built from Dockerfile.enclave:

  • Base image: Amazon Linux 2 (multi-stage build)
  • Builder stage: Installs Python 3.8 and the minimal dependency set, then downloads and SHA-256-verifies the official AWS Nitro root certificate
  • Runtime stage: Copies only the enclave application code (no database, no API server, no watcher/sweeper). Generates a self-signed TLS certificate for the encrypted vsock channel. Verifies that mock/dev credentials are excluded from the image
  • Baked-in policy constants: Platform fee addresses (EVM, BTC, LTC, SOL), maximum fee rate, and maximum merchant count are set as ENV variables in the Dockerfile. Because these are part of the image, they are included in the PCR0 measurement — changing any fee address changes the hash, requiring an explicit update to the allowed PCR list on the host

Production safety checks baked into the build:

  • _mock_root_key.pem (dev-only mock signing key) must NOT be present — build fails if it is
  • aws_nitro_root.pem (real AWS root cert) MUST be present — build fails if it is missing
  • Plaintext provisioning endpoint is physically removed from the running server in production

Application Code

FilePurpose
enclave/server.pyFastAPI server — the only process running inside the enclave. Exposes endpoints for encrypted provisioning, policy provisioning, address derivation, and transaction signing. Enforces one-shot provisioning (mnemonic and policy cannot be changed without restarting the enclave), transaction policy validation (rejects any transaction that violates the whitelist), and rate limiting (bounds signing operations per hour). In production, insecure routes are physically removed at module load. Holds per-merchant mnemonics only in memory (never written to disk).
enclave/policy.pyTransaction policy engine. Validates every transaction before signing against a strict whitelist: only sweep transactions (deposit → treasury) and gas funding transactions (treasury → deposit) are permitted. Enforces per-chain rules for EVM (native + ERC-20), Bitcoin, Litecoin, and Solana (native SOL + SPL tokens). Rejects contract deployments, arbitrary contract calls, forbidden token instructions (approve, transferFrom, etc.), and outputs to unknown addresses. Enforces fee conservation bounds and miner fee caps. Platform fee addresses are baked into the enclave image (part of PCR0).
enclave/protocol.pyPydantic request/response models shared between enclave and host. Defines the wire format for all RPC calls including policy provisioning.
enclave/crypto.pyRSA-2048 OAEP keypair generation and encryption/decryption. The enclave generates a fresh keypair at startup; callers encrypt mnemonics with the public key before sending them in.
enclave/attestation_provider.pyAttestation abstraction. In production, calls /dev/nsm (the Nitro Security Module) to obtain a hardware-signed attestation document from the hypervisor. Verifies attestation documents by decoding CBOR/COSE_Sign1, validating the AWS certificate chain, checking PCR0, and confirming public key binding. Returns the attested public key for encrypted provisioning (prevents MITM key substitution).
enclave/attestation.pyAttestation document parsing and signature verification logic.
enclave/vsock_bridge.pyVsock-to-TCP bridge. Nitro enclaves have no TCP networking — only vsock. This bridge forwards vsock connections to the local uvicorn server.
enclave/transport.pyTLS transport layer with certificate pinning support.
enclave/nitro_defaults.pyDeployment constants (ports, paths, recommended environment variables).
signer/interface.pyAbstract signer interface (defines derive_address, sign, sign_transaction, sign_sol_transaction).
signer/local_signer.pyBIP44/SLIP-10 HD wallet implementation. Derives addresses and signs transactions for Ethereum (and all EVM chains — Polygon, BSC, Base, Arbitrum, MegaETH, Monad, HyperEVM), Bitcoin, Litecoin, and Solana. Private keys are derived in-memory from the mnemonic and never leave the process.
token_registry.pyChain and token definitions. Maps asset identifiers to chain types, contract addresses, and decimal precision. Used by the signer for multi-chain address derivation.
logging_config.pyStructured logging configuration for the enclave server.

Dependencies

The enclave uses a minimal dependency set (requirements-enclave.txt):

PackagePurpose
fastapi, uvicornHTTP server
eth-account, bip44, base58HD wallet derivation (BIP39/BIP44/SLIP-10)
pycoinBitcoin and Litecoin transaction signing
soldersSolana Ed25519 keypairs, address derivation, and signing
cryptographyRSA-OAEP encryption, TLS certificates
cbor2CBOR/COSE attestation document parsing
aws_nsm_interfaceNitro Security Module device access (/dev/nsm)
requestsHTTP client
eval_type_backportPython type-hint compatibility for Python 3.8
python-dotenvEnvironment variable loading

2. Build Instructions

To reproduce the enclave image and independently verify the PCR0 hash, run the following on a Nitro-capable EC2 instance (e.g., m5.xlarge or any .metal instance with Nitro Enclaves enabled):

Prerequisites: Docker, nitro-cli (installed via amazon-linux-extras install aws-nitro-enclaves-cli)

Shell
# Clone the repository
git clone <repo-url>
cd backend
# Build the Docker image
docker build -f Dockerfile.enclave -t enclave-signer:latest .
# Build the Enclave Image File (EIF)
nitro-cli build-enclave \
--docker-uri enclave-signer:latest \
--output-file enclave-signer.eif

The nitro-cli build-enclave command outputs JSON containing the PCR measurements:

JSON
{
"Measurements": {
"HashAlgorithm": "Sha384",
"PCR0": "<96-character hex string>",
"PCR1": "...",
"PCR2": "..."
}
}

PCR0 is the measurement that matters — it is the SHA-384 hash of the entire enclave image. Compare it to the expected value published below.

Note on reproducibility: The enclave image generates a random TLS certificate at build time, which means a fresh build will produce a different PCR0 than ours. The purpose of publishing the source code is so that anyone can audit what the enclave does — the attestation document from AWS proves that our specific build is what is actually running. Both pieces together provide the full guarantee.

How Attestation Works

When the enclave starts, the following happens:

  1. The Nitro hypervisor measures the enclave image and records the hash as PCR0
  2. The enclave generates a fresh RSA-2048 keypair in memory
  3. The enclave requests an attestation document from the hypervisor via /dev/nsm, embedding its public key
  4. The hypervisor returns a COSE_Sign1 document signed by the AWS Nitro root certificate, containing:
    • The PCR0 measurement
    • The enclave's public key
    • A certificate chain back to the AWS Nitro root CA
  5. Anyone can fetch this attestation document and verify:
    • The signature chains back to the AWS Nitro root certificate
    • The PCR0 matches the expected value published on this page
    • The public key is bound to the attestation (so you know you're encrypting secrets for this specific enclave)

This proves that the enclave is running the exact code that produced the published PCR0, and that no one — including the server operator — has tampered with it.


What This Guarantees

GuaranteeHow
Private keys never leave the enclaveNo disk, no network, no shell access. Keys exist only in volatile memory.
The code running is the code publishedPCR0 measurement is signed by AWS hardware — unforgeable.
No one can modify the enclave at runtimeNitro enclaves have no SSH, no debug port, no interactive access.
Provisioned secrets are encrypted in transitRSA-OAEP encryption with a key extracted from the attested enclave — MITM key substitution is impossible.
Plaintext provisioning is impossible in productionThe endpoint is physically removed from the server at startup.
Only whitelisted transactions are signedThe enclave validates every transaction against a strict policy before signing. Only sweeps (deposit → treasury) and gas funding (treasury → deposit) are permitted. Contract deployments, arbitrary calls, and forbidden token operations are rejected.
Fee addresses are immutablePlatform fee addresses are baked into the enclave image as environment variables. Changing them changes the PCR0 hash, requiring an explicit host-side update.
Mnemonic cannot be changed at runtimeOne-shot provisioning: once a mnemonic is loaded, re-provisioning with a different mnemonic is rejected (409) until enclave restart.
Signing is rate-limitedThe enclave enforces per-merchant rate limits on signing operations, bounding the damage from a compromised host.