Cryptographie

Bannière Amazon du livre Maîtriser Ethereum

L’une des technologies fondamentales d’Ethereum est la cryptographie, qui est une branche des mathématiques largement utilisées en sécurité informatique. La cryptographie signifie "écriture secrète" en grec, mais l’étude de la cryptographie englobe plus que la simple écriture secrète, appelée cryptage. La cryptographie peut, par exemple, également être utilisée pour prouver la connaissance d’un secret sans le révéler (par exemple, avec une signature numérique), ou pour prouver l’authenticité des données (par exemple, avec des empreintes digitales, également appelées "hachages"). Ces types de preuves cryptographiques sont des outils mathématiques essentiels au fonctionnement de la plate-forme Ethereum (et, en fait, de tous les systèmes de chaîne de blocs), et sont également largement utilisés dans les applications Ethereum.

Notez qu’au moment de la publication, aucune partie du protocole Ethereum n’implique de cryptage ; c’est-à-dire que toutes les communications avec la plateforme Ethereum et entre les nœuds (y compris les données de transaction) sont non cryptées et peuvent (nécessairement) être lues par n’importe qui. C’est ainsi que tout le monde peut vérifier l’exactitude des mises à jour d’état et qu’un consensus peut être atteint. À l’avenir, des outils cryptographiques avancés, tels que les preuves à zéro connaissance et le cryptage homomorphe, seront disponibles, ce qui permettra d’enregistrer certains calculs cryptés sur la chaîne de blocs tout en permettant le consensus ; cependant, bien que des dispositions aient été prises à leur intention, elles n’ont pas encore été déployées.

Dans ce chapitre, nous présenterons une partie de la cryptographie utilisée dans Ethereum : à savoir la cryptographie à clé publique (PKC), qui est utilisée pour contrôler la propriété des fonds, sous la forme de clés privées et d’adresses.

Clés et adresses

Comme nous l’avons vu précédemment dans le livre, Ethereum a deux types de comptes différents : les comptes détenus par des tiers ou en externe (Externally Owned Accounts ou EOA) et les contrats. La propriété de l’ether par les EOAs est établie par des clés privées numériques, des adresses Ethereum et des signatures numériques. Les clés privées sont au cœur de toutes les interactions des utilisateurs avec Ethereum. En fait, les adresses de compte sont directement dérivées des clés privées : une clé privée détermine de manière unique une seule adresse Ethereum, également appelée compte.

Les clés privées ne sont en aucun cas utilisées directement dans le système Ethereum ; ils ne sont jamais transmis ou stockés sur Ethereum. C’est-à-dire que les clés privées doivent rester privées et ne jamais apparaître dans les messages transmis au réseau, ni être stockées en chaîne ; seules les adresses de compte et les signatures numériques sont transmises et stockées sur le système Ethereum. Pour plus d’informations sur la manière de conserver les clés privées en toute sécurité, consultez [control_responsibility] et [wallets_chapter].

L’accès et le contrôle des fonds sont réalisés avec des signatures numériques, qui sont également créées à l’aide de la clé privée. Les transactions Ethereum nécessitent une signature numérique valide pour être incluses dans la chaîne de blocs. Toute personne disposant d’une copie d’une clé privée a le contrôle du compte correspondant et de tout ether qu’il détient. En supposant qu’un utilisateur garde sa clé privée en sécurité, les signatures numériques dans les transactions Ethereum prouvent le véritable propriétaire des fonds, car elles prouvent la propriété de la clé privée.

Dans les systèmes basés sur la cryptographie à clé publique, tels que ceux utilisés par Ethereum, les clés sont fournies par paires composées d’une clé privée (secrète) et d’une clé publique. Considérez la clé publique comme similaire à un numéro de compte bancaire et la clé privée comme similaire au code PIN secret ; c’est ce dernier qui fournit le contrôle sur le compte, et le premier qui l’identifie aux autres. Les clés privées elles-mêmes sont très rarement vues par les utilisateurs d’Ethereum ; pour la plupart, ils sont stockés (sous forme cryptée) dans des fichiers spéciaux et gérés par le logiciel de portefeuille Ethereum.

Dans la partie paiement d’une transaction Ethereum, le destinataire prévu est représenté par une adresse Ethereum, qui est utilisée de la même manière que les détails du compte bénéficiaire d’un virement bancaire. Comme nous le verrons plus en détail sous peu, une adresse Ethereum pour un EOA est générée à partir de la partie clé publique d’une paire de clés. Cependant, toutes les adresses Ethereum ne représentent pas des paires de clés publiques-privées ; ils peuvent aussi représenter des contrats, qui, comme nous le verrons dans [smart_contracts_chapter], ne sont pas soutenus par des clés privées.

Dans le reste de ce chapitre, nous allons d’abord explorer la cryptographie de base un peu plus en détail et expliquer les mathématiques utilisées dans Ethereum. Ensuite, nous verrons comment les clés sont générées, stockées et gérées. Enfin, nous passerons en revue les différents formats d’encodage utilisés pour représenter les clés privées, les clés publiques et les adresses.

Cryptographie à clé publique et cryptomonnaie

La cryptographie à clé publique (également appelée "cryptographie asymétrique") est un élément central de la sécurité de l’information moderne. Le protocole d’échange de clé, d’abord publié dans les années 1970 par Martin Hellman, Whitfield Diffie et Ralph Merkle, a été une percée monumentale qui a suscité la première grande vague d’intérêt public dans le domaine de la cryptographie. Avant les années 1970, de solides connaissances cryptographiques étaient gardées secrètes par les gouvernements.

La cryptographie à clé publique utilise des clés uniques pour sécuriser les informations. Ces clés sont basées sur des fonctions mathématiques qui ont une propriété particulière : il est facile de les calculer, mais difficile de calculer leur inverse. Sur la base de ces fonctions, la cryptographie permet la création de secrets numériques et de signatures numériques infalsifiables, qui sont sécurisées par les lois des mathématiques.

