EN
← Dossiers techniques
Identité

Signer une carte d’agent, et la rendre vérifiable

Vérifier qu’une carte d’agent vient bien de qui elle prétend. Sur les 175 sites de notre dernier passage, 8 en publient une. Signatures vérifiables : 0.

Une carte d’agent est un petit fichier qu’un site publie pour dire qui il est et ce qu’il sait faire, à destination des IA. Il peut être signé, comme on signe un contrat. Nous avons interrogé deux cent six sites en deux passages : dix publient une carte, aucune ne porte de signature qu’un tiers puisse vérifier. La seule que nous ayons réussi à valider était ailleurs — un site qu’un lecteur nous a signalé — et il nous a fallu cent vingt-huit tentatives pour y arriver. Voici pourquoi, et comment éviter ça.

Le problème, en une phrase

Pour vérifier une signature, il faut retrouver exactement les octets qui ont été signés. Or un même fichier JSON peut s’écrire de mille façons : les champs dans un autre ordre, avec ou sans espaces, les accents codés différemment, les nombres écrits autrement. Se mettre d’accord sur une seule écriture s’appelle canonicaliser. Si l’auteur ne dit pas laquelle il a employée, celui qui vérifie doit deviner.

Écrivez votre convention de signature assez précisément pour qu’un inconnu retrouve les octets signés sans avoir à deviner.

Ce qu’il faut publier

ChampCe qu’il doit direContre-exemple observé
AlgorithmeEd25519, nommé sans ambiguïté« signature cryptographique »
CanonicalisationRFC 8785 (JCS), nommée par sa référence« canonical-json », qui ne désigne rien
Champs retirésla liste exhaustive, dans l’ordre« excluant la signature » — il en manquait trois
Clé publiqueune adresse résolvable, et son identifiantune empreinte sans adresse
Empreinte canoniquele SHA-256 des octets signésabsente, donc rien à comparer

La vérification, en cinq étapes

  • Récupérer la clé publique à l’adresse que le document annonce.
  • Vérifier que l’identifiant de clé du document et celui de la clé concordent.
  • Retirer exactement les champs annoncés, puis canonicaliser selon la RFC 8785.
  • Recalculer le SHA-256 et le comparer à l’empreinte publiée.
  • Vérifier la signature Ed25519 sur ces octets.
// JCS, RFC 8785 : clés triées par unités de code UTF-16,
// nombres au format ES, aucun espace.
function jcs(v) {
  if (v === null) return "null";
  if (typeof v === "boolean") return String(v);
  if (typeof v === "number") return Number.isFinite(v) ? JSON.stringify(v) : "null";
  if (typeof v === "string") return JSON.stringify(v);
  if (Array.isArray(v)) return "[" + v.map(jcs).join(",") + "]";
  return "{" + Object.keys(v).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))
    .map((k) => JSON.stringify(k) + ":" + jcs(v[k])).join(",") + "}";
}

Une carte re-signée à chaque appel

La seule carte signée que nous ayons vérifiée est refabriquée à chaque visite : deux appels espacés d’une seconde donnent deux fichiers différents. La signature prouve donc qui l’a émise au moment où on la lit, mais elle ne fige rien. Un agent ne peut pas s’y référer plus tard en disant « la carte que j’ai lue le 3 septembre disait ceci ».