Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
ea21a9a
feat(api): replace enclave keys route with POST /v1/enclave-assignment
kilianglas Aug 18, 2026
97bbfc9
feat(client): add Nitro attestation verifier ported from bedrock
kilianglas Aug 18, 2026
8e3fbca
feat(client): add the assignment HTTP client and CLI
kilianglas Aug 18, 2026
1e3230d
feat(e2e): verify attestations instead of parsing them
kilianglas Aug 18, 2026
112970f
refactor: tighten comments and drop redundant tests
kilianglas Aug 18, 2026
a0e0d9d
refactor(client): drop the verifier-client binary
kilianglas Aug 18, 2026
cecf4bd
refactor(client): introduce ClientConfig and a reusable request path
kilianglas Aug 19, 2026
ee05046
refactor(client): configure the client the way world-id-protocol does
kilianglas Aug 19, 2026
405db17
refactor: simplify the client and dedup the route error handling
kilianglas Aug 19, 2026
a71b7fa
refactor: cleanup
kilianglas Aug 19, 2026
37d6074
fix(client): reject empty PCR configurations instead of matching them
kilianglas Aug 19, 2026
39d29f3
fix(api): restore the doc comment missing_docs requires
kilianglas Aug 19, 2026
c747baf
docs(client): add the MIT notice the ported code requires
kilianglas Aug 19, 2026
3135e9c
refactor(api): centralize error mapping and test routes through the r…
kilianglas Aug 19, 2026
8da712f
refactor(client): rename Client to FaceVerifierClient
kilianglas Aug 19, 2026
af932d6
docs: state invariants rather than what changed
kilianglas Aug 19, 2026
b7065c8
Merge branch 'main' into kilianglas/enclave-assignment
kilianglas Aug 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
972 changes: 943 additions & 29 deletions Cargo.lock

Large diffs are not rendered by default.

19 changes: 18 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
[workspace]
members = ["api", "e2e/enclave-match-e2e", "secure-enclave", "shared/enclave-types"]
members = [
"api",
"client/verifier-client",
"e2e/enclave-match-e2e",
"secure-enclave",
"shared/enclave-types",
]
resolver = "3"

[workspace.package]
Expand All @@ -13,23 +19,34 @@ publish = false
anyhow = "1.0"
ark-babyjubjub = { package = "taceo-ark-babyjubjub", version = "0.5" }
async-trait = "0.1"
# Attestation crates are pinned to bedrock's versions so the two verifiers cannot drift.
aws-nitro-enclaves-nsm-api = { version = "0.4", default-features = false }
axum = "0.8"
base64 = "0.22"
ciborium = "0.2"
coset = "0.4.2"
crypto_box = { version = "0.9.1", default-features = false, features = ["getrandom"] }
eddsa-babyjubjub = { package = "taceo-eddsa-babyjubjub", version = "0.5" }
enclave-types = { path = "shared/enclave-types" }
face-engine = { git = "https://github.com/worldcoin/biometric-engines", rev = "face-engine-v2.16.0", default-features = false, features = ["tract"] }
hex = { version = "0.4", default-features = false, features = ["alloc"] }
hex-literal = "1.1"
image = { version = "=0.25.6", default-features = false, features = ["jpeg", "png", "webp"] }
p384 = { version = "0.13", default-features = false, features = ["ecdsa", "sha384"] }
pontifex = { version = "1.1.2", default-features = false }
rand = "0.8"
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
serde = { version = "1.0", features = ["derive"] }
serde_bytes = "0.11"
serde_json = "1.0"
sha2 = { version = "0.10", default-features = false }
thiserror = "2"
tokio = { version = "1.48", features = ["macros", "net", "rt-multi-thread", "signal", "time"] }
tower = { version = "0.5", features = ["util"] }
tower-http = { version = "0.6", features = ["trace"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
url = { version = "2", features = ["serde"] }
verifier-client = { path = "client/verifier-client" }
webpki = "0.22"
x509-cert = "0.2.5"
48 changes: 45 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ Rust workspace for the embedding verifier API and secure enclave.

```text
embedding-verifier/
├── api/ # Axum HTTP API
└── secure-enclave/ # Secure enclave process
├── api/ # Axum HTTP API (the untrusted host)
├── client/verifier-client/ # Attestation-verifying client
└── secure-enclave/ # Secure enclave process
```

## Development
Expand All @@ -22,13 +23,54 @@ cargo build
cargo test --all

# Run the API on http://localhost:8000
RUST_LOG=info cargo run --bin api
# ENCLAVE_CID and ENCLAVE_PORT are required; the process panics without them.
RUST_LOG=info ENCLAVE_CID=16 ENCLAVE_PORT=1000 cargo run --bin api
curl http://localhost:8000/health

# Run the secure enclave placeholder
RUST_LOG=info cargo run --bin secure-enclave
```

## Enclave assignment

`POST /v1/enclave-assignment` returns the enclave's encryption-key attestation and nothing
else:

```json
{ "attestation": "<base64 COSE_Sign1>" }
```

The enclave's identity (`module_id`) and expiry (the leaf certificate's `notAfter`) are read
from the document *after* verifying it, never from fields the untrusted host could set.

`verifier-client` verifies the document — the COSE signature, the certificate chain up to the
pinned AWS Nitro root, and the expected measurements. It is configured by a JSON file, in the
shape `world-id-protocol` uses for an authenticator:

```json
{
"host_url": "http://localhost:8000",
"allowed_pcr_configs": [
[{ "index": 0, "value": "<PCR0 hex from scripts/build-eif.sh>" }]
],
"max_attestation_age_millis": 3600000,
"allow_debug_measurements": false
}
```

Only `host_url` and `allowed_pcr_configs` are required; the rest have defaults. A
configuration that pins no measurements is rejected — with nothing pinned, verification only
proves a document came from *some* enclave. A `--debug-mode` enclave reports all-zero PCRs and
its memory is readable from the parent instance, so it is rejected unless
`allow_debug_measurements` is set.

`enclave-match-e2e` reads that file from `VERIFIER_CONFIG` and fetches its encryption key
through the host, exercising the assignment route and the client together:

```bash
VERIFIER_CONFIG=./client.json cargo run --bin enclave-match-e2e -- <credential> <live> <challenge>
```

## Nitro-enabled development host

Use an Amazon Linux 2023 EC2 instance type that supports Nitro Enclaves and launch it with
Expand Down
1 change: 1 addition & 0 deletions api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@ tracing.workspace = true
tracing-subscriber.workspace = true

[dev-dependencies]
http-body-util = "0.1"
serde_json.workspace = true
tower.workspace = true
Loading
Loading