Par exemple, multiplier deux grands nombres premiers ensemble est trivial. Mais étant donné le produit de deux grands nombres premiers, il est très difficile de trouver les facteurs premiers (un problème appelé factorisation primaire ou première). Disons que nous présentons le nombre 8 018 009 et que nous vous disons qu’il est le produit de deux nombres premiers. Trouver ces deux nombres premiers est beaucoup plus difficile pour vous que pour moi de les multiplier pour produire 8 018 009.

Certaines de ces fonctions mathématiques peuvent être facilement inversées si vous connaissez des informations secrètes. Dans l’exemple précédent, si je vous dis que l’un des facteurs premiers est 2 003, vous pouvez trivialement trouver l’autre avec une simple division : 8 018 009 ÷ 2 003 = 4 003. Ces fonctions sont souvent appelées fonctions de trappe car elles sont très difficiles à inverser à moins que vous ne receviez une information secrète qui peut être utilisée comme raccourci pour inverser la fonction.

Une catégorie plus avancée de fonctions mathématiques utiles en cryptographie est basée sur des opérations arithmétiques sur une courbe elliptique. Dans l’arithmétique des courbes elliptiques, la multiplication modulo d’un nombre premier est simple mais la division (l’inverse) est pratiquement impossible. C’est ce qu’on appelle le problème de logarithme discret et il n’y a actuellement aucune trappe connue. La cryptographie à courbe elliptique est largement utilisée dans les systèmes informatiques modernes et constitue la base de l’utilisation par Ethereum (et d’autres cryptomonnaies) des clés privées et des signatures numériques.

Note

Consultez les ressources suivantes si vous souhaitez en savoir plus sur la cryptographie et les fonctions mathématiques utilisées dans la cryptographie moderne :

Dans Ethereum, nous utilisons la cryptographie à clé publique (également connue sous le nom de cryptographie asymétrique) pour créer la paire de clés publique-privée dont nous avons parlé dans ce chapitre. Ils sont considérés comme une "paire" car la clé publique est dérivée de la clé privée. Ensemble, ils représentent un compte Ethereum en fournissant, respectivement, un identifiant de compte accessible au public (l’adresse) et un contrôle privé sur l’accès à tout ether du compte et sur toute authentification dont le compte a besoin lors de l’utilisation de contrats intelligents. La clé privée contrôle l’accès en étant l’élément d’information unique nécessaire pour créer des signatures numériques, qui sont nécessaires pour signer des transactions afin de dépenser des fonds sur le compte. Les signatures numériques sont également utilisées pour authentifier les propriétaires ou les utilisateurs de contrats, comme nous le verrons dans [smart_contracts_chapter].

Tip

Dans la plupart des implémentations de portefeuille, les clés privées et publiques sont stockées ensemble sous la forme d’une paire de clés pour plus de commodité. Cependant, la clé publique peut être trivialement calculée à partir de la clé privée, de sorte qu’il est également possible de ne stocker que la clé privée.

Une signature numérique peut être créée pour signer n’importe quel message. Pour les transactions Ethereum, les détails de la transaction elle-même sont utilisés comme message. Les mathématiques de la cryptographie - dans ce cas, la cryptographie à courbe elliptique - permettent de combiner le message (c’est-à-dire les détails de la transaction) avec la clé privée pour créer un code qui ne peut être produit qu’avec la connaissance de la clé privée. Ce code s’appelle la signature numérique. Notez qu’une transaction Ethereum est essentiellement une demande d’accès à un compte particulier avec une adresse Ethereum particulière. Lorsqu’une transaction est envoyée au réseau Ethereum afin de déplacer des fonds ou d’interagir avec des contrats intelligents, elle doit être envoyée avec une signature numérique créée avec la clé privée correspondant à l’adresse Ethereum en question. Les mathématiques de la courbe elliptique signifient que n’importe qui peut vérifier qu’une transaction est valide, en vérifiant que la signature numérique correspond aux détails de la transaction et à l’adresse Ethereum à laquelle l’accès est demandé. La vérification n’implique pas du tout la clé privée ; qui reste privé. Cependant, le processus de vérification détermine sans aucun doute que la transaction ne peut provenir que de quelqu’un avec la clé privée qui correspond à la clé publique derrière l’adresse Ethereum. C’est la « magie » de la cryptographie à clé publique.

Tip

Il n’y a pas de cryptage dans le cadre du protocole Ethereum - tous les messages envoyés dans le cadre du fonctionnement du réseau Ethereum peuvent (nécessairement) être lus par tout le monde. En tant que telles, les clés privées ne sont utilisées que pour créer des signatures numériques pour l’authentification des transactions.

Clés privées

Une clé privée est simplement un nombre, choisi au hasard. La propriété et le contrôle de la clé privée sont à la base du contrôle de l’utilisateur sur tous les fonds associés à l’adresse Ethereum correspondante, ainsi que de l’accès aux contrats qui autorisent cette adresse. La clé privée est utilisée pour créer les signatures nécessaires pour dépenser de l’ether en prouvant la propriété des fonds utilisés dans une transaction. La clé privée doit rester secrète à tout moment, car la révéler à des tiers équivaut à leur donner le contrôle de l’ether et des contrats sécurisés par cette clé privée. La clé privée doit également être sauvegardée et protégée contre toute perte accidentelle. S’il est perdu, il ne peut pas être récupéré et les fonds garantis par celui-ci sont également perdus à jamais.

Tip

La clé privée Ethereum n’est qu’un chiffre. Une façon de choisir vos clés privées au hasard consiste simplement à utiliser une pièce de monnaie, un crayon et du papier : lancez une pièce 256 fois et vous obtenez les chiffres binaires d’une clé privée aléatoire que vous pouvez utiliser dans un portefeuille Ethereum (probablement - voir la section suivante ). La clé publique et l’adresse peuvent ensuite être générées à partir de la clé privée.

Générer une clé privée à partir d’un nombre aléatoire

Le premier et l’étape la plus importante dans la génération de clés consiste à trouver une source sécurisée d’entropie ou de caractère aléatoire. La création d’une clé privée Ethereum consiste essentiellement à choisir un nombre compris entre 1 et 2256. La méthode exacte que vous utilisez pour choisir ce nombre n’a pas d’importance tant qu’elle n’est pas prévisible ou déterministe. Le logiciel Ethereum utilise le générateur de nombres aléatoires du système d’exploitation sous-jacent pour produire 256 bits aléatoires. Habituellement, le générateur de nombres aléatoires du système d’exploitation est initialisé par une source humaine d’aléatoire, c’est pourquoi il peut vous être demandé de remuer votre souris pendant quelques secondes ou d’appuyer sur des touches aléatoires de votre clavier. Une alternative pourrait être le bruit de rayonnement cosmique sur le canal du microphone de l’ordinateur.

