Senza firma, una riga nel file hosts di un server basta a rispondere «licenza valida» al posto nostro. Ogni risposta porta una firma Ed25519 sulla forma canonica dei dati: chiavi ordinate, JSON compatto. Verificala prima di fidarti di qualsiasi cosa. La libreria lo fa per te, anche sulla copia in cache, a sua volta legata al proprio host perché non la si possa spostare da un sito all’altro.
Serve solo se chiami l’API direttamente. Ricostruisci la forma canonica dall’oggetto analizzato — mai dai byte grezzi ricevuti, che possono differire — e poi verifica la firma Ed25519 staccata con la nostra chiave pubblica.
Ed25519, 32 byte grezzi in base64. È la stessa per tutti gli autori e tutti i prodotti.
/PTkKQpweo9XCLOS0+b0vgrecx7Ly/SsAuwTiA737Tw=
La firma copre l’oggetto donnees serializzato secondo queste quattro regole, e nient’altro. Sbagliane una e ogni firma sembrerà non valida.
Per la risposta qui sopra, i byte firmati esattamente:
{"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'))
Scrivici dalla tua area autore. Una domanda che è stato necessario porre significa di solito che a questa pagina manca un paragrafo.