Verify an AEGIS artefact without running AEGIS
Every published release ships an independent verifier written in Rust — a second implementation that shares no code with AEGIS — with the specification corpus and a SHA256SUMS manifest. Checking a receipt, a SCITT capsule or an inclusion proof needs those and nothing else.
The repository is private. Release assets, including the verifier binary, are downloadable by people with read access; links into the repository return 404 for everyone else. That is a limit of the current distribution, not of the verification: nothing in it asks you to trust AEGIS. Publishing the verifier crate (deliberately unpublished so far) or the repository is the owner's decision, and the day either happens nothing on this page changes except who can click the links.
Latest release on GitHub · sha256sum --check SHA256SUMS · aegis-verify vectors canonical-vectors.json
The same check, as a GitHub Action
aegis-control/.github/actions/verify
Check an AEGIS receipt, capsule or inclusion proof in your own CI, without running AEGIS and without trusting whoever gave you the artefact.
That last clause is the whole point. AEGIS signs what it does; this is the other side of the transaction. It runs a second implementation of the verification — a Rust binary that shares no code with AEGIS — over whatever you hand it.
What it checks
| Inputs | Question it answers |
|---|---|
artifact + signature + keys |
Is this receipt genuinely signed by the key it names? |
capsule + scitt-keys |
Is this SCITT capsule what it claims to be? |
inclusion-proof |
Is this entry really in the log? |
Before any of them, it replays the RFC 8785 canonicalisation corpus against the verifier itself. That matters more than it looks: a verifier that has drifted accepts things, and a clean pass from one would be worse than no check at all.
If you pass none of the three, the action fails. A step that checks nothing and reports green is how a verification gate quietly stops being one.
Checking a capsule
This is the one a holder outside the issuing organisation uses.
- uses: Oshinsu/aegis-control/.github/actions/verify@main
with:
release: v0.15.0
capsule: ./receipt.cose
scitt-keys: ./scitt-keys.cbor
where scitt-keys.cbor came from the issuer's own well-known endpoint:
curl -sfo scitt-keys.cbor https://aegis.example/.well-known/scitt-keys
Four things are checked, and each depends on the last having held:
- the bytes decode as a tagged COSE_Sign1, using
cosetandciborium— third-party libraries, not the encoder that produced the envelope; - the protected header carries what
draft-mih-scitt-agent-action-capsule-02 §3.1 requires, and nothing
outside its closed
capsule_*claim set; - the Ed25519 signature verifies over a
Sig_structurethe verifier rebuilds itself, rather than over anything the producer said it signed; capsule_idis the digest of the capsule that carries it, recomputed with an independent RFC 8785 implementation.
Prefer scitt-keys over capsule-key. Taking the key from the issuer's
published key set is a different claim from taking it from the same party that
handed you the capsule, and it is the stronger one. Passing both is refused:
two sources for one key is a way to check against the wrong one and not notice.
Getting the verifier
Two ways, and they are not equivalent.
A pinned release — release: v0.15.0. The binary is downloaded and checked
against the SHA256SUMS published beside it, so you do not have to trust the
transport. Linux x86_64 only; on any other runner this fails rather than
silently building instead, because a caller who asked for a pinned artefact
should not be handed a compiled one without being told.
A build from source — the default. Three sources, in order of preference:
- a
verifier/directory already in your workspace (verifier-path, or detected automatically) — no network, no credentials; - a clone of this repository — needs
tokenwhile it stays private; cargo install aegis-verify— not yet; the crate is deliberately unpublished.
Building trusts whatever ref resolves to when the job runs. Pinning a release
does not. Prefer the release.
The limitation worth stating
This repository is private. An action in a private repository can be used
only from repositories that can read it, and cloning the verifier needs a
token. So "anyone can check an AEGIS receipt" is not true today — what is true
is that anyone with read access can, and that nothing about the checking
depends on trusting AEGIS.
The path out is not more code here. It is publishing the verifier
(verifier/Cargo.toml carries publish = false on purpose — that is the
owner's decision, not a side effect of a build), or making the repository
public. On the day either happens, nothing in this action changes.
Examples
Verify a signed receipt and its place in the log, from a workspace checkout:
- uses: actions/checkout@v5
- uses: ./.github/actions/verify
with:
artifact: ${{ runner.temp }}/receipt.json
signature: ${{ runner.temp }}/receipt.sig.json
keys: ${{ runner.temp }}/keys.json
inclusion-proof: ${{ runner.temp }}/proof.json
From another repository, against a pinned release:
- uses: Oshinsu/aegis-control/.github/actions/verify@main
with:
release: v0.15.0
token: ${{ secrets.AEGIS_READ_TOKEN }}
artifact: ./receipt.json
signature: ./receipt.sig.json
keys: ./keys.json
What it does not do
It does not verify the signature over a tree head — that is a separate call with
artifact, kept separate so a caller knows which of the two failed. It does not
fetch anything from a transparency service; you fetch, it checks, and keeping
those apart means the action never decides which URL to trust on your behalf.
And it does not tell you whether a decision was right: it tells you the record
of that decision is authentic and unaltered, which is a narrower claim and the
only one cryptography can make.