Dans cet article nous allons étudier ce que sont les clés étendues. Nous allons voir de quoi est-ce qu'elles sont constituées, quelles sont les différences entre xpub/zpub/xprv... et quels sont leurs rôles au sein du portefeuille HD.
Sommaire :
La dérivation de paires enfants.
Pour comprendre le rôle des clés étendues, il est important de comprendre le fonctionnement de la dérivation des paires de clés enfants.
Pour rappel, les portefeuilles déterministes hiérarchiques sont basés sur une graine (seed en anglais) qui représente l'information unique à la base du wallet. Elle permet de dériver l'ensemble des paires de clés de l'utilisateur, et donc d'accéder à l'ensemble des bitcoins du portefeuille. A partir de cette graine, on dérive une première profondeur constituée de la clé maîtresse et du code de chaîne maître grâce à HMAC-SHA512.
Le principe du portefeuille HD va ensuite être de dériver différentes profondeurs de clés afin de constituer des branches. Sur chaque profondeur, les paires sœurs se différencient grâce à un index. Chaque paire enfant est constituée d'une clé privée enfant, d'une clé publique enfant et d'un code de chaîne enfant.
Pour dériver une paire de clé enfant à partir d'une paire de clé parent, on va appliquer l'algorithme HMAC-SHA512. Cet algorithme dispose de 2 entrées, dans la première entrée on met notre clé parent (publique ou privée) concaténée avec l'index choisi pour l'enfant. Et dans la deuxième entrée de l'algorithme, on met le code de chaine parent.
L'index représente le numéro d'identification de la paire enfant. Il permet de différencier les paires de la même profondeur ayant la même paire parent.
Le code chaine permet d'introduire une source d'entropie au sein du processus de dérivation. Comme vous pouvez le voir sur le schéma précédent, sans le code de chaîne de la paire parent, il est impossible de dériver des paires enfants. Ainsi, il existe un code de chaîne unique associé à chaque paire de clés.
C'est sûrement la première fois que vous entendez parler de ces codes de chaînes, et c'est normal. Ils n'ont aucune utilité pratique pour l'utilisateur du portefeuille. Leur seule utilité est dans le processus de dérivation des paires de clés. Sans l'utilisation de ces codes, si l'on dérivait les paires enfants seulement à partir des paires parents, alors il suffirait de disposer d'une seule clé privée du portefeuille pour pouvoir déterminer l'ensemble de toutes les autres clés de ce wallet. Le code de chaîne agit donc comme une sécurité supplémentaire, permettant d'isoler la fuite d'une clé privée à cette seule clé.
Si l'on revient à notre schéma ci-dessus, on voit que la sortie de la fonction HMAC donne une information de 512 bits. Cette information sera ensuite séparée en deux. Les 256 bits de gauche seront parsés et additionnés à la clé privée parent modulo n (l'ordre de la courbe sachant le point d'origine), pour donner la clé privée enfant :
h = HMAC-SHA512 (Clé = Cpar, Message = 0X00 || kpar || i )
h = h1 || h2
kenf = parse256(h1) + kpar [mod n]
Et les 256 bits de droite donneront le code de chaine enfant :
Cenf = h2
La clé publique enfant dans ce schéma de dérivation sera déterminée à partir de la clé privée enfant par addition et doublement de points sur les courbes elliptiques.
Dans cet exemple nous avons dérivé une paire de clés enfants renforcées étant donné que l'on a utilisé la clé privée parent directement en entrée de la fonction HMAC. Les clés enfants normales (pas renforcées) sont calculées avec en entrée de la fonction HMAC la clé publique parent. Le reste du calcul est relativement similaire.
Si l'on souhaite dériver un clé publique enfant depuis une clé publique parent, le schéma sera le suivant :
Je ne vais pas plus détailler la dérivation hiérarchique de paires de clés dans cet article. Pour ceux qui souhaitent en apprendre plus voici ce que je vous conseille de lire :
Cet article sur la cryptographie sur les courbes elliptiques pour comprendre les mécanismes entre clé privée et clé publique : Les signatures numériques - extrait ebook Bitcoin Démocratisé 1.
La partie "Dérivation de paires de clés." dans cet article : Le portefeuille Bitcoin - extrait ebook Bitcoin Démocratisé 2.
Les clés étendues.
Comme nous avons pu le voir dans la partie précédente, la dérivation des paires de clés enfants nécessite de disposer de deux informations :
Une des deux clés parents.
Le code de chaîne associé.
Ainsi, simplement avec une clé parent, vous ne pourrez rien dériver. Vous devrez nécessairement disposer du code de chaîne associé à la paire parent. La clé étendue réunit ces deux informations en une seule chaîne de caractère.
Ainsi, avec une clé publique étendue (clé publique parent + code de chaîne parent) vous pourrez dériver des clés publique enfants. Et avec une clé privée étendue (clé privée parent + code de chaine parent) vous pourrez dériver des clés privées enfants et des clés publiques enfants.
Rappelez vous, je vous ai parlé rapidement des clés renforcées et des clés normales. Les clés renforcées sont celles dérivées avec en entrée 1 de la fonction HMAC la clé privée parent. Et les clés normales sont celles dérivées avec en entrée 1 de la fonction HMAC la clé publique parent.
Ainsi, une clé publique étendue ne pourra dériver que des clés publiques enfants normales. Et une clé privée étendue pourra dériver de tout : des clés enfants publiques et privées, renforcées ou normales :
Pour information : Sur les notations de chemins de dérivation, une paire issue d'une dérivation renforcée s'écrit avec une apostrophe ou avec un "h" à droite de son index. Aussi, on ne note pas directement son index réel, mais plutôt son index auquel on soustrait 2 147 483 648. Je vous explique tout cela en détail dans mon ebook gratuit : Tome 2 Bitcoin Démocratisé. ou sur ce post twitter : https://twitter.com/Loic_Pandul/status/1556672236945285121
En plus de cette charge utile que représentent la clé parent et le code chaine, la clé étendue dispose de quelques métadonnées qui permettent de faciliter son utilisation. Les voici :
La version : On ajoute les préfixes "xpub", "zpub", "xprv"... Ce préfixe permet de différencier les clés privée étendues des clé publiques étendues, et d'indiquer l'objectif de standard suivi (voir partie suivante).
La profondeur : Indique le nombre de dérivations par rapport à la clé maîtresse.
L'empreinte du parent : Représente les 4 premiers octets du HASH160 de la clé publique parent.
L'index : le numéro de la paire parmi ses sœurs dont est issue la clé étendue.
Et enfin, une checksum de toutes les métadonnées et de la charge utile de la clé étendue en utilisant HASH256.
Et voici dans l'ordre la taille de ces informations :
Version | 4 octets |
Profondeur | 1 octet |
Empreinte parent | 4 octets |
Index | 4 octets |
Code de chaîne | 32 octets |
Clé (publique ou privée) | 33 octets (pour la clé privée qui ne fait que 32 octets, on concatène à la base l'octet 0x00). |
Checksum | 4 octets |
Voici par exemple une xpub avec les couleurs du précédent tableau :
En Base 58: xpub6CTNzMUkzpurBWaT4HQoYzLP4uBbGJuWY358Rj7rauiw4rMHCyq3Rfy9w4kyJXJzeFfyrKLUar2rUCukSiDQFa7roTwzjiAhyQAdPLEjqHT
En HEX(base 16):
0488B21E036D5601AD80000000C605DF9FBD77FD6965BD02B77831EC5C78646AD3ACA14DC3984186F72633A89303772CCB99F4EF346078D167065404EED8A58787DED31BFA479244824DF50658051F067C3A
Les clés étendues sur un portefeuille HD standard sont utilisées à la profondeur du compte. Cette profondeur est la dernière à utiliser une dérivation renforcée. Les dérivations enfants à partir du compte se font de façon normale afin d'être en capacité de dériver des clés publiques enfants depuis la xpub, et donc d'être en capacité d'observer des fonds et de dériver des adresses à partir de cette information unique.
Enfin, d'un point de vue pratique pour l'utilisateur, les clés étendues sont utilisées pour dériver des paires enfants d'un compte. La clé privée étendue est très rarement utilisée, vous rencontrerez plutôt la clé publique étendue. Celle-ci vous permet de dériver des adresses de réception et d'observer les transactions d'un compte sans pour autant faire fuiter vos clés privées associées. Vous pouvez par exemple utiliser votre xpub pour créer un portefeuille "watch-only".
La clé publique étendue représente donc une information très sensible pour les comptes de votre portefeuille. De façon générale, il faut éviter de l'importer n'importe où. Et contrairement à ce que son nom indique, sauf cas spécifique, il ne faut surtout pas la communiquer.
Soyez conscient que si une personne a accès à une de vos xpub, elle pourra tracer tous vos paiements et voir les bitcoins que vous possédez sur le compte associé.
Les différents préfixes (xpub, zpub...).
Enfin, on peut se demander ce que veulent dire tous ces préfixes.
Pour commencer, ils agissent comme une partie lisible par l'Homme afin d'identifier d'un coup d'œil que l'on à faire à une clé étendue.
Ensuite, ils permettent de différencier facilement les clés privées étendues des clés publiques étendues. Le "pub" désigne ainsi une clé publique étendue, et le "prv" désigne une clé privée étendue.
La première lettre du préfixe permet de désigner l'objectif de dérivation du portefeuille. Ainsi :
"x" est utilisé comme préfixe pour un objectif BIP44 (Legacy) ou BIP86 (Segwit V1). L'équivalent testnet sera "t".
"y" est utilisé comme préfixe pour un objectif BIP49 (Nested SegWit). L'équivalent testnet sera "u".
"z" est utilisé comme préfixe pour un objectif BIP84 (Segwit V0). L'équivalent testnet sera "v".
Préfixe base 58 | Préfixe base 16 | Réseau | Objectif | Scripts associés | Dérivation | Type de clé |
xpub | 0488b21e | Mainnet | Legacy et SegWit V1 | P2PK / P2PKH / P2TR | m/44'/0' m/86'/0' | publique |
xprv | 0488ade4 | Mainnet | Legacy et SegWit V1 | P2PK / P2PKH / P2TR | m/44'/0' m/86'/0' | privée |
tpub | 043587cf | Testnet | Legacy et SegWit V1 | P2PK / P2PKH / P2TR | m/44'/1' m/86'/1' | publique |
tprv | 04358394 | Testnet | Legacy et SegWit V1 | P2PK / P2PKH / P2TR | m/44'/1' m/86'/1' | privée |
ypub | 049d7cb2 | Mainnet | Nested SegWit | P2WPKH in P2SH | m/49'/0' | publique |
yprv | 049d7878 | Mainnet | Nested SegWit | P2WPKH in P2SH | m/49'/0' | privée |
upub | 049d7cb2 | Testnet | Nested SegWit | P2WPKH in P2SH | m/49'/1' | publique |
uprv | 044a4e28 | Testnet | Nested SegWit | P2WPKH in P2SH | m/49'/1' | privée |
zpub | 04b24746 | Mainnet | SegWit V0 | P2WPKH | m/84'/0' | publique |
zprv | 04b2430c | Mainnet | SegWit V0 | P2WPKH | m/84'/0' | privée |
vpub | 045f1cf6 | Testnet | SegWit V0 | P2WPKH | m/84'/1' | publique |
vprv | 045f18bc | Testnet | SegWit V0 | P2WPKH | m/84'/1' | privée |
Il peut arriver que vous ayez besoin de modifier le préfixe d'une clé étendue, par exemple si votre logiciel de gestion de portefeuille vous donne une xpub alors que le chemin de dérivation est en m/84'.
Il suffit alors simplement de changer le préfixe. Attention, les modifications sur une clé étendue se font toujours en format hexadécimal (base 16).
Par exemple :
# clé publique étendue xpub en base 58 :
xpub6CTNzMUkzpurBWaT4HQoYzLP4uBbGJuWY358Rj7rauiw4rMHCyq3Rfy9w4kyJXJzeFfyrKLUar2rUCukSiDQFa7roTwzjiAhyQAdPLEjqHT
# conversion clé publique étendue xpub en base 16, préfixe en vert :
0488B21E036D5601AD80000000C605DF9FBD77FD6965BD02B77831EC5C78646AD3ACA14DC3984186F72633A89303772CCB99F4EF346078D167065404EED8A58787DED31BFA479244824DF50658051F067C3A
# changement de préfixe pour zpub :
04b24746036D5601AD80000000C605DF9FBD77FD6965BD02B77831EC5C78646AD3ACA14DC3984186F72633A89303772CCB99F4EF346078D167065404EED8A58787DED31BFA479244824DF50658051F067C3A
# conversion de la clé étendue en format base 58 :
zpub6r7ubgpbJBzot6xgizz3yAXPQqUV9YtWNG7ZzWudLvUhB3yjiJAAfoHRyUg9JLcqTXubMGXbWAjxEn8st73Rr3V4Y9LquXogWrHvAV1wWBs
Les clés étendues Bitcoin n'ont dorénavant plus de secret pour vous.
留言