Plus précisément, une clé privée peut être n’importe quel nombre différent de zéro jusqu’à un très grand nombre légèrement inférieur à 2256 - un énorme nombre à 78 chiffres, environ 1,158 * 1077. Le nombre exact partage les 38 premiers chiffres avec 2256 et est défini comme l’ordre de la courbe elliptique utilisée dans Ethereum (voir La cryptographie à courbe elliptique expliquée). Pour créer une clé privée, nous choisissons au hasard un nombre de 256 bits et vérifions qu’il se trouve dans la plage valide. En termes de programmation, cela est généralement réalisé en introduisant une chaîne encore plus grande de bits aléatoires (collectés à partir d’une source aléatoire sécurisée par cryptographie) dans un algorithme de hachage de 256 bits tel que Keccak-256 ou SHA-256, qui produiront commodément un nombre de 256 bits. Si le résultat est dans la plage valide, nous avons une clé privée appropriée. Sinon, nous réessayons simplement avec un autre nombre aléatoire.

Tip

2256 - la taille de l’espace de clé privée d’Ethereum - est un nombre insondable. Il est d’environ 1077 en décimal ; c’est-à-dire un nombre à 77 chiffres. À titre de comparaison, on estime que l’univers visible contient 1080 atomes. Ainsi, il y a presque assez de clés privées pour donner à chaque atome de l’univers un compte Ethereum. Si vous choisissez une clé privée au hasard, il est impossible que quelqu’un la devine ou la choisisse lui-même.

Notez que le processus de génération de clé privée est hors ligne ; il ne nécessite aucune communication avec le réseau Ethereum, ni même aucune communication avec qui que ce soit. En tant que tel, afin de choisir un nombre que personne d’autre ne choisira jamais, il doit être vraiment aléatoire. Si vous choisissez vous-même le numéro, la probabilité que quelqu’un d’autre l’essaie (et s’enfuie ensuite avec votre ether) est trop élevée. Utiliser un mauvais générateur de nombres aléatoires (comme la fonction pseudo-aléatoire rand dans la plupart des langages de programmation) est encore pire, car il est encore plus évident et encore plus facile à reproduire. Tout comme pour les mots de passe des comptes en ligne, la clé privée doit être impossible à deviner. Heureusement, vous n’avez jamais besoin de vous souvenir de votre clé privée, vous pouvez donc adopter la meilleure approche possible pour la choisir : à savoir, le vrai hasard.

Warning

N’écrivez pas votre propre code pour créer un nombre aléatoire ou n’utilisez pas un "simple" générateur de nombres aléatoires proposé par votre langage de programmation. Il est essentiel que vous utilisiez un générateur de nombres pseudo-aléatoires cryptographiquement sécurisé (tel que CSPRNG) avec une valeur d’amorçage provenant d’une source d’entropie suffisante. Étudiez la documentation de la bibliothèque de générateurs de nombres aléatoires que vous choisissez pour vous assurer qu’elle est cryptographiquement sécurisée. La mise en œuvre correcte de la bibliothèque CSPRNG est essentielle à la sécurité des clés.

Ce qui suit est une clé privée générée aléatoirement affichée au format hexadécimal (256 bits affichés sous la forme de 64 chiffres hexadécimaux, chacun de 4 bits) :

f8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315

Clés publiques

Une clé publique Ethereum est un point sur une courbe elliptique, ce qui signifie qu’il s’agit d’un ensemble de coordonnées x et y qui satisfont l’équation de la courbe elliptique.

En termes plus simples, une clé publique Ethereum est constituée de deux nombres réunis. Ces chiffres sont produits à partir de la clé privée par un calcul qui ne peut aller que dans un sens. Cela signifie qu’il est trivial de calculer une clé publique si vous avez la clé privée, mais vous ne pouvez pas calculer la clé privée à partir de la clé publique.

Warning

Des MATHÉMATIQUES sont sur le point d’arriver ! Ne pas paniquer. Si vous commencez à vous perdre à n’importe quel moment dans les paragraphes suivants, vous pouvez ignorer les quelques sections suivantes. Il existe de nombreux outils et bibliothèques qui feront le calcul pour vous.

La clé publique est calculée à partir de la clé privée en utilisant la multiplication par courbe elliptique, qui est pratiquement irréversible : K = k * G, où k est la clé privée, G est un point constant appelé le point générateur, K est la clé publique résultante et * est l’opérateur spécial de "multiplication" de la courbe elliptique. Notez que la multiplication de courbe elliptique n’est pas comme la multiplication normale. Il partage des attributs fonctionnels avec la multiplication normale, mais c’est à peu près tout. Par exemple, l’opération inverse (qui serait une division pour des nombres normaux), connue sous le nom de "trouver le logarithme discret" - c’est-à-dire calculer k si vous connaissez K - est aussi difficile que d’essayer toutes les valeurs possibles de k (une recherche par force brute cela prendra probablement plus de temps que cet univers ne le permettra).

En termes plus simples : l’arithmétique sur la courbe elliptique est différente de l’arithmétique entière "régulière". Un point (G) peut être multiplié par un entier (k) pour produire un autre point (K). Mais la division n’existe pas, il n’est donc pas possible de simplement "diviser" la clé publique K par le point G pour calculer la clé privée k. Il s’agit de la fonction mathématique à sens unique décrite dans Cryptographie à clé publique et cryptomonnaie.

Note

La multiplication de courbe elliptique est un type de fonction que les cryptographes appellent une fonction "à sens unique" : elle est facile à faire dans un sens (multiplication) et impossible à faire dans le sens inverse (division). Le propriétaire de la clé privée peut facilement créer la clé publique puis la partager avec le monde, sachant que personne ne peut inverser la fonction et calculer la clé privée à partir de la clé publique. Cette astuce mathématique devient la base de signatures numériques infalsifiables et sécurisées qui prouvent la propriété des fonds Ethereum et le contrôle des contrats.

