Aller au contenu

Signatures typées EIP-712 : domaines, condensés et vérification sûre

EIP-712 rend les messages structurés Ethereum déterministes et lisibles, mais une signature sûre exige de vérifier précisément domaine, type, valeur, nonce, échéance, exécution et politique du signataire.

Mis à jour

À des fins éducatives uniquement ; ne constitue ni un conseil en investissement ni une recommandation d’investissement. Les investissements peuvent entraîner des pertes.

Réponse directe

EIP-712 normalise la manière dont les applications Ethereum décrivent, hachent et font signer des données structurées typées. Une demande contient types, primaryType, domain et message ; son condensé est keccak256("\x19\x01" || domainSeparator || hashStruct(message)). L’encodage devient déterministe et un portefeuille compatible peut afficher les champs plus clairement qu’un hachage opaque.

La norme ne rend pas le message véridique, anodin, révocable ou protégé contre la répétition. L’application doit lier l’autorité à la bonne chaîne et au bon vérificateur, définir chaque champ sans ambiguïté, imposer nonces et limites temporelles, valider le bon signataire et restreindre l’exécution. Une signature valide prouve l’approbation d’un condensé exact selon une règle de vérification, pas l’identité, l’intention éclairée ni la sûreté du site ou du contrat.

Signatures typées EIP-712
0 / 5
0 articles examinés; 5 points toujours non résolus

La réalisation de cet examen ne prouve pas qu'un actif, une transaction ou un système est sûr.

Fonctionnement

1. Identifier l’action et le chemin de vérification

Déterminez si la demande autorise une connexion, un ordre, un vote, une allowance de jeton, un transfert, un appel relayé ou une autre action. Repérez le code qui reconstruit le condensé et consomme la signature. Pour un compte détenu de l’extérieur, on récupère souvent une adresse depuis une signature ECDSA ; pour un compte contrat, ERC-1271 isValidSignature(hash, signature) et sa valeur de réussite 0x1626ba7e peuvent être nécessaires.

2. Fixer le domaine

Examinez le type EIP712Domain exact et ses valeurs. Les champs standard sont name, version, chainId, verifyingContract et salt, mais seuls ceux présents sont hachés. Confirmez indépendamment chaîne active, code déployé et vérificateur prévu ; nom, symbole, étiquette de proxy ou adresse à somme de contrôle familiers ne suffisent pas. ERC-5267 eip712Domain() peut exposer le domaine, mais sa prise en charge est facultative et proxies ou mises à niveau restent à examiner.

3. Reconstruire le graphe des types

Partez de primaryType, conservez l’ordre des membres et rassemblez récursivement les structures référencées. encodeType ajoute leurs définitions triées par nom de type. EIP-712 accepte les entiers de largeur fixe, address, bool, de bytes1 à bytes32, les bytes et string dynamiques, tableaux et structures ; les alias uint et int, types à virgule fixe et valeurs cycliques ne sont pas définis.

4. Décoder chaque valeur et unité

Associez chaque valeur à son type déclaré et à son sens applicatif. Vérifiez adresses complètes, unités entières brutes, signes, ordre des tableaux, destinataires, spenders, actifs, montants, frais, limites, destinations, hachages de calldata et chaînes lisibles. Les bytes et string dynamiques sont représentés dans encodeData par le hachage Keccak-256 de leur contenu ; les tableaux hachent les encodages concaténés et les structures imbriquées utilisent leur propre hashStruct.

5. Recalculer indépendamment le condensé

Calculez typeHash = keccak256(encodeType(primaryType)), puis hashStruct(message) = keccak256(typeHash || encodeData(message)). Calculez pareillement le séparateur de domaine et combinez-le aux octets de version ERC-191 0x19 0x01. Comparez frontend, bibliothèque de signature, contrat vérificateur et implémentation indépendante ; des JSON visuellement identiques ne prouvent pas un encodage typé identique.

6. Auditer répétition, temps et exécution

EIP-712 n’inclut aucune protection contre la répétition. Vérifiez que le validateur contrôle le signataire prévu, consomme ou invalide le bon nonce, impose deadline ou les fenêtres de validité, lie tous les paramètres critiques et conserve le résultat voulu si un relayeur ou un frontrunner soumet en premier. La séparation de domaine ne prévient que les collisions entre domaines réellement encodés ; des champs absents ou erronés peuvent permettre une réutilisation entre contrats ou chaînes.

7. Signer au minimum et rapprocher le résultat

Refusez champs cachés, types inexpliqués, valeurs illimitées, échéances lointaines, contrats inconnus, identifiants de chaîne divergents, écrans de blind signing ou contexte d’exécution incomplet. Conservez le JSON typé exact et le condensé, utilisez si possible un compte dédié et contrôlez transaction, reçu, événements, soldes, allowances, nonces, état de l’ordre et finalité. Déconnecter le site ne révoque ni une signature utilisable ni une autorité déjà créée.

