Tinfoil Verifier
Portable remote-attestation verifier & secure HTTP client for enclave-backed services.

Overview
Tinfoil Verifier is a Go library that verifies the integrity of remote enclaves (AMD SEV-SNP & Intel TDX) and binds that verification to TLS connections.βIt also ships a drop-in secure http.Client that performs attestation transparently.
Features
- π Hardware-rooted remote attestation for SEV-SNP & TDX
- π¦ Self-contained with no external attestation service
- πΈ Secure HTTP client with automatic certificate pinning
- π‘ Sigstore integration for reference measurements
- π§βπ» WASM build for browser/nodejs
Installation
go get github.com/tinfoilsh/verifier@latest
Note Until go-sev-guest upstreams a required feature, add the temporary replace directive:
go mod edit -replace github.com/google/go-sev-guest=github.com/tinfoilsh/go-sev-guest@v0.0.0-20250704193550-c725e6216008
Quick Start
import "github.com/tinfoilsh/verifier/client"
// 1. Create a client
tinfoilClient := client.NewSecureClient("enclave.example.com", "org/repo")
// 2. Perform HTTP requests β attestation happens automatically
resp, err := tinfoilClient.Get("/api/data", nil)
To verify manually and expose the verification state:
groundTruth, err := tinfoilClient.Verify() // β³ returns *client.GroundTruth with details
Secure HTTP Client
The client package wraps net/http and adds:
- Attestation gate β the first request verifies the enclave.
- TLS pinning β the enclave-generated certificate fingerprint is pinned for the session.
- Round-tripping helpers β convenience
Get, Post methods.
headers := map[string]string{"Content-Type": "application/json"}
body := []byte(`{"key": "value"}`)
resp, err := tinfoilClient.Post("/api/submit", headers, body)
For advanced usage retrieve the underlying *http.Client:
httpClient, err := tinfoilClient.HTTPClient()
Remote Attestation
Tinfoil Verifier currently supports two platforms:
| Platform |
Technique |
Docs |
| AMD SEV-SNP |
VCEK certificates & SNP report validation |
AMD Spec |
| Intel TDX |
TDX quote validation & TD report checks |
Intel Guide |
Verification Flow
sequenceDiagram
participant Client
participant Enclave
participant TrustRoot
participant Sigstore
Client->>Enclave: Request attestation
Enclave-->>Client: Report + TLS pubkey
Client->>TrustRoot: Verify signature chain
Client->>Sigstore: Fetch reference measurement
Client->>Client: Compare measurements & pin cert
JavaScript / WASM
This verifier can be compiled to WebAssembly to run directly in web browsers. Built from the same Go source code, it's compiled to WebAssembly to run natively in browsers without requiring server-side verification.
When new versions are tagged, our GitHub Actions workflow automatically:
- Compiles the Go verification logic to WebAssembly
- Generates versioned WASM files with integrity guarantees
- Deploys them to GitHub Pages for secure, cached distribution
- Updates version tags so clients always load the correct module
This ensures that browser-based applications can perform an audit of Tinfoil without additional infrastructure dependencies.
Usage: This WASM verifier is integrated into Tinfoil Chat to provide transparent verification of the Tinfoil private chat.
Quick Start
The WASM verifier is hosted at:
https://tinfoilsh.github.io/verifier/tinfoil-verifier.wasm
Include the Go WASM runtime and load the verifier:
<script src="wasm_exec.js"></script>
<script>
// Load the WASM verifier
const go = new Go();
WebAssembly.instantiateStreaming(
fetch("https://tinfoilsh.github.io/verifier/tinfoil-verifier.wasm"),
go.importObject
).then((result) => {
go.run(result.instance);
// Complete end-to-end verification (recommended)
verify("inference.example.com", "tinfoilsh/confidential-llama-qwen")
.then(groundTruthJSON => {
const groundTruth = JSON.parse(groundTruthJSON);
console.log("TLS Public Key:", groundTruth.tls_public_key);
console.log("HPKE Public Key:", groundTruth.hpke_public_key);
console.log("Verification successful!");
})
.catch(error => {
console.error("Verification failed:", error);
});
});
</script>
Complete Verification (Recommended)
Use the verify() function for complete end-to-end verification that performs all steps atomically:
// Complete end-to-end verification
const groundTruthJSON = await verify("inference.example.com", "tinfoilsh/confidential-llama-qwen");
const groundTruth = JSON.parse(groundTruthJSON);
// The ground truth contains:
// - tls_public_key: TLS certificate fingerprint
// - hpke_public_key: HPKE public key for E2E encryption
// - digest: GitHub release digest
// - code_measurement: Expected code measurement from GitHub
// - enclave_measurement: Actual runtime measurement from enclave
// - hardware_measurement: TDX platform measurements (if applicable)
// - code_fingerprint: Fingerprint of code measurement
// - enclave_fingerprint: Fingerprint of enclave measurement
console.log("TLS Public Key:", groundTruth.tls_public_key);
console.log("HPKE Public Key:", groundTruth.hpke_public_key);
console.log("Verification successful - measurements match!");
The verify() function automatically:
- Fetches the latest release digest from GitHub
- Verifies code provenance using Sigstore/Rekor
- Performs runtime attestation against the enclave
- Verifies hardware measurements (for TDX platforms)
- Compares code and runtime measurements using platform-specific logic
If any step fails, an error is thrown with details about which step failed.
Manual Step-by-Step Verification
For more control, you can perform individual verification steps:
// 1. Verify enclave attestation
const enclaveResult = await verifyEnclave("inference.example.com");
console.log("TLS Public Key:", enclaveResult.tls_public_key);
console.log("HPKE Public Key:", enclaveResult.hpke_public_key);
console.log("Enclave measurement:", enclaveResult.measurement);
// 2. Verify code matches GitHub release
const repo = "tinfoilsh/confidential-llama-qwen";
const digest = "sha256:abc123...";
const codeMeasurementJSON = await verifyCode(repo, digest);
const codeMeasurement = JSON.parse(codeMeasurementJSON);
console.log("Code measurement:", codeMeasurement);
// 3. Compare measurements manually (note: requires platform-specific comparison logic)
const enclaveMeasurement = JSON.parse(enclaveResult.measurement);
// Platform-specific comparison would be needed here
Auditing Guide
- Certificate chain β see
/attestation/genoa_cert_chain.pem
- Attestation logic β start with
/attestation/attestation.go and platform files:
- Measurement matching β inspect
/sigstore/sigstore.go
Reporting Vulnerabilities
Please report security vulnerabilities by emailing contact@tinfoil.sh
We aim to respond to security reports within 24 hours and will keep you updated on our progress.