Apertura próxima — los autores se quedan el 100 % de su precio Hazte autor Iniciar sesión Crear cuenta
Hola, inicia sesión Cuenta y listas TuÁrea de autor

Verificar la firma tú mismo

1.Por qué la respuesta va firmada

Sin firma, una línea en el archivo hosts de un servidor basta para responder «licencia válida» en nuestro lugar. Cada respuesta lleva una firma Ed25519 sobre la forma canónica de los datos: claves ordenadas, JSON compacto. Verifícala antes de fiarte de nada. La biblioteca lo hace por ti, incluso sobre la copia en caché, que a su vez está vinculada a su host para que no pueda copiarse de un sitio a otro.

2.Verificar la firma tú mismo

Solo hace falta si llamas a la API directamente. Reconstruye la forma canónica a partir del objeto analizado, nunca de los bytes en crudo recibidos, que pueden diferir, y después verifica la firma Ed25519 separada con nuestra clave pública.

Nuestra clave pública

Ed25519, 32 bytes en crudo en base64. Es la misma para todos los autores y todos los productos.

/PTkKQpweo9XCLOS0+b0vgrecx7Ly/SsAuwTiA737Tw=

La forma canónica

La firma cubre el objeto donnees serializado con estas cuatro reglas, y nada más. Falla una y todas las firmas parecerán inválidas.

  1. Claves ordenadas de forma ascendente.
  2. Sin espacios en blanco: ninguno tras los dos puntos ni tras las comas.
  3. Las barras no se escapan.
  4. Los caracteres no ASCII se quedan en UTF-8, sin escape barra invertida-u.

Para la respuesta de arriba, los bytes firmados exactamente:

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'))

¿Algo no queda claro?

Escríbenos desde tu área de autor. Una pregunta que hubo que hacer suele significar que a esta página le falta un párrafo.

Área de autor