EIP-1271 : Signature et vérification des signatures de contrats intelligents
La norme EIP-1271 (opens in a new tab) permet aux contrats intelligents de vérifier les signatures.
Dans ce tutoriel, nous donnons un aperçu des signatures numériques, du contexte de l'EIP-1271 et de la mise en œuvre spécifique de l'EIP-1271 utilisée par Safe (opens in a new tab) (anciennement Gnosis Safe). L'ensemble peut servir de point de départ à la mise en œuvre de la norme EIP-1271 dans vos propres contrats.
Qu'est-ce qu'une signature ?
Dans ce contexte, une signature (plus précisément, une « signature numérique ») est un message accompagné d'une forme de preuve que le message provient d'une personne, d'un expéditeur ou d'une adresse spécifique.
Par exemple, une signature numérique peut se présenter comme suit :
- Message : « Je veux me connecter à ce site web avec mon portefeuille Ethereum. »
- Signataire : Mon adresse est
0x000… - Preuve : Voici une preuve que c'est bien moi,
0x000…, qui ai créé l'intégralité de ce message (il s'agit généralement de quelque chose de cryptographique).
Il est important de noter qu'une signature numérique comprend à la fois un « message » et une « signature ».
Pourquoi ? À titre d'exemple, si vous me donnez un contrat à signer, que je retire la page de signature et que je ne vous remets que mes signatures sans le reste du contrat, le contrat n'est pas valide.
De même, une signature numérique ne signifie rien sans un message associé !
Pourquoi l'EIP-1271 existe-t-elle ?
Pour créer une signature numérique à utiliser sur les blockchains basées sur Ethereum, vous avez généralement besoin d'une clé privée secrète que personne d'autre ne connaît. C'est ce qui fait que votre signature vous appartient (personne d'autre ne peut créer la même signature sans connaître la clé secrète).
Votre compte Ethereum (c.-à-d. votre compte détenu en externe/EOA) est associé à une clé privée, et c'est cette clé privée qui est généralement utilisée lorsqu'un site Web ou une dapp vous demande une signature (p. ex. pour « Se connecter avec Ethereum »).
Une application peut vérifier une signature (opens in a new tab) que vous créez à l'aide d'une bibliothèque tierce comme ethers.js sans connaître votre clé privée (opens in a new tab) et avoir la certitude que c'est vous qui avez créé la signature.
En fait, parce que les signatures numériques EOA utilisent la cryptographie à clé publique, elles peuvent être générées et vérifiées hors chaîne ! C'est ainsi que fonctionne le vote DAO sans gaz — au lieu de soumettre des votes en chaîne, les signatures numériques peuvent être créées et vérifiées hors chaîne à l'aide de bibliothèques cryptographiques.
Alors que les comptes EOA disposent d'une clé privée, les comptes de contrats intelligents ne disposent d'aucune forme de clé privée ou secrète (de sorte que la fonction « Se connecter avec Ethereum », etc. ne peut pas fonctionner nativement avec les comptes de contrats intelligents).
Le problème que l'EIP-1271 cherche à résoudre : comment savoir si la signature d'un contrat intelligent est valide si le contrat intelligent n'a pas de « secret » qu'il peut incorporer dans la signature ?
Comment fonctionne l'EIP-1271 ?
Les contrats intelligents ne disposent pas de clés privées pouvant être utilisées pour signer des messages. Alors, comment savoir si une signature est authentique ?
Eh bien, une idée est que nous pouvons simplement demander au contrat intelligent si une signature est authentique !
L'EIP-1271 normalise l'idée de « demander » à un contrat intelligent si une signature donnée est valide.
Un contrat qui implémente l'EIP-1271 doit avoir une fonction appelée isValidSignature qui prend en entrée un message et une signature. Le contrat peut alors exécuter une logique de validation (la spécification n'impose rien de spécifique ici) et renvoyer une valeur indiquant si la signature est valide ou non.
Si isValidSignature renvoie un résultat valide, c'est en gros le contrat qui dit « oui, j'approuve cette signature + ce message ! »
Interface
Voici l'interface exacte dans la spécification EIP-1271 (nous parlerons du paramètre _hash ci-dessous, mais pour l'instant, considérez-le comme le message en cours de vérification) :
1pragma solidity ^0.5.0;23contract ERC1271 {45 // bytes4(keccak256("isValidSignature(bytes32,bytes)")6 bytes4 constant internal MAGICVALUE = 0x1626ba7e;78 /**9 * @dev Devrait retourner si la signature fournie est valide pour le hachage fourni10 * @param _hash Hachage des données à signer11 * @param _signature Tableau d'octets de la signature associé à _hash12 *13 * DOIT retourner la valeur magique bytes4 0x1626ba7e lorsque la fonction réussit.14 * NE DOIT PAS modifier l'état (en utilisant STATICCALL pour solc < 0.5, modificateur view pour solc > 0.5)15 * DOIT autoriser les appels externes16 */17 function isValidSignature(18 bytes32 _hash,19 bytes memory _signature)20 public21 view22 returns (bytes4 magicValue);23}Afficher toutExemple d'implémentation EIP-1271 : Safe
Les contrats peuvent implémenter isValidSignature de nombreuses manières — la spécification elle-même ne dit pas grand-chose sur l'implémentation exacte.
Un contrat significatif qui met en œuvre l'EIP-1271 est Safe (anciennement Gnosis Safe).
Dans le code de Safe, isValidSignature est implémenté (opens in a new tab) de sorte que les signatures peuvent être créées et vérifiées de deux manières (opens in a new tab) :
- Messages en chaîne
- Création : un propriétaire du coffre-fort crée une nouvelle transaction sécurisée pour « signer » un message, en transmettant le message sous forme de données dans la transaction. Une fois que suffisamment de propriétaires ont signé la transaction pour atteindre le seuil multisig, la transaction est diffusée et exécutée. Dans la transaction, il y a une fonction de Safe appelée (
signMessage(bytes calldata _data)) qui ajoute le message à une liste de messages « approuvés ». - Vérification : appelez
isValidSignaturesur le contrat Safe, et passez le message à vérifier comme paramètre de message et une valeur vide pour le paramètre de signature (opens in a new tab) (c.-à-d.,0x). Le Safe verra que le paramètre de signature est vide et au lieu de vérifier cryptographiquement la signature, il saura simplement aller de l'avant et vérifier si le message figure sur la liste des messages « approuvés ».
- Création : un propriétaire du coffre-fort crée une nouvelle transaction sécurisée pour « signer » un message, en transmettant le message sous forme de données dans la transaction. Une fois que suffisamment de propriétaires ont signé la transaction pour atteindre le seuil multisig, la transaction est diffusée et exécutée. Dans la transaction, il y a une fonction de Safe appelée (
- Messages hors chaîne :
- Création : un propriétaire de Safe crée un message hors chaîne, puis demande à d'autres propriétaires de Safe de signer le message chacun individuellement jusqu'à ce qu'il y ait suffisamment de signatures pour dépasser le seuil d'approbation multisig.
- Vérification : appelez
isValidSignature. Dans le paramètre du message, envoyez le message à vérifier. Dans le paramètre de signature, transmettez les signatures individuelles de chaque propriétaire de coffre-fort, toutes concaténées ensemble, dos à dos. Le Safe vérifiera qu'il y a suffisamment de signatures pour atteindre le seuil et que chaque signature est valide. Si c'est le cas, il renverra une valeur indiquant une vérification de signature réussie.
Qu'est-ce que le paramètre _hash exactement ? Pourquoi ne pas transmettre le message dans son intégralité ?
Vous avez peut-être remarqué que la fonction isValidSignature dans l'interface EIP-1271 (opens in a new tab) ne prend pas en entrée le message lui-même, mais plutôt un paramètre _hash. Cela signifie qu'au lieu de passer le message complet de longueur arbitraire à isValidSignature, nous passons un hachage de 32 octets du message (généralement keccak256).
Chaque octet de calldata — c.-à-d. les données de paramètre de fonction passées à une fonction de contrat intelligent — coûte 16 gaz (4 gaz si l'octet est un zéro) (opens in a new tab), ce qui peut permettre d'économiser beaucoup de gaz si un message est long.
Spécifications précédentes de l'EIP-1271
Il existe dans la nature des spécifications EIP-1271 qui ont une fonction isValidSignature avec un premier paramètre de type bytes (longueur arbitraire, au lieu d'une longueur fixe bytes32) et le nom de paramètre message. Il s'agit d'une ancienne version (opens in a new tab) de la norme EIP-1271.
Comment implémenter l'EIP-1271 dans mes propres contrats ?
Les spécifications sont très ouvertes à cet égard. L'implémentation de Safe présente quelques bonnes idées :
- Vous pouvez considérer les signatures EOA du « propriétaire » du contrat comme étant valides.
- Vous pouvez stocker une liste de messages approuvés et seulement considérer ceux qui sont valides.
En fin de compte, c'est à vous de décider en tant que développeur de contrat !
Conclusion
EIP-1271 (opens in a new tab) est une norme polyvalente qui permet aux contrats intelligents de vérifier les signatures. Cela ouvre la voie à des contrats intelligents pour qu'ils agissent davantage comme des EOA - par exemple, en offrant un moyen de faire fonctionner la fonction « Se connecter avec Ethereum » avec les contrats intelligents — et cela peut être implémenté de plusieurs façons (Safe offre une implémentation intéressante et originale à prendre en compte).
Dernière mise à jour de la page : 16 janvier 2026