Avant de montrer comment générer une clé publique à partir d’une clé privée, examinons un peu plus en détail la cryptographie à courbe elliptique.

La cryptographie à courbe elliptique expliquée

La courbe elliptique cryptographique est un type de cryptographie asymétrique ou cryptographie à clé publique basée sur le problème du logarithme discret exprimé par addition et multiplication sur les points d’une courbe elliptique.

Une visualisation d’une courbe elliptique est un exemple de courbe elliptique, similaire à celle utilisée par Ethereum.

Note

Ethereum utilise exactement la même courbe elliptique, appelée secp256k1, que Bitcoin. Cela permet de réutiliser de nombreuses bibliothèques et outils de courbes elliptiques de Bitcoin.

ecc-curve
Figure 1. Une visualisation d’une courbe elliptique

Ethereum utilise une courbe elliptique spécifique et un ensemble de constantes mathématiques, telles que définies dans une norme appelée secp256k1, établie par le National Institute of Standards and Technology (NIST) des États-Unis. La courbe secp256k1 est définie par la fonction suivante, qui produit une courbe elliptique :

y2 = (x3 + 7) over (𝔽 p)

ou alors:

y2 mod p = (x3 + 7) mod p

Le mod p (modulo nombre premier p) indique que cette courbe est sur un corps fini d’ordre premier p, également écrit comme (𝔽 p), où p = 2256 – 232 – 29 – 28 – 27 – 26 – 24 – 1, qui est un très grand nombre premier.

Parce que cette courbe est définie sur un champ fini d’ordre premier au lieu de sur les nombres réels, elle ressemble à un motif de points dispersés en deux dimensions, ce qui la rend difficile à visualiser. Cependant, le calcul est identique à celui d’une courbe elliptique sur des nombres réels. A titre d’exemple, Cryptographie sur courbe elliptique: visualisation d’une courbe elliptique sur F(p), avec p=17 montre la même courbe elliptique sur un champ fini beaucoup plus petit d’ordre premier 17, montrant un motif de points sur une grille. La courbe elliptique secp256k1 Ethereum peut être considérée comme un motif beaucoup plus complexe de points sur une grille insondable.

ecc-over-F17-math
Figure 2. Cryptographie sur courbe elliptique: visualisation d’une courbe elliptique sur F(p), avec p=17

Ainsi, par exemple, ce qui suit est un point Q avec des coordonnées (x,y) qui est un point sur la courbe secp256k1 :

Q =
(49790390825249384486033144355916864607616083520101638681403973749255924539515,
59574132161899900045862086493921015780032175291755807399284007721050341297360)

[example_1] montre comment vous pouvez vérifier cela vous-même en utilisant Python. Les variables x et y sont les coordonnées du point Q, comme dans l’exemple précédent. La variable p est l’ordre premier de la courbe elliptique (le premier qui est utilisé pour toutes les opérations modulo). La dernière ligne de Python est l’équation de la courbe elliptique (l’opérateur % en Python est l’opérateur modulo). Si x et y sont bien les coordonnées d’un point sur la courbe elliptique, alors elles satisfont l’équation et le résultat est zéro (0L est un entier long valant zéro). Essayez vous-même, en tapant python sur une ligne de commande et en copiant chaque ligne (après l’invite + >>> +)de la liste.

Utiliser Python pour confirmer que ce point est sur la courbe elliptique
Python 3.4.0 (default, Mar 30 2014, 19:23:13)
[GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.38)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> p = 115792089237316195423570985008687907853269984665640564039457584007908834 \
671663
>>> x = 49790390825249384486033144355916864607616083520101638681403973749255924539515
>>> y = 59574132161899900045862086493921015780032175291755807399284007721050341297360
>>> (x ** 3 + 7 - y**2) % p
0L

Opérations arithmétiques sur les courbes elliptiques

Beaucoup de mathématiques sur les courbes elliptiques ressemblent beaucoup à l’arithmétique des nombres entiers que nous avons apprise à l’école. Plus précisément, nous pouvons définir un opérateur d’addition qui, au lieu de sauter le long de la droite numérique, saute vers d’autres points de la courbe. Une fois que nous avons l’opérateur d’addition, nous pouvons également définir la multiplication d’un point et d’un nombre entier, ce qui équivaut à une addition répétée.

L’addition de courbe elliptique est définie de telle sorte que, étant donné deux points P1 et P2 sur la courbe elliptique, il existe un troisième point P3 = P1 + P2, également sur la courbe elliptique.

Géométriquement, ce troisième point P3 est calculé en traçant une ligne entre P1 et P2. Cette ligne coupera la courbe elliptique exactement à un endroit supplémentaire (étonnamment). Appelez ce point P3' = (x, y). Réfléchissez ensuite sur l’axe des x pour obtenir P3 = (x, –y).

Si P1 et P2 sont au même point, la ligne "entre" P1 et P2 devrait s’étendre pour être la tangente à la courbe en ce point P1. Cette tangente coupera la courbe exactement en un nouveau point. Vous pouvez utiliser des techniques de calcul pour déterminer la pente de la ligne tangente. Curieusement, ces techniques fonctionnent, même si nous restreignons notre intérêt aux points de la courbe à deux coordonnées entières !

Dans les mathématiques des courbes elliptiques, il existe également un point appelé "point à l’infini", qui correspond à peu près au rôle du nombre zéro en addition. Sur les ordinateurs, il est parfois représenté par x = y = 0 (ce qui ne satisfait pas l’équation de la courbe elliptique, mais c’est un cas séparé facile qui peut être vérifié). Il y a quelques cas particuliers qui expliquent la nécessité du point à l’infini.

Dans certains cas (par exemple, si P1 et P2 ont les mêmes valeurs x mais des valeurs y différentes), la ligne sera exactement verticale, auquel cas P3 = le point à l’infini.

Si P1 est le point à l’infini, alors P1 + P2 = P2. De même, si P2 est le point à l’infini, alors P1 + P2 = P1. Cela montre comment le point à l’infini joue le rôle que joue zéro dans l’arithmétique "normale".

