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
| Champ | Ce qu’il doit dire | Contre-exemple observé |
|---|---|---|
| Algorithme | Ed25519, nommé sans ambiguïté | « signature cryptographique » |
| Canonicalisation | RFC 8785 (JCS), nommée par sa référence | « canonical-json », qui ne désigne rien |
| Champs retirés | la liste exhaustive, dans l’ordre | « excluant la signature » — il en manquait trois |
| Clé publique | une adresse résolvable, et son identifiant | une empreinte sans adresse |
| Empreinte canonique | le SHA-256 des octets signés | absente, 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 ».