Platform Method & Trust Verify Contact Request access
Verification

Check the report without us.

A signed document is only worth what an outsider can confirm about it. Paste an Armada attestation below and your browser will recompute its hash, check its signature against our published key, and walk the chain back through every scan before it. Nothing is uploaded. The whole check runs on your machine, and it works just as well if you never speak to us.

One record, or the whole chain as an array. Whitespace does not matter. Field order does, because the field order is part of what was hashed.

The published key is fetched when you run the first check.
Check against a different key

If someone hands you a key out of band and you would rather trust that one than the copy on this page, paste it here. Leave it empty to use the published key.

What the check proves

Four questions, answered without trusting anybody.

Does the hash describe this content?

Your browser rebuilds the hash from the record's own fields: the client, the timestamp, the score, the tier, the catalog version, and all thirteen control states. If a single character of any of it was edited after signing, the recomputed hash will not match the one in the record, and the check fails on that line. This is the check that matters most, because a valid signature over a hash proves nothing if the hash does not describe what you are reading.

Did the holder of the private key sign it?

The signature is ECDSA on the P-256 curve over SHA-256. It verifies against the public key published on this page, and the matching private key never appears here or anywhere else on this site. Anyone can confirm a signature with the public half. Nobody can forge one without the private half.

Is a scan missing from the history?

Each record carries the hash of the record before it. Paste a chain and the checker walks the links. Delete an unflattering scan from the middle of a client's history and every record after it stops matching, which is visible here rather than only to us.

Was this a real tenant or a test fixture?

Every attestation carries a graphMode field and it is never omitted. The checker prints it in plain language on every record. A run against test fixtures is labelled as one, and no amount of valid signing turns it into a live result.

Honest limits

What this page does not prove yet.

Armada is pre-launch. Publishing a verifier that overstates itself would be the same failure as publishing a report that overstates itself, so here is the ceiling on what a passing check means today.

The signing key is a development key.

The private half is generated by the application and held on disk. It is not hardware-backed, and its custody is only as good as our handling of it. A passing check today proves the record is unaltered since signing. It does not prove the key was impossible to misuse. Hardware-backed custody in Azure Key Vault lands before any live client tenant is signed, and the key published here will be replaced with the vault key at that point.

A signature says nothing about whether the reading was right.

Cryptography can prove a record has not changed since it was written. It cannot prove that Microsoft Graph returned the truth, or that our interpretation of a signal was the correct one. Those are separate claims and they are argued on the control catalog, not here.

Nothing has been scanned in anger.

No client tenant has been scanned by Armada. The sample chain this page can load is a real signature over real evaluator output, produced against test fixtures, and it is labelled that way in the record itself and in the result. It is here so the mechanism can be inspected before there is anything at stake, not to imply a customer base.

You are running our JavaScript.

A verifier served by the party being verified is a reasonable convenience and a poor root of trust. That is why the algorithm is written out below and the key is downloadable. Anyone who wants to check a record with their own tools, on their own machine, should do exactly that, and should get the same answer.

The key

Published, so it can be pinned.

This is the current attestation signing key. Download it, compare it against the copy printed here, and keep your own copy. If it ever changes without a public note, that is worth an email.

attestation-signing-key.pub.pem ECDSA P-256 · key id local-dev-key-v1 · development custody
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9WO8ORWLAJOGgt0HQDkG+WsPZHlR
VjWAC/jpzm1D2xoUaNOmfI4UZVH6J+avBR/M629/V+kF6aGIcK4TWg0b/Q==
-----END PUBLIC KEY-----
Verify it yourself

The algorithm, written out.

Two SHA-256 digests and one signature check. The field order below is part of the hash, so the JSON has to be rebuilt in exactly this order to reproduce it.

01
Hash the controls
controlsHash = SHA256( JSON({ states, catalogVersion }) )

// catalog 2026.08 onward also folds the per-control versions in:
controlsHash = SHA256( JSON({ states, catalogVersion, controlVersions }) )

A record declares which of the two it is by whether it carries a controlVersions field, and the checker reads that off the record rather than assuming the current generation. A report handed over under an older catalog has to keep verifying years later, or the signature was never worth much.

02
Hash the record, chained to the one before
hash = SHA256( JSON({ prevHash, clientId, stamp, score, tierKey, controlsHash }) )
03
Check the signature over that hash
ECDSA_P256_SHA256_verify( publicKey, signature, ascii(hash) )

The signed message is the hexadecimal hash string itself, not its raw bytes. The signature is DER encoded and base64 wrapped.

With openssl, offline

printf '%s' "$HASH" > hash.txt
printf '%s' "$SIGNATURE_B64" | base64 -d > sig.der
openssl dgst -sha256 -verify attestation-signing-key.pub.pem -signature sig.der hash.txt

Prints Verified OK when the signature matches. Recompute the two digests in step 01 and 02 separately and confirm that $HASH is the hash of the content, or you have only checked half of it.

Where the algorithm lives

The signing side is api/src/lib/attestation.js and api/src/lib/signing.js in the product. The checker on this page is assets/verify.js, unminified and commented, and the engine test suite verifies the published sample chain against the published key on every run, so this page and the product cannot quietly drift apart.

Holding a report and want it checked?

If you were handed an Armada-produced assessment by your IT provider and something about it does not sit right, write to us directly. We will help you check it even if it makes our own customer look bad, because a verifier that only confirms good news is not a verifier.