Sans signature, une ligne dans le fichier hosts d’un serveur suffit à répondre « licence valide » à notre place. Chaque réponse porte une signature Ed25519 sur la forme canonique des données — clés triées, JSON compact. Vérifiez-la avant de faire confiance à quoi que ce soit. La bibliothèque s’en charge, y compris sur la copie en cache, elle-même liée à son hôte pour qu’on ne puisse pas la déplacer d’un site à l’autre.
Utile seulement si vous appelez l’API directement. Reconstruisez la forme canonique à partir de l’objet analysé — jamais à partir des octets bruts reçus, qui peuvent différer — puis vérifiez la signature Ed25519 détachée avec notre clé publique.
Ed25519, 32 octets bruts en base64. Elle est la même pour tous les auteurs et tous les produits.
/PTkKQpweo9XCLOS0+b0vgrecx7Ly/SsAuwTiA737Tw=
La signature couvre l’objet donnees sérialisé selon ces quatre règles, et rien d’autre. Manquez-en une et toutes les signatures paraîtront invalides.
Pour la réponse ci-dessus, les octets exactement signés :
{"domaine":"exemple.fr","emis":1790687453,"essai":false,"hote":"boutique.exemple.fr","motif":"","ok":true,"quand":"","revalider":1790773853,"sursis":2592000}
function signature_valide(array $donnees, $signature, $publique)
{
ksort($donnees);
$corps = json_encode($donnees, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
return sodium_crypto_sign_verify_detached(
base64_decode($signature, true),
$corps,
base64_decode($publique, true)
);
}
import { createPublicKey, verify } from 'node:crypto';
const publique = createPublicKey({
key: Buffer.concat([Buffer.from('302a300506032b6570032100', 'hex'),
Buffer.from('/PTkKQpweo9XCLOS0+b0vgrecx7Ly/SsAuwTiA737Tw=', 'base64')]),
format: 'der',
type: 'spki',
});
const canonique = (d) =>
JSON.stringify(Object.fromEntries(Object.keys(d).sort().map((k) => [k, d[k]])));
const valide = verify(null, Buffer.from(canonique(rep.donnees), 'utf8'),
publique, Buffer.from(rep.signature, 'base64'));
import base64, json
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
publique = Ed25519PublicKey.from_public_bytes(base64.b64decode('/PTkKQpweo9XCLOS0+b0vgrecx7Ly/SsAuwTiA737Tw='))
canonique = json.dumps(rep['donnees'], sort_keys=True,
separators=(',', ':'), ensure_ascii=False)
publique.verify(base64.b64decode(rep['signature']), canonique.encode('utf-8'))
Écrivez-nous depuis votre espace auteur. Une question qu’il a fallu poser signifie en général qu’il manque un paragraphe à cette page.