Independently verify ACP evidence hasn’t been altered

The AI Control Plane signs every decision it records and links each one to the one before it. This check tells you whether the evidence pack in your hands is exactly what ACP issued — or whether a record has been edited, reordered, inserted or removed since.

No account. No admin rights. Nothing to install.

It runs on the PowerShell that is already on every Windows laptop, works with no network connection, and sends nothing anywhere. You can read the whole script before you run it.


Step 1: Download the verifier

Download the verifier

Verify-AcpEvidence.ps1 — save it into the folder holding your evidence pack, alongside the evidence file.

You also need our public key, if it did not come with your pack. Download acp-verification-key.json — no account needed — and put it in the same folder.

Step 2: Run the verification

Open that folder, type powershell in the address bar, press Enter, and paste this line.

powershell -ExecutionPolicy Bypass -File .\Verify-AcpEvidence.ps1

There is nothing to fill in. It finds the evidence file and the key in the folder, and stops and asks if it finds more than one.

Step 3: Read the result

The last line is the answer.

RESULT: PASS

Every record matches its own content, the chain between them is unbroken, and every signature checks out against the published signing key.

RESULT: FAIL

Something does not match. The output names the first record that fails and what failed about it. Treat the pack as unreliable and come back to us through a channel you already trust.


What a PASS does and does not tell you

It does tell you the signed decision records are intact: not one character of a signed record has changed, none has been removed from the middle or the end, none has been added, and none has been reordered or relabelled.

It does not tell you that the events described actually happened the way they are described — a faithful record of a wrong decision still verifies. And on its own it does not prove whose key signed them. For that, compare the key fingerprint the verifier prints against the one published on our trust page, and treat a mismatch as a reason to stop.

You are downloading this checker from a domain we control, which is the same limitation the trust page describes about itself. The script is readable plain text precisely so you do not have to take that on faith, and the verification itself needs no contact with us at all.

If it will not run

Windows says the file is blocked, or nothing happens

Files downloaded from the internet are marked as untrusted. Clear that mark on this one file — no admin rights needed:

Unblock-File .\Verify-AcpEvidence.ps1
Your organisation blocks scripts entirely

Some managed estates enforce an execution policy through Group Policy, or restrict PowerShell to Constrained Language Mode. Those settings override the command above, and no amount of local flag-setting will get around them — by design.

In that case, verification has to happen somewhere your policy allows it: an unmanaged machine, a sanctioned analysis environment, or the Python verifier below. Ask us and we will work to whatever your estate permits.

I would rather use Python

The same checks are implemented in verify_evidence_offline.py, which ships in the evidence pack and needs Python 3 with the cryptography package. The two verifiers are held to identical results by a differential test, so either one answers the same question.

Technical details

Exactly what is checked, and how

For every record in the pack, in order:

  1. Content digest. The record is re-serialised to a canonical JSON form — keys sorted by code point, no insignificant whitespace — and hashed with SHA-256 together with the previous record’s digest. The result must equal the digest stored on the record.
  2. Signature. That digest is verified as an Ed25519 (RFC 8032) signature against the published public key for the key id named on the record.
  3. Chain linkage. The first record must point at the all-zero genesis digest, and every later record must point at its predecessor. This is what makes deletion and reordering detectable rather than invisible.
  4. Signed tip. Where the pack carries a signed head, its record count, tenant and tip digest must agree with the records present — so truncating the pack fails even though each surviving record is individually valid.

The verifier refuses to run against a shared-secret (HMAC) key. A key that can verify can also forge, so a PASS obtained with one would not be independent — it would only prove that whoever holds the secret produced the records, and that includes you.

What the signature covers. The signed record for each decision is its payload. An export repeats a few fields alongside it for readability — action, result, captured_at — and those copies sit outside the signature, so treat the signed payload as the record of what happened. We are changing the export to bind them in.

How long it takes. Windows has no built-in Ed25519, so the signature maths runs in PowerShell itself — roughly 0.7 seconds per record. A twenty-record pack takes about fifteen seconds; a full five-hundred-record export takes around six minutes. It prints its progress as it goes, so a long run is working rather than stuck.

Key identity and the SPKI fingerprint

The verifier prints the signing key id and the SHA-256 digest of the DER-encoded SubjectPublicKeyInfo for the key that verified the pack. Compare it with the fingerprint published on the trust page. That page also explains why a fingerprint published only by us is corroboration of limited value, and points at the independently signed anchor that is worth more.

Exit codes, for scripted use
0PASS — every check passed
1FAIL — a record, the chain or a signature did not verify
2REFUSED — the input could not be checked safely; never treat as a pass

Anything the verifier cannot reproduce with certainty exits 2 and says what it could not handle. It will not print a PASS it cannot justify.

Back to the capability and evidence page