Il s’avère que + est associatif, ce qui signifie que (A + B) + C = A + (B + C). Cela signifie que nous pouvons écrire A + B + C (sans parenthèses) sans ambiguïté.

Maintenant que nous avons défini l’addition, nous pouvons définir la multiplication de la manière standard qui étend l’addition. Pour un point P sur la courbe elliptique, si k est un nombre entier, alors k * P = P + P + P + …​ + P (k fois). Notez que k est parfois (peut-être de manière déroutante) appelé un "exposant" dans ce cas.

Génération d’une clé publique

Commencer avec une clé privée sous la forme d’un nombre k généré aléatoirement, nous le multiplions par un point prédéterminé sur la courbe appelé point générateur G pour produire un autre point ailleurs sur la courbe, qui est la clé publique correspondante K :

K = k * G

Le point générateur est spécifié dans le cadre de la norme secp256k1 ; c’est la même chose pour toutes les implémentations de secp256k1, et toutes les clés dérivées de cette courbe utilisent le même point G. Comme le point générateur est toujours le même pour tous les utilisateurs d’Ethereum, une clé privée k multipliée par G donnera toujours la même clé publique K. La relation entre k et K est fixe, mais ne peut être calculée que dans un sens, de k vers K. C’est pourquoi une adresse Ethereum (dérivée de K) peut être partagée avec n’importe qui et ne révèle pas la clé privée de l’utilisateur (k).

Comme nous l’avons décrit dans la section précédente, la multiplication de k * G est équivalente à une addition répétée, donc G + G + G + …​ + G, répété k fois. En résumé, pour produire une clé publique K à partir d’une clé privée k, on ajoute le point générateur G à lui-même, k fois.

Tip

Une clé privée peut être convertie en clé publique, mais une clé publique ne peut pas être reconvertie en clé privée, car le calcul ne fonctionne que dans un sens.

Appliquons ce calcul pour trouver la clé publique de la clé privée spécifique que nous vous avons montrée dans Clés privées :

Exemple de calcul de clé privée à clé publique
K = f8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315 * G

Une bibliothèque cryptographique peut nous aider à calculer K, en utilisant la multiplication de courbes elliptiques. La clé publique résultante K est définie comme le point :

K = (x, y)

où :

x = 6e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b
y = 83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0

Dans Ethereum, vous pouvez voir des clés publiques représentées par une sérialisation de 130 caractères hexadécimaux (65 octets ). Ceci est adopté à partir d’un format de sérialisation standard proposé par le consortium industriel Standards for Efficient Cryptography Group (SECG), documenté dans http://www.secg.org/sec1-v2.pdf [Standards for Efficient Cryptography (SEC1)]. La norme définit quatre préfixes possibles pouvant être utilisés pour identifier des points sur une courbe elliptique, répertoriés dans Préfixes de clé publique EC sérialisés.

Table 1. Préfixes de clé publique EC sérialisés
Préfixe Signification Longueur (octets comptant le préfixe)

0x00

Pointe à l’infini

1

0x04

Point non compressé

65

0x02

Point compressé avec pair y

33

0x03

Point compressé avec impair y

33

Ethereum utilise uniquement des clés publiques non compressées ; par conséquent, le seul préfixe pertinent est (hex) 04. La sérialisation concatène les coordonnées x et y de la clé publique :

04 + coordonnée x (32 octets/64 hex) + coordonnée y (32 octets/64 hex)

Par conséquent, la clé publique que nous avons calculée précédemment est sérialisée comme suit :

046e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b83b5c38e5e2b0 \
c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0

Bibliothèques de courbes elliptiques

Il existe quelques implémentations de la courbe elliptique secp256k1 qui sont utilisées dans les projets liés à la cryptomonnaie :

OpenSSL

La bibliothèque OpenSSL offre un ensemble complet de primitives cryptographiques, y compris une implémentation complète de secp256k1. Par exemple, pour dériver la clé publique, la fonction EC_POINT_mul peut être utilisée.

libsecp256k1

libsecp256k1 de Bitcoin Core est une implémentation en langage C de la courbe elliptique secp256k1 et d’autres primitives cryptographiques. Il a été écrit à partir de zéro pour remplacer OpenSSL dans le logiciel Bitcoin Core et est considéré comme supérieur en termes de performances et de sécurité.

Fonctions de hachage cryptographique

Les fonctions de hachage cryptographiques sont utilisées dans Ethereum. En fait, les fonctions de hachage sont largement utilisées dans presque tous les systèmes cryptographiques - un fait capturé par cryptographeur Bruce Schneier, qui a dit , "Bien plus que des algorithmes de chiffrement, les fonctions de hachage unidirectionnelles sont les bêtes de somme de la cryptographie moderne."

Dans cette section, nous discuterons des fonctions de hachage, explorerons leurs propriétés de base et verrons comment ces propriétés les rendent si utiles dans de nombreux domaines de la cryptographie moderne. Nous abordons ici les fonctions de hachage car elles font partie de la transformation des clés publiques Ethereum en adresses. Ils peuvent également être utilisés pour créer des empreintes digitales, qui facilitent la vérification des données.

En termes simples, une fonction de hachage est "toute fonction qui peut être utilisée pour mapper des données de taille arbitraire à des données de taille fixe. ” L’entrée d’une fonction de hachage est appelée une pré-image, le message ou simplement les données d’entrée. La sortie est appelée hash ou résultat de hachage ou hachage en français. Les fonctions de hachage cryptographiques sont une sous-catégorie spéciale qui possède des propriétés spécifiques utiles pour sécuriser les plates-formes, telles qu’Ethereum.

Une fonction de hachage cryptographique est une fonction de hachage unidirectionnelle qui associe des données de taille arbitraire à une chaîne de bits de taille fixe. La nature "unidirectionnelle" signifie qu’il est impossible de recréer les données d’entrée si l’on ne connaît que le hachage de sortie. La seule façon de déterminer une entrée possible est de mener une recherche par force brute, en vérifiant chaque candidat pour une sortie correspondante ; étant donné que l’espace de recherche est virtuellement infini, il est aisé de comprendre l’impossibilité pratique de la tâche. Même si vous trouvez des données d’entrée qui créent un hachage correspondant, il se peut qu’il ne s’agisse pas des données d’entrée d’origine : les fonctions de hachage sont des fonctions "plusieurs vers un". Trouver deux ensembles de données d’entrée qui hachent la même sortie s’appelle trouver une collision de hachage. En gros, plus la fonction de hachage est bonne, plus les collisions de hachage sont rares. Pour Ethereum, ils sont effectivement impossibles.