Exemples calculés

Exemple 1 : Construction du type et du condensé

Pour Order(address maker,address token,uint256 amount,uint256 nonce,uint256 deadline), typeHash est le hachage Keccak-256 de cette chaîne exacte, ordre des champs compris. Le hachage du message est keccak256(typeHash || maker || token || amount || nonce || deadline) et chaque membre encodé occupe 32 octets. Le condensé final ajoute 0x1901, séparateur de domaine et hachage du message ; passer amount de 250000000 à 250000001 modifie le condensé et invalide l’ancienne signature.

Exemple 2 : Unités et échéance

250 USDC d’un jeton à six décimales s’encodent comme valeur brute 250000000, pas 250. Si l’horodatage courant est 1727000000 et l’échéance 1727000900, la fenêtre vaut 900 seconds = 15 minutes. L’affichage décimal et l’horloge locale ne sont que des aides ; le vérificateur utilise l’entier brut et sa règle temporelle on-chain.

Exemple 3 : Contrôle de répétition

Un ordre porte le nonce 41 et un maximum de 5 ETH. Après consommation du nonce 41, une seconde soumission doit échouer même si la signature reste valide. Si le contrat ne consomme pas le nonce et que l’exécution n’est pas idempotente, la même signature peut autoriser encore 5 ETH ; le séparateur de domaine seul ne l’empêche pas.

Exemple 4 : Validité d’un portefeuille contrat

Un portefeuille contrat 2-sur-3 approuve un condensé avec A, B et C comme signataires. Les signatures de A et B peuvent faire renvoyer aujourd’hui 0x1626ba7e par ERC-1271. Si une mise à niveau remplace B par D, les mêmes octets peuvent devenir invalides : la validité ERC-1271 peut dépendre de l’état, de la politique, du temps et d’appels externes actuels ; récupérer une adresse ne suffit pas pour un compte contrat.

Risques

  • chainId erroné ou absent
  • verifyingContract contrefait ou inattendu
  • name ou version de domaine trompeur
  • Implémentation proxy ou domaine modifié après mise à niveau
  • primaryType erroné ou type fantôme au libellé proche
  • Ordre des membres, dépendances ou encodeur incompatible
  • Adresse tronquée, substituée ou étiquetée de façon trompeuse
  • Erreur de décimales ou d’entier signé contre non signé
  • Élément de tableau, structure imbriquée ou charge bytes cachée
  • Montant illimité, portée large ou destinataire contrôlé par l’attaquant
  • Nonce absent, périmé, partagé ou mal consommé
  • Échéance absente, lointaine, en dépassement ou ambiguë
  • Répétition entre chaînes, contrats, comptes ou actions
  • Rétention, censure, front-running ou redirection par le relayeur
  • Malléabilité de signature ou récupération ECDSA trop permissive
  • Changement de signataire, module, seuil, état ou code ERC-1271
  • Rendu du portefeuille, blind signing ou type non pris en charge
  • JSON du frontend différent du condensé du vérificateur
  • Révocation ou annulation perdant une course d’ordonnancement
  • Confusion entre dialogue de signature, reçu, état et finalité

Idées reçues

Idée reçue 1 : Les signatures EIP-712 sont des transactions

Ce sont des messages signés hors chaîne. Un relayeur peut les soumettre ensuite à un contrat ; la transaction résultante peut consommer du Gas et changer l’état sans être envoyée par le signataire.

Idée reçue 2 : Un affichage structuré rend la demande sûre

Les champs typés facilitent l’examen, mais schémas, valeurs, contrats, libellés, imbrications cachées ou rendu incomplet malveillants peuvent encore tromper.

Idée reçue 3 : Le séparateur de domaine empêche toute répétition

Il ne sépare que le domaine encodé. La répétition dans un même domaine exige nonce, échéance, annulation, comptabilité d’exécution ou idempotence ; un champ omis ne crée aucune frontière.

Idée reçue 4 : Récupérer l’adresse attendue prouve l’autorisation

La récupération prouve une signature EOA sur le condensé, pas la sémantique applicative. Les comptes contrats exigent leur politique ERC-1271 plutôt qu’une récupération ordinaire.

Idée reçue 5 : Fermer la page ou déconnecter le portefeuille annule la signature

Une signature copiée reste utilisable jusqu’à ce que nonce, échéance, annulation, état ou politique du vérificateur l’invalide. Vérifiez l’état on-chain pertinent, pas la session.

Sujets connexes

Sources

Navigation

Rechercher dans le wiki...