Aller au contenu

Journal de transparence

Tout ce que nous signons, en public

Chaque signature de Content Credentials, chaque horodatage et chaque résultat de vérification signé que délivre Kennmarq.com est d’abord inscrit dans ce journal. Le journal ne peut que croître, et nous signons une racine couvrant l’ensemble toutes les heures tant qu’il croît, et au moins une fois par jour. Chacun peut vérifier que la signature d’un fichier s’y trouve, et que rien n’a jamais été supprimé, modifié ou antidaté.

Dernière racine signée

Entrées
563
Date de signature
(racine n° 149)
Empreinte de la racine
897c3b232864c2c9130f7d67a12815bb865d0ca08f4efec23f83e5b78f2fa893
ID de la clé
3b51f0f999b77a04bd96b2b86fa783237f5f33f29c55275a7e5a06ad7230829e
Signature
MEYCIQDvtHKEuzfherpaixgaZFQUw3aaS2FIuay/ETvcVGbgVQIhAJc6l/rUw38Yoi04yj1bKKbZyGIr5I24JaE4ezqbC5uB

563 entrées dans le journal à ce jour. En JSON : https://api.kennmarq.com/v1/log/root

Ce qui y figure

  • Signatures : pour chaque fichier marqué via l’API, le libellé de son manifeste et le SHA-256 du fichier, de sa signature, du certificat de signature et de l’horodatage contenu dans la signature. Pour un fichier marqué en mode local, qui ne nous parvient jamais, sa liaison stricte (hard binding) remplace son SHA-256.
  • Horodatages : pour chaque jeton de notre serveur d’horodatage, son numéro de série, son heure, son SHA-256 et l’empreinte qu’il horodate.
  • Ancrages des journaux d’audit : le journal d’audit de chaque organisation est chaîné par hachage ; sa dernière empreinte est inscrite ici, sous un pseudonyme que seuls ses membres peuvent reconnaître, de sorte que son historique ne peut pas être réécrit sans que cela se voie.
  • Résultats de vérification signés : pour chaque résultat de POST /v1/verify que nous signons, son SHA-256, le SHA-256 du fichier vérifié et l’ID de la clé de notre vérificateur.

Jamais dans le journal : noms ou ID d’organisation, noms ou contenus de fichiers, ID de filigrane, modèles, applications ou titres, adresses ou personnes. Qui détient un fichier peut retrouver son entrée ; personne d’autre n’apprend quoi que ce soit du journal.

Vérifiez par vous-même

  1. Retrouvez l’entrée d’un fichier par le libellé de son manifeste, ou par le X-Log-Index que l’API a renvoyé avec lui : GET /v1/log/proof/urn:c2pa:… répond avec l’entrée et les empreintes qui la relient à une racine signée.
  2. Vérifiez que l’entrée correspond au fichier (son SHA-256, le libellé de son manifeste), puis remontez la preuve jusqu’à la racine.
  3. Vérifiez la signature de la racine avec notre clé publique, ci-dessous.
  4. Conservez les racines que vous avez vues. GET /v1/log/consistency prouve que toute racine ultérieure commence toujours par chacune des entrées d’une racine antérieure.

La référence de l’API donne les formats exacts, et les quelques lignes de shell et de Python qui effectuent chaque vérification. L’arbre est celui de la RFC 9162 (Certificate Transparency), et les racines sont signées comme les têtes d’arbre de la RFC 6962 : les outils et bibliothèques existants s’appliquent donc.

Vérifier la dernière racine avec OpenSSL (et jq)
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.bin

Racines récentes

Les dix dernières racines signées
RacineDate de signatureEntréesEmpreinte de la racine
149563897c3b232864c2c9130f7d67a12815bb865d0ca08f4efec23f83e5b78f2fa893
148550533fa80cc9342b3b7d2a938e123583adaa3a3ff1e1f15a5e0c567b9285ae5c5c
147544cb537fb383038e50850a7e8ebdbab3e01ef879e50e161ff38666ba8ae6d8da76
146543f4b334fc696c7580c8dfd1cc72655e3470da10d61708f3fe861f3ddc3a92177b
14554220737af83ce09bc9955cf5659eab4f4de98c999bfb02a28c0608f09b4e07dfe0
144537cbac0d45d78547b09fb5a56e65770c68ce5112e648c9d2350c7c80fbdc2eb7ce
1435221e76b52cd13890935c1918437a9bf508c10d1ac1f936a25a338659824d11e9eb
14251680391ea31eb3546589ed9c6e78d1a78efb2a3bddd0eae4ba6b6c9a4353f4f44b
141515df323aad2b192d395ade8d304389e7bdc0af1a6233d9b8ab4e57ad42c15e5c13
140514f9ba75d9da9f43887116258817f14d2e37bef979e0bdcc11a820c160762ee801

Toutes les racines, des plus récentes aux plus anciennes : GET /v1/log/roots.

Notre clé de journal

ECDSA P-256 avec SHA-256. ID de la clé 3b51f0f999b77a04bd96b2b86fa783237f5f33f29c55275a7e5a06ad7230829e, soit le SHA-256 de la clé ci-dessous encodée en DER. Elle ne signe que des têtes d’arbre, et sa clé privée ne quitte jamais AWS KMS.

PEM
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE42CpuoaS4/rNCAyQ08euvOtCa9X3
Zuq7bXjiCyeh4C0O92Ey6CbvOtfkS11IoLLFWFzzXrcpi/0L2vDeXsufyw==
-----END PUBLIC KEY-----
Nos horodatages proviennent de notre propre serveur RFC 3161 : chacun d’eux est donc consigné ici. L’heure inscrite dans un horodatage et l’heure à laquelle son entrée a été journalisée figurent côte à côte, et une fois qu’une racine les couvre, ni l’une ni l’autre ne peut plus changer.