Regardons de plus près les principales propriétés des fonctions de hachage cryptographiques. Ceux-ci inclus:

Déterministe

Un message d’entrée donné produit toujours la même sortie de hachage.

Vérifiable

Le calcul du hachage d’un message est efficace (complexité linéaire).

Non-corrélationnaire

Une petite modification du message (par exemple, un changement de 1 bit) devrait modifier la sortie de hachage si largement qu’elle ne peut pas être corrélée au hachage du message d’origine.

Irréversibile

Le calcul du message à partir de son hachage est irréalisable, ce qui équivaut à une recherche par force brute dans tous les messages possibles.

Protection contre les collisions

Il devrait être impossible de calculer deux messages différents qui produisent la même sortie de hachage.

La résistance aux collisions de hachage est particulièrement importante pour éviter la falsification de signature numérique dans Ethereum.

La combinaison de ces propriétés rend les fonctions de hachage cryptographiques utiles pour un large éventail d’applications de sécurité, notamment :

  • Empreinte des données

  • Intégrité des messages (détection d’erreur)

  • Preuve de travail

  • Authentification (hachage de mot de passe et étirement de clé)

  • Générateurs de nombres pseudo-aléatoires

  • Engagement de message (mécanismes de validation-révélation)

  • Identifiants uniques

Nous en trouverons beaucoup dans Ethereum au fur et à mesure que nous progressons dans les différentes couches du système.

Fonction de hachage cryptographique d’Ethereum : Keccak-256

Ethereum utilise le hachage cryptographique Keccak-256 dans de nombreux endroits. Keccak-256 a été conçu comme candidat pour le SHA-3 Cryptographic Hash Function Competition organisé en 2007 par le National Institute of Science and Technology (NIST). Keccak était l’algorithme gagnant, qui a été normalisé en tant que Federal Information Processing Standard (FIPS) 202 en 2015.

Cependant, pendant la période de développement d’Ethereum, la normalisation du NIST n’était pas encore finalisée. Le NIST a ajusté certains des paramètres de Keccak après l’achèvement du processus de normalisation, prétendument pour améliorer son efficacité. Cela se produisait en même temps que le dénonciateur héroïque Edward Snowden a révélé des documents qui impliquent que le NIST pourrait avoir été indûment influencé par la National Security Agency (NSA) pour affaiblir intentionnellement la norme de générateur de nombres aléatoires Dual_EC_DRBG, plaçant effectivement une porte dérobée dans le générateur de nombres aléatoires standard. Le résultat de cette controverse a été une réaction violente contre les modifications proposées et un retard important dans la normalisation de SHA-3. À l’époque, la Fondation Ethereum a décidé d’implémenter l’algorithme Keccak original, tel que proposé par ses inventeurs, plutôt que la norme SHA-3 telle que modifiée par le NIST.

Warning

Bien que vous puissiez voir "SHA-3" mentionné dans les documents et le code Ethereum, beaucoup, sinon toutes, de ces instances font en fait référence à Keccak-256, et non à la norme FIPS-202 SHA-3 finalisée. Les différences d’implémentation sont légères, liées aux paramètres de remplissage, mais elles sont importantes dans la mesure où Keccak-256 produit des sorties de hachage différentes de FIPS-202 SHA-3 pour la même entrée.

Quelle fonction de hachage suis-je en train d’utiliser ?

Comment pouvez-vous savoir si la bibliothèque de logiciels que vous utilisez implémente FIPS-202 SHA-3 ou Keccak-256, si les deux pouvaient s’appeler "SHA-3" ?

Un moyen simple de le dire est d’utiliser un vecteur de test, une sortie attendue pour une entrée donnée. Le test le plus couramment utilisé pour une fonction de hachage est l' entrée vide. Si vous exécutez la fonction de hachage avec une chaîne vide en entrée, vous devriez voir les résultats suivants :

Keccak256("") =
  c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470

SHA3("") =
  a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a

Quel que soit le nom de la fonction, vous pouvez la tester pour voir s’il s’agit du Keccak-256 d’origine ou de la norme NIST finale FIPS-202 SHA-3 en exécutant ce test simple. N’oubliez pas qu’Ethereum utilise Keccak-256, même s’il est souvent appelé SHA-3 dans le code.

Note

En raison de la confusion créée par la différence entre la fonction de hachage utilisée dans Ethereum (Keccak-256) et la norme finalisée (FIP-202 SHA-3), des efforts sont en cours pour renommer toutes les instances de sha3 dans tous les codes, opcodes, et des bibliothèques à keccak256. Voir ERC59 pour plus de détails.

Examinons ensuite la première application de Keccak-256 dans Ethereum, qui consiste à produire des adresses Ethereum à partir de clés publiques.

Adresses Ethereum

Les adresses Ethereum sont des identifiants uniques dérivés de clés publiques ou de contrats utilisant la fonction de hachage unidirectionnelle Keccak-256.

Dans nos exemples précédents, nous avons commencé avec une clé privée et avons utilisé la multiplication par courbe elliptique pour dériver une clé publique :

Clé privée k :

k = f8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315

Clé publique K (coordonnées x et y concaténées et affichées en hexadécimal) :

K = 6e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b83b5c38e5e...
Note

Il est à noter que la clé publique n’est pas formatée avec le préfixe (hex) 04 lors du calcul de l’adresse.

Nous utilisons Keccak-256 pour calculer le hachage de cette clé publique :

Keccak256(K) = 2a5bc342ed616b5ba5732269001d3f1ef827552ae1114027bd3ecf1f086ba0f9

Ensuite, nous ne gardons que les 20 derniers octets (octets les moins significatifs), qui sont notre adresse Ethereum :

001d3f1ef827552ae1114027bd3ecf1f086ba0f9

