Ouverture prochaine — les auteurs gardent 100 % de leur prix Devenir auteur Se connecter Créer un compte
Bonjour, identifiez-vous Compte et listes EspaceAuteur

Vérifier la signature vous-même

1.Pourquoi la réponse est signée

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.

2.Vérifier la signature vous-même

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.

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 forme canonique

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.

  1. Clés triées par ordre croissant.
  2. Aucun blanc : pas d’espace après les deux-points ni les virgules.
  3. Les barres obliques ne sont pas échappées.
  4. Les caractères non ASCII restent en UTF-8, sans échappement antislash-u.

Pour la réponse ci-dessus, les octets exactement signés :

utf-8
{"domaine":"exemple.fr","emis":1790687453,"essai":false,"hote":"boutique.exemple.fr","motif":"","ok":true,"quand":"","revalider":1790773853,"sursis":2592000}
PHP PHP
sodium
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)
    );
}
JS Node.js
node:crypto
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'));
PY Python
cryptography
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'))

Quelque chose n’est pas clair ?

É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.

Auteur