For the complete documentation index, see llms.txt. This page is also available as Markdown.

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:

File
Contents

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

1

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.

2

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.

3

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:

Field
Description

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:

  1. Verify the JWT signature (Google signed it) - see Step 3 above.

  2. Confirm the JWT's aud claim equals the returned verificationPublicKey - this is what proves the key was generated inside the TEE.

  3. 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.js createVerify defaults 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:

  1. Re-fetch /attestation with a new nonce.

  2. Verify the new JWT signature and confirm its aud matches the new verificationPublicKey.

  3. Retry verification with the updated key.

Only treat the response as invalid if verification still fails after re-attesting.

Last updated