Public signing key · 9f7d56d92d05f139b569f8e6be3eaaf7
Check the stamp on a report we signed.
Every report we hand over carries a stamp, and two small files come with it. Together they let you confirm two things on your own machine: your report came from us, and nobody has altered a byte of it since we signed. Two standard commands do the whole job. You need no account with us, no software of ours, and nothing from us except the key below.
Checking a report right now? Skip to the commands.
Our signing key
- Algorithm: ECDSA on the NIST P-256 curve, signing a SHA-256 digest.
- Key id:
9f7d56d92d05f139b569f8e6be3eaaf7 - File: /attestation/takeinterest-9f7d56d92d05f139b569f8e6be3eaaf7.pub.pem
- Index of every key we have ever used: /attestation/keys.json
Fetch it, then confirm the file is what it claims to be:
curl -O https://takeinterest.ai/attestation/takeinterest-9f7d56d92d05f139b569f8e6be3eaaf7.pub.pem
openssl pkey -pubin -in takeinterest-9f7d56d92d05f139b569f8e6be3eaaf7.pub.pem -outform DER | shasum -a 256 | cut -c1-32You get back 9f7d56d92d05f139b569f8e6be3eaaf7. Key ids are just the first 32 characters of the SHA-256 of the key itself, so a file's name and its contents have to agree. If yours disagree, stop andwrite to us.
Pin this key. Everything else here is arithmetic anyone can redo. Your whole trust in the result sits on getting the right key, so take it from this page over HTTPS and not from whoever handed you the report.
Here is the key in full, so you can compare it against the file you downloaded:
-----BEGIN PUBLIC KEY-----
MIIBSzCCAQMGByqGSM49AgEwgfcCAQEwLAYHKoZIzj0BAQIhAP////8AAAABAAAA
AAAAAAAAAAAA////////////////MFsEIP////8AAAABAAAAAAAAAAAAAAAA////
///////////8BCBaxjXYqjqT57PrvVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMVAMSd
NgiG5wSTamZ44ROdJreBn36QBEEEaxfR8uEsQkf4vOblY6RA8ncDfYEt6zOg9KE5
RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBoN79R9QIhAP////8AAAAA
//////////+85vqtpxeehPO5ysL8YyVRAgEBA0IABBfUu7nPbb1UlDd+5oBFCH4r
wBBi8IKwUcSN2a2P1lR37UM8wVpaDfwHJDoGkCBRgJjnKKkpjB6LDNcOBH7gsw8=
-----END PUBLIC KEY-----What you were handed
report.html, your report.report.html.payload.json, the record we signed, in plain readable JSON you should open and read.report.html.sig, our signature over that record.
Inside the record sit your report's name, its exact size and SHA-256, who it was made for, when we stamped it, and the audit facts underneath: how many checks ran, how many were measured, and every check that could not run, each one with its reason written out.
Step one, is the record ours
openssl dgst -sha256 \
-verify takeinterest-9f7d56d92d05f139b569f8e6be3eaaf7.pub.pem \
-signature report.html.sig \
report.html.payload.jsonYou want exactly this back:
Verified OKAnything else, do not trust the file. Signatures that do not match printVerification failure on OpenSSL and Verification Failure on the LibreSSL that Apple ships, and both exit with status 1. Output you do not recognise reads as a fail, never as a pass. Usually your key file did not load, and a check that could not run is not a check that passed.
Step two, is your report the one that record covers
shasum -a 256 report.htmlCompare what prints to the sha256 value inside report.html.payload.json. Those two have to match character for character. No shasum on your machine?openssl dgst -sha256 report.html gives you the same number.
Never skip step two. Our signature covers the record. Your report is tied to that signature by one thing only: the sha256 written inside the record. Step two is where those two meet. Alter one byte of your report and step one still prints Verified OK, since the record we signed has not moved. Step two catches an altered report and step one cannot. We ran that exact test before publishing this page.
Both steps passed, so what do you know
- Your record was signed by whoever holds the private half of the key above, and that is us.
- Neither your record nor your report has changed since we signed them.
- Whatever scope we wrote into the record is the scope we signed. We cannot quietly narrow a scan afterwards and hand you a clean-looking report, since a narrowed scope no longer matches the signature.
What you do not know
Three things, and they carry more weight than the three above.
- Your code is not certified safe. Signatures say something about a document, never a grade on a system. Reports verify perfectly and describe systems full of problems. Expect exactly that. Reports with nothing in them would not be worth stamping.
- We did not necessarily look at everything. Read for this one. Narrow scans and thorough scans produce equally valid signatures, and we tested that: a seal over a run where zero of five checks were measured verifies exactly as cleanly as a full one. Coverage lives in the record, never in the signature. Open the record and read the
not_measuredlist, where every check that did not run is written out with its reason. Count that list yourself. The headline numbers give you a first glance:grep -o '"checks_total":[0-9]*\|"checks_measured":[0-9]*' report.html.payload.jsonchecks_totalis counted from the results themselves andchecks_measuredis copied from what the scanner reported, so trust the list over the headline and tell us if the two disagree. Ifscan_scopeorrulesetsaysmeasured: false, we could not attest what got skipped, so treat your coverage as unknown. - Nothing here is independently dated. Our
sealed_attime is our own clock at the moment of signing. No third party notarised it. So a stamp proves we signed and never proves when. Ask us if the date carries weight for you, and we will find a way to establish it that does not lean on our word.
If all you kept was the seal file
Both files above ship with every stamp. Only have report.html.seal.json? Both live inside it, base64 encoded, and stock tools get them out:
grep -o '"payload_b64": *"[^"]*"' report.html.seal.json | sed 's/.*"\([^"]*\)"$/\1/' | base64 -d > payload.json
grep -o '"signature_b64": *"[^"]*"' report.html.seal.json | sed 's/.*"\([^"]*\)"$/\1/' | base64 -d > sig.der
openssl dgst -sha256 -verify takeinterest-9f7d56d92d05f139b569f8e6be3eaaf7.pub.pem -signature sig.der payload.jsonWhat comes out is byte for byte what we delivered. We checked that too.
When we change keys
Your report stays checkable only against the key that signed it, so retiring a key would break every report already in the world. We leave old keys up. Every key we have ever signed with keeps its own address and its row in keys.json, marked retired with the date we stopped using it.
Suppose a key gets retired for being compromised and not for age. Different situation, and we will say so on this page in those words. Signatures from a compromised key stop meaning anything at all, old ones included, and you should ask us to re-sign whatever you rely on.
Verifying a stamp says nothing about whoever sent it
Say a report arrives by email and the same message tells you where to get the key. Check the key against this page instead, and type the address yourself. Anyone who can forge a report can forge a key link in the same message, and then both steps pass against the wrong key.
We built that attack to see it work. Our made-up report, signed with a made-up key, passed step one and step two perfectly. One thing catches it: the fingerprint of the key does not equal 9f7d56d92d05f139b569f8e6be3eaaf7. So the fingerprint check is the whole trust chain, and the other two steps are arithmetic underneath it.
Verifying a signed report, answered
How do I check that a report really came from Take Interest?
Download our public key from takeinterest.ai/verify, then run two standard commands. First, openssl dgst -sha256 -verify <key> -signature report.html.sig report.html.payload.json, which must print Verified OK. Second, shasum -a 256 report.html, whose output must match the sha256 value written inside report.html.payload.json. Both have to pass. Neither command needs an account, an internet connection or any software from us.
What does a valid signature actually prove?
Three things. Your record was signed by whoever holds the private half of the published key. Neither the record nor the report has changed since signing. And the scan scope written into the record is the scope that was signed, so a scan cannot be narrowed after the fact to make a report look cleaner than the work behind it.
Does a valid signature mean my code is safe?
No. Signatures are statements about a document and never grades on a system. Reports verify perfectly and describe systems full of problems, and that is the normal case. It also does not mean everything was examined: the signed record lists every check that could not run, with its reason, and you should read that list before drawing conclusions about coverage.
What algorithm and key do you sign with?
ECDSA on the NIST P-256 curve over a SHA-256 digest. Our current key id is 9f7d56d92d05f139b569f8e6be3eaaf7, published at https://takeinterest.ai/attestation/takeinterest-9f7d56d92d05f139b569f8e6be3eaaf7.pub.pem. Key ids are the first 32 hex characters of the SHA-256 of the key's own DER encoding, so you can recompute it from the file we publish and confirm the name matches the contents.
What happens to old reports when you change signing keys?
They keep verifying. Reports check only against the key that signed them, so retired keys stay published at their own address and stay listed in /attestation/keys.json with the date they stopped being used. If a key is ever retired because it was compromised instead of because it aged out, we will say so on this page in those words, and signatures made with that key stop carrying weight.
Can I verify without installing anything?
If you have openssl you have everything. Most macOS and Linux machines already ship it. Checking the signature is one openssl command and checking the file is a second one, and no part of the process contacts us or runs code we wrote.
Stuck on a check
Send us the output you got and the name of the report. Failed checks are worth an answer whether the fault turns out to be ours or a broken download. Contact us.