Platform Method & Trust Verify Contact Request access
Verification

Check the report without us.

Paste an Armada attestation below. Your browser recomputes its hash, checks the signature against our published key, and walks the chain back through earlier scans. Nothing is uploaded, and you don't need to contact 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

What the check answers.

Does the hash describe this content?

Your browser rebuilds the hash from the record's fields: client, timestamp, score, tier, catalog version, every control state and, from catalog 2026.11, the domain the email check read. Change one character and the hash won't match. This is the check that matters most, because a valid signature means nothing if the hash doesn't match what you're reading.

Did the holder of the private key sign it?

The signature is ECDSA P-256 over SHA-256 and verifies against the public key on this page. Anyone can check a signature with the public key. Nobody can forge one without the private key, which never appears on this site.

Is a scan missing from the history?

Each record carries the hash of the one before it. Paste a chain and the checker follows the links. If a scan is deleted from the middle, every later record fails.

Which of these did a machine measure, and which did a person claim?

Most of the catalog has no Microsoft telemetry behind it, so a provider can record a declaration instead: a named person, a date, an expiry. The checker lists declarations apart from measured controls and never adds them to the score. Expired ones are still shown and labeled, but not counted. On every record that has declarations, the checker notes what the signature does and doesn't prove about them.

Was this a real tenant or a test fixture?

Every attestation has a graphMode field. From catalog 2026.10 it's part of the hash, so relabeling a test run as a live scan fails verification. Older records still carry the field and still verify, and the checker tells you the flag wasn't covered on those.

Honest limits

What this page does not prove yet.

Armada is pre-launch. Here is what a passing check does and doesn't mean today.

The signing key is a development key.

The app generates the private key and stores it on disk, not in hardware. A passing check proves the record hasn't changed since signing. It doesn't prove the key couldn't have been misused. Before any live client tenant is signed, the key moves to Azure Key Vault and the key on this page will be replaced.

A signature says nothing about whether the reading was right.

Cryptography proves a record hasn't changed. It can't prove Microsoft Graph returned correct data or that we read it correctly. That's covered on the control catalog.

No client tenant has been scanned.

The sample chain on this page is a real signature over real evaluator output, run against test fixtures. The record and the result both say so.

You are running our JavaScript.

A verifier served by the company being verified is convenient, but it shouldn't be your only check. The algorithm is written out below and the key is downloadable, so you can check a record with your own tools and get the same answer.

The key

Published, so it can be pinned.

This is the current signing key. Download it and keep a copy. If it ever changes without a public notice, email us.

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
2026.07  controlsHash = SHA256( JSON({ states, catalogVersion }) )
2026.08  controlsHash = SHA256( JSON({ states, catalogVersion, controlVersions }) )
2026.09  controlsHash = SHA256( JSON({ states, catalogVersion, controlVersions, declarations }) )

The checker reads each record's format from the fields it carries instead of assuming the current one, so older reports keep verifying. Both published samples are on this page: an old record and a current one, both valid.

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. The engine test suite checks the published sample chain against the published key on every run.

Holding a report and want it checked?

If your IT provider gave you an assessment made with Armada and something looks wrong, write to us. We'll help you check it, even if the answer is bad news for our customer.