Attestation
The enclave exposes a GET /attestation endpoint that lets anyone verify what code is actually running inside the Trusted Execution Environment.
What is attestation?
The enclave runs inside a GCP Confidential VM (AMD SEV-SNP), which means its memory is encrypted at the hardware level and inaccessible to the host, Google, or Hinkal's own infrastructure. GCP's Confidential Space service can issue a signed JWT - called an attestation token - that proves:
The exact Docker image digest that is currently running
That it is running inside a genuine AMD SEV-SNP hardware enclave
That secure boot is enabled and debugger access is disabled
This JWT is signed by Google's Confidential Space attestation service and verifiable against Google's public OIDC keys.
The Hinkal-API-Enclave repository
Every time Hinkal deploys a new version of the enclave-api, the following files are automatically published to github.com/Hinkal-Protocol/Hinkal-API-Enclave:
digest.txt
SHA256 digest of the deployed Docker image + the git commit SHA it was built from (both signed together)
bundle.json
Sigstore/cosign bundle: signature, Fulcio certificate, and Rekor transparency log inclusion proof
enclave-api-src/
Full TypeScript source of the enclave-api at that commit
enclave-api-dist/
Compiled JavaScript bundle (enclave-api + all shared libraries)
enclaveApiGcp.yaml
The GitHub Actions workflow used to build, sign, and deploy
How to verify
Verify the cosign bundle
Install cosign, download digest.txt and bundle.json from the Hinkal-API-Enclave repository, then run:
This proves that digest.txt (containing both the image digest and the commit SHA) was signed by a GitHub Actions workflow in the Hinkal-Protocol org, and that the signing event is recorded in Rekor's public transparency log.
Verify the running enclave matches the digest
Call the attestation endpoint with a UUID nonce you generate yourself:
Response:
imageDigest is extracted from submods.container.image_digest in the decoded JWT. Compare it to the first line of digest.txt from the Hinkal-API-Enclave repository. If they match, the running enclave is the image whose provenance you verified in Step 1.
verificationPublicKey is an EC P-256 public key generated by the enclave at startup. It is embedded as the aud claim in the JWT — because the JWT is signed by Google's attestation service, this proves the key was generated inside the TEE and belongs to this specific enclave instance.
Verify the JWT signature
The JWT is signed by Google's Confidential Space attestation service using RS256. Decode the payload to inspect it:
Key fields to inspect:
submods.container.image_digest
Digest of the running image — matches digest.txt line 1
eat_nonce
Your nonce — proves this token was issued for your specific request
aud
The enclave's verificationPublicKey — proves the key was generated inside the TEE
hwmodel
GCP_AMD_SEV_SNP — confirms AMD SEV-SNP hardware
secboot
true — secure boot enabled
dbgstat
disabled-since-boot — debugger access disabled
iss
https://confidentialcomputing.googleapis.com — Google issued this token
To verify the JWT signature cryptographically, fetch Google's public keys and check the RS256 signature over the JWT header and payload. The signing keys are published at:
This endpoint is documented in Google's Confidential Space attestation token validation reference.
Find the full Node.js example in the Hinkal-API-Enclave repository README.
Using the public key to verify Hinkal API responses
Every Hinkal API endpoint returns an x-hinkal-response-signature response header - a base64-encoded ECDSA SHA-256 signature over the raw JSON response body, signed with the EC P-256 private key corresponding to verificationPublicKey.
Every authenticated request includes a per-request nonce (UUID) in the body or query string.
The enclave echoes this nonce back in the response body. The echoed nonce, covered by
x-hinkal-response-signature, binds the response to the specific request and proves the enclave processed
that exact request - not a cached or replayed response.
Important: you cannot simply fetch verificationPublicKey from /attestation and use it directly - that would only prove you talked to a server that returned a key, not that the key came from the TEE. Before trusting the key you must:
Verify the JWT signature (Google signed it) - see Step 3 above.
Confirm the JWT's
audclaim equals the returnedverificationPublicKey- this is what proves the key was generated inside the TEE.Store the verified key and use it for all subsequent response verification.
Only after these checks does a valid x-hinkal-response-signature constitute proof that the response was produced by the TEE.
The signature uses IEEE P1363 encoding.
dsaEncoding: 'ieee-p1363'is required - Node.jscreateVerifydefaults to DER.
The same verification code applies unchanged to WaaS API responses — just fetch a WaaS route (e.g. https://api.hinkal.io/waas/create-wallet) in step 3 instead.
The full trust chain
Key rotation
You do not need to call /attestation before every request. Fetch verificationPublicKey once at startup (or on first use), verify the JWT, and store the key. Reuse it for all subsequent response verification - there is no need to re-attest on each call.
verificationPublicKey does change whenever the server restarts, so the stored key can become outdated over time. If response signature verification fails, treat it as a potential key rotation and:
Re-fetch
/attestationwith a new nonce.Verify the new JWT signature and confirm its
audmatches the newverificationPublicKey.Retry verification with the updated key.
Only treat the response as invalid if verification still fails after re-attesting.
Last updated