Transparency log
Everything we sign, in public
Every Content Credentials signature, time-stamp and signed check result Kennmarq.com hands out is first written to this log. The log can only grow, and we sign a root over all of it every hour while it grows, at least once a day. Anyone can check that a file's signature is in it, and that nothing was ever removed, changed or backdated, us included.
Latest signed root
- Entries
- 374
- Signed
- (root 96)
- Root hash
- 264b1ee55014b2441437014d730e3e88eaf118b6ce1338beb4090591daded29c
- Key ID
- 3b51f0f999b77a04bd96b2b86fa783237f5f33f29c55275a7e5a06ad7230829e
- Signature
- MEYCIQCB2TSnaNbENqR76gLDND1ueVHoUcYTA3s193IujqcW4AIhALsTYZqhEaFpXjlOGA3Rtv3L+gVwvx9xrIukbCSQ7dls
381 entries in the log now. As JSON: https://api.kennmarq.com/v1/log/root
What goes in
- Signatures: for each file marked through the API, its manifest's label and the SHA-256 of the file, of its signature, of the signing certificate and of the time-stamp inside the signature. For a file marked in local mode, which never reaches us, its hard binding stands in for its SHA-256.
- Time-stamps: for each token from our time-stamp server, its serial, its time, its SHA-256 and the hash it stamps.
- Audit-log anchors: each organisation's audit log is hash-chained; its latest hash goes in here, under a pseudonym only its members can recognise, so its history can't be rewritten unseen.
- Signed check results: for each result of POST /v1/verify we sign, its SHA-256, the checked file's SHA-256 and our checker key's ID.
Never in it: organisation names or IDs, file names or contents, watermark IDs, models, apps or titles, addresses or people. Whoever holds a file can find its entry; nobody else learns anything from the log.
Check it yourself
- Find a file's entry by its manifest's label, or by the
X-Log-Indexthe API returned with it:GET /v1/log/proof/urn:c2pa:…answers with the entry and the hashes that connect it to a signed root. - Check that the entry matches the file (its SHA-256, its manifest's label), and fold the proof up to the root.
- Check the root's signature with our public key, below.
- Keep the roots you've seen.
GET /v1/log/consistencyproves any later root still starts with every entry of an earlier one.
The API reference has the exact formats, and the few lines of shell and Python that do each check. The tree is RFC 9162's (Certificate Transparency), and roots are signed like RFC 6962's tree heads, so existing tools and libraries apply.
curl -s "https://api.kennmarq.com/v1/log/key?format=pem" -o log-key.pem
curl -s "https://api.kennmarq.com/v1/log/root" -o root.json
printf '0001%016x%016x%s' "$(jq .timestamp root.json)" "$(jq .tree_size root.json)" \
"$(jq -r .root_hash root.json)" | xxd -r -p > tree-head.bin
jq -r .signature root.json | base64 --decode > signature.der
openssl dgst -sha256 -verify log-key.pem -signature signature.der tree-head.binRecent roots
| Root | Signed | Entries | Root hash |
|---|---|---|---|
| 96 | 374 | 264b1ee55014b2441437014d730e3e88eaf118b6ce1338beb4090591daded29c | |
| 95 | 368 | 26d4828ac190591c76fc79a8a1152c90bb6efc6f5c67e4454f676d163c8fd569 | |
| 94 | 367 | 80ac6ea3fc0970ca4fd4596254ba14c94012cc88c89f56e555c6852fb4f04f1d | |
| 93 | 366 | f5006059d9f1b0916fb9b50530341f4e2bb890237f13e5183f5afc40f41a2a30 | |
| 92 | 351 | 897f23ae30be3c5591a91ae9e7378e4911562f0b8cbc3110c66a4270b90ef7d5 | |
| 91 | 345 | ca4f6ca697a43d16038757a01d26d28e9b46b286b8599db17c808df55c468487 | |
| 90 | 344 | ec87e5a4a94c011a30e2a1bfbae9c9b4212a7a9ba97d36922bd6a087c0c67c42 | |
| 89 | 343 | 6aa46d0cedc3148d9897a18023419f639dd54a8bda755849db1f9f7e18fe0565 | |
| 88 | 331 | acffc0c7b3b768a51d53df32626ede643ee8a244b5fffd0325707505def1e5b7 | |
| 87 | 325 | 770fcf19ff2f56c641645c3bab5660dd77a8a4789259f4da84fae0a220443f29 |
Every root, newest first: GET /v1/log/roots.
Our log key
ECDSA P-256 with SHA-256. Key ID 3b51f0f999b77a04bd96b2b86fa783237f5f33f29c55275a7e5a06ad7230829e, the SHA-256 of the key below in DER. It signs tree heads and nothing else, and it lives in AWS KMS, which never lets it out.
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE42CpuoaS4/rNCAyQ08euvOtCa9X3
Zuq7bXjiCyeh4C0O92Ey6CbvOtfkS11IoLLFWFzzXrcpi/0L2vDeXsufyw==
-----END PUBLIC KEY-----