Le plus souvent, vous verrez des adresses Ethereum avec le préfixe 0x qui indique qu’elles sont codées en hexadécimal, comme ceci :

0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9

Formats d’adresse Ethereum

Les adresses Ethereum sont des nombres hexadécimaux, des identifiants dérivés des 20 derniers octets du hachage Keccak-256 de la clé publique.

("somme de contrôle","dans les formats d’adresses Ethereum"Contrairement aux adresses Bitcoin, qui sont encodées dans l’interface utilisateur de tous les clients pour inclure une somme de contrôle intégrée pour se protéger contre les adresses mal saisies, les adresses Ethereum sont présentées sous forme hexadécimale brute sans aucune somme de contrôle.

La justification de cette décision était que les adresses Ethereum seraient éventuellement cachées derrière des abstractions (telles que les services de noms) aux couches supérieures du système et que des sommes de contrôle devraient être ajoutées aux couches supérieures si nécessaire.

En réalité, ces couches supérieures ont été développées trop lentement et ce choix de conception a entraîné un certain nombre de problèmes dans les premiers jours de l’écosystème, notamment la perte de fonds en raison d’adresses mal saisies et d’erreurs de validation des entrées. De plus, comme les services de noms Ethereum ont été développés plus lentement que prévu initialement, les encodages alternatifs ont été adoptés très lentement par les développeurs de portefeuilles. Nous examinerons ensuite quelques-unes des options d’encodage.

Inter Exchange Client Address Protocol (ICAP)

Le client Inter exchange Address Protocol (ICAP) est un codage d’adresse Ethereum partiellement compatible avec le International Bank Account Number (IBAN), offrant un encodage polyvalent, à somme de contrôle et interopérable pour les adresses Ethereum. Les adresses ICAP peuvent encoder des adresses Ethereum ou des noms communs enregistrés auprès d’un registre de noms Ethereum. Vous pouvez en savoir plus sur ICAP sur Ethereum Wiki.

L’IBAN est une norme internationale d’identification des numéros de compte bancaire, principalement utilisée pour les virements électroniques. Il est largement adopté dans l’espace européen unique de paiements en euros (SEPA) et au-delà. L’IBAN est un service centralisé et fortement réglementé. ICAP est une implémentation décentralisée mais compatible pour les adresses Ethereum.

Un IBAN consiste en une chaîne de 34 caractères alphanumériques au maximum (insensible à la casse) comprenant un code pays, une somme de contrôle et un identifiant de compte bancaire (qui est spécifique au pays).

ICAP utilise la même structure en introduisant un code de pays non standard, "XE", qui signifie "Ethereum", suivi d’une somme de contrôle à deux caractères et de trois variantes possibles d’un identifiant de compte :

Direct

Un entier gros-boutiste base-36 comprenant jusqu’à 30 caractères alphanumériques, représentant les 155 bits les moins significatifs d’une adresse Ethereum. Étant donné que cet encodage correspond à moins que les 160 bits complets d’une adresse Ethereum générale, il ne fonctionne que pour les adresses Ethereum qui commencent par un ou plusieurs octets à zéro. L’avantage est qu’il est compatible avec l’IBAN, en termes de longueur de champ et de somme de contrôle. Exemple : XE60HAMICDXSV5QXVJA7TJW47Q9CHWKJD (33 caractères).

Basic

Identique à l’encodage Direct, sauf qu’il comporte 31 caractères. Cela lui permet d’encoder n’importe quelle adresse Ethereum, mais la rend incompatible avec la validation du champ IBAN. Exemple : XE18CHDJBPLTBCJ03FE9O2NS0BPOJVQCU2P (35 caractères).

Indirect

Encode un identifiant qui se résout en une adresse Ethereum via un fournisseur de registre de noms. Il utilise 16 caractères alphanumériques, comprenant un identifiant d’actif (par exemple, ETH), un service de nom (par exemple, XREG) et un nom lisible par l’homme à 9 caractères (par exemple, KITTYCATS). Exemple : XE##ETHXREGKITTYCATS (longueur de 20 caractères), où le ## doit être remplacé par les deux caractères de la somme de contrôle calculée.

Nous pouvons utiliser l’outil de ligne de commande helpeth pour créer des adresses ICAP. Vous pouvez obtenir de l’aide en l’installant avec :

$ npm install -g helpeth

Si vous n’avez pas npm, vous devrez peut-être d’abord installer nodeJS, ce que vous pouvez faire en suivant les instructions sur https://nodeJS.org.

Maintenant que nous avons helpeth, essayons de créer une adresse ICAP avec notre exemple de clé privée (préfixée par 0x et passée en paramètre à helpeth).

$ helpeth keyDetails \
  -p 0xf8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315

Address: 0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9
ICAP: XE60 HAMI CDXS V5QX VJA7 TJW4 7Q9C HWKJ D
Public key: 0x6e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b...

La commande helpeth construit une adresse Ethereum hexadécimale ainsi qu’une adresse ICAP pour nous. L’adresse ICAP de notre exemple de clé est :

XE60HAMICDXSV5QXVJA7TJW47Q9CHWKJD

Étant donné que notre exemple d’adresse Ethereum commence par un octet zéro, il peut être encodé à l’aide de la méthode d’encodage Direct ICAP qui est valide au format IBAN. Vous pouvez le dire car il comporte 33 caractères.

Si notre adresse ne commençait pas par un zéro, elle serait encodée avec l’encodage Basic, qui comporterait 35 caractères et serait invalide en tant qu’IBAN.

Tip

Les chances qu’une adresse Ethereum commence par un octet zéro sont de 1 sur 256. Pour en générer une comme celle-là, il faudra en moyenne 256 tentatives avec 256 clés privées aléatoires différentes avant d’en trouver une qui fonctionne comme un type "Direct" compatible IBAN encodé comme adresse ICAP.

À l’heure actuelle, ICAP n’est malheureusement pris en charge que par quelques portefeuilles.

Encodage hexadécimal avec somme de contrôle en majuscules (EIP-55)

En raison de la lenteur du déploiement d’ICAP et des services de noms, une norme a été proposée par la Proposition d’amélioration d’Ethereum 55 (EIP-55). EIP-55 offre une somme de contrôle rétrocompatible pour les adresses Ethereum en modifiant la capitalisation de l’adresse hexadécimale. L’idée est que les adresses Ethereum sont insensibles à la casse et que tous les portefeuilles sont censés accepter les adresses Ethereum exprimées en majuscules ou en minuscules, sans aucune différence d’interprétation.

En modifiant la capitalisation des caractères alphabétiques dans l’adresse, nous pouvons transmettre une somme de contrôle qui peut être utilisée pour protéger l’intégrité de l’adresse contre les erreurs de frappe ou de lecture. Les portefeuilles qui ne prennent pas en charge les sommes de contrôle EIP-55 ignorent simplement le fait que l’adresse contient des majuscules mixtes, mais ceux qui la prennent en charge peuvent la valider et détecter les erreurs avec une précision de 99,986 %.

L’encodage en majuscules mixtes est subtil et vous ne le remarquerez peut-être pas au début. Notre exemple d’adresse est :

0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9

Avec une somme de contrôle à capitalisation mixte EIP-55, cela devient :

0x001d3F1ef827552Ae1114027BD3ECF1f086bA0F9

Pouvez-vous faire la différence ? Certains des caractères alphabétiques (A à F) de l’alphabet de codage hexadécimal sont désormais en majuscules, tandis que d’autres sont en minuscules.

EIP-55 est assez simple à mettre en œuvre. Nous prenons le hachage Keccak-256 de l’adresse hexadécimale minuscule. Ce hachage agit comme une empreinte numérique de l’adresse, nous donnant une somme de contrôle pratique. Tout petit changement dans l’entrée (l’adresse) devrait entraîner un grand changement dans le hachage résultant (la somme de contrôle), nous permettant de détecter efficacement les erreurs. Le hachage de notre adresse est ensuite encodé dans la capitalisation de l’adresse elle-même. Décomposons-le, étape par étape :

  1. Hachez l’adresse en minuscules, sans le préfixe 0x :

Keccak256("001d3f1ef827552ae1114027bd3ecf1f086ba0f9") =
23a69c1653e4ebbb619b0b2cb8a9bad49892a8b9695d9a19d8f673ca991deae1
  1. Mettez en majuscule chaque caractère d’adresse alphabétique si le chiffre hexadécimal correspondant du hachage est supérieur ou égal à 0x8. C’est plus facile à montrer si nous alignons l’adresse et le hachage :

Adresse : 001d3f1ef827552ae1114027bd3ecf1f086ba0f9
Hachage : 23a69c1653e4ebbb619b0b2cb8a9bad49892a8b9...

Notre adresse contient un caractère alphabétique d en quatrième position. Le quatrième caractère du hachage est 6, qui est inférieur à 8. Donc, nous laissons le d minuscule. Le prochain caractère alphabétique de notre adresse est f, en sixième position. Le sixième caractère du hachage hexadécimal est c, qui est supérieur à 8. Par conséquent, nous capitalisons le F dans l’adresse, et ainsi de suite. Comme vous pouvez le voir, nous n’utilisons que les 20 premiers octets (40 caractères hexadécimaux) du hachage comme somme de contrôle, car nous n’avons que 20 octets (40 caractères hexadécimaux) dans l’adresse à capitaliser de manière appropriée.

Vérifiez vous-même l’adresse en majuscules mixtes résultante et voyez si vous pouvez dire quels caractères ont été en majuscules et à quels caractères ils correspondent dans le hachage de l’adresse :

Adresse : 001d3F1ef827552Ae1114027BD3ECF1f086bA0F9
Hachage : 23a69c1653e4ebbb619b0b2cb8a9bad49892a8b9...
Détection d’une erreur dans une adresse encodée EIP-55

Maintenant, regardons comment les adresses EIP-55 nous aideront à trouver une erreur. Supposons que nous ayons imprimé une adresse Ethereum, qui est codée EIP-55 :

0x001d3F1ef827552Ae1114027BD3ECF1f086bA0F9

Faisons maintenant une erreur fondamentale en lisant cette adresse. Le caractère avant le dernier est un F majuscule. Pour cet exemple, supposons que nous interprétions cela comme un E majuscule et que nous tapions l’adresse suivante (incorrecte) dans notre portefeuille :

0x001d3F1ef827552Ae1114027BD3ECF1f086bA0E9

Heureusement, notre portefeuille est conforme à la norme EIP-55 ! Il remarque les majuscules mixtes et tente de valider l’adresse. Il le convertit en minuscules et calcule le hachage de la somme de contrôle :

Keccak256("001d3f1ef827552ae1114027bd3ecf1f086ba0e9") =
5429b5d9460122fb4b11af9cb88b7bb76d8928862e0a57d46dd18dd8e08a6927

Comme vous pouvez le voir, même si l’adresse n’a changé que d’un caractère (en fait, un seul bit, car e et f sont séparés d’un bit), le hachage de l’adresse a radicalement changé. C’est la propriété des fonctions de hachage qui les rend si utiles pour les sommes de contrôle !

Maintenant, alignons les deux et vérifions la capitalisation :

001d3F1ef827552Ae1114027BD3ECF1f086bA0E9
5429b5d9460122fb4b11af9cb88b7bb76d892886...

C’est tout faux ! Plusieurs des caractères alphabétiques sont mal capitalisés. N’oubliez pas que la capitalisation est l’encodage de la somme de contrôle correcte.

La casse de l’adresse que nous avons saisie ne correspond pas à la somme de contrôle que nous venons de calculer, ce qui signifie que quelque chose a changé dans l’adresse et qu’une erreur a été introduite.

Conclusion

Dans ce chapitre, nous avons fourni un bref aperçu de la cryptographie à clé publique et nous nous sommes concentrés sur l’utilisation des clés publiques et privées dans Ethereum et l’utilisation d’outils cryptographiques, tels que les fonctions de hachage, dans la création et la vérification des adresses Ethereum. Nous avons également examiné les signatures numériques et comment elles peuvent démontrer la propriété d’une clé privée sans révéler cette clé privée. Dans [wallets_chapter], nous allons rassembler ces idées et voir comment les portefeuilles peuvent être utilisés pour gérer les collections de clés.