Verify a seal yourself
Rebuild the digest from the public fields and recover the signer. Twenty lines, no trust in the endpoint.
A seal's signature is over a string you can rebuild from the seal's own public fields. If the recovered address is the auditor's, the auditor signed exactly these answers and exactly this review for exactly this hash.
The digest
zkcheck:v1
<hash, lower-case>
<answers: "01:1,02:1,03:0,…", 1 pass, 0 fail, - not run>
<keccak256(review text) or "0x" if none>
joined with \n, then keccak256 of the UTF-8 bytes. The auditor signs that 32-byte digest as an EIP-191 personal message (personal_sign / viem's signMessage({ message: { raw } })).
The script
import { keccak256, recoverMessageAddress, toHex } from "viem";
const WORKER = "https://<worker>"; // published on zkcheck.dev
const AUDITOR = "0x…"; // the auditor's address, from zkcheck.dev or GET /
const hash = process.argv[2];
const seal = await fetch(`${WORKER}/seals/${hash}`).then((r) => r.json());
const answers = seal.checks.map((c) => `${c.id}:${c.pass === null ? "-" : c.pass ? "1" : "0"}`).join(",");
const reviewHash = seal.review ? keccak256(toHex(seal.review)) : "0x";
const digest = keccak256(toHex(`zkcheck:v1\n${seal.hash.toLowerCase()}\n${answers}\n${reviewHash}`));
const signer = await recoverMessageAddress({ message: { raw: digest }, signature: seal.signature });
console.log(signer === seal.auditor ? "signature matches the seal's auditor" : "MISMATCH");
console.log(signer.toLowerCase() === AUDITOR.toLowerCase() ? "and it is the zkCheck auditor" : "but it is not the auditor you expected");
pnpm add viem
pnpm tsx verify.ts 0xb857b3aa…
Also check the hash
The seal says it is about hash. Confirm the token you care about has that code:
const code = await client.getCode({ address });
console.log(keccak256(code!) === seal.hash);
If it does not, the seal is about something else, whatever the seal's name says.
What this proves, and what it does not
It proves the auditor signed these fields. It does not prove the answers are right; for that, the stake (when the registry exists) and the proof (when the checks run in a zkVM) are the layers. It does prove that nobody between the auditor and you changed a false to a true, which is the thing a badge on someone else's website cannot promise on its own.
In a build step
A launchpad that displays badges can run this once per seal at build time and refuse to display any that fails. The whole thing is one HTTP call and one ecrecover.