top of page
  • Loïc Morel

BIP47, le vilain petit canard.


« Il est trop grand, » disaient-ils tous, et le coq d’Inde qui était venu au monde avec des éperons et qui se croyait empereur, se gonfla comme un bâtiment toutes voiles dehors, et marcha droit sur lui en grande fureur et rouge jusqu’aux yeux. Le pauvre canet ne savait s’il devait s’arrêter ou marcher : il eut bien du chagrin d’être bafoué par tous les canards de la cour.


BIP47, le vilain petit canard illustration

 

Le 17 mars 2022, je publiais cet article : Qu'est-ce que PayNym et BIP47 ?


Avec ce papier, j'ai essayé d'aborder en détail le fonctionnement des codes de paiements réutilisables. En relisant cet article aujourd'hui, je m'aperçois que des erreurs techniques ou des imprécisions y sont présentes. Puisque je souhaite conserver l'article original, je vous propose dans le présent post une réécriture de cet article sur BIP47, PayNym et les codes de paiement réutilisables.


Même si mon niveau de connaissance en cryptographie reste modeste, je pense avoir progressé dans ce domaine depuis la publication du dernier article sur BIP47. Cette nouvelle version sera donc plus juste et beaucoup plus détaillée.

En plus de toute la partie technique et théorique, vous trouverez dans cette seconde version des tutoriels complets sous forme de vidéos.


Bonne lecture.


If you wish to read this article in English, here is the translation of The Sovereign Bitcoiner : https://sovrnbitcoiner.com/bip47-ugly-duckling/

 

Un des fléaux les plus importants sur le protocole Bitcoin est la réutilisation d'adresse. La transparence et la distribution du réseau rend cette pratique dangereuse pour la confidentialité de l'utilisateur. Pour éviter les problèmes liés à cela, il est conseillé d'utiliser une nouvelle adresse de réception vierge pour tout nouveau paiement entrant vers un portefeuille, ce qui peut être compliqué à réaliser dans certains cas.


Ce compromis est vieux comme le White Paper. Satoshi nous mettait déjà en garde contre ce risque dans son ouvrage publié fin 2008 :


"As an additional firewall, a new key pair should be used for each transaction to keep them from being linked to a common owner."

Traduction française : "En guise de pare-feu additionnel, une nouvelle paire de clés pourrait être utilisée pour chaque transaction afin de les garder non liées à un propriétaire commun."

De nombreuses solutions existent pour recevoir de multiples paiements, sans pour autant produire de réutilisation d'adresse. Chacune d'elles dispose de ses compromis et de ses inconvénients. Parmi toutes ces solutions, il y a le BIP47, une proposition développée par Justus Ranvier et publiée en 2015 permettant de générer des codes de paiements réutilisables. Leur objectif est de pouvoir réaliser plusieurs transactions vers une même personne, sans pour autant réutiliser d'adresse.


Au départ, cette proposition a reçu un accueil méprisant de la part d'une partie de la communauté, et elle n'a jamais été ajoutée à Bitcoin Core. Certains logiciels ont tout de même choisi de l'implémenter de leur côté. Ainsi, Samourai Wallet a développé sa propre implémentation du BIP47 : PayNym. Aujourd'hui, cette implémentation est évidemment disponible sur Samourai Wallet pour les smartphones, mais également sur Sparrow Wallet pour les PC.


Avec le temps, Samourai a programmé de nouvelles fonctionnalités directement liées à PayNym. À présent, il existe tout un écosystème d'outils permettant d'optimiser la confidentialité de l'utilisateur fondés sur PayNym et sur BIP47.


Dans cet article, vous découvrirez le principe du BIP47 et de PayNym, les mécanismes de ces protocoles et les applications pratiques qui en découlent. Je vais uniquement aborder la première version du BIP47, celle actuellement utilisée pour PayNym, mais les versions 2, 3 et 4 fonctionnent pratiquement de la même façon.


La seule différence majeure se trouve au niveau de la transaction de notification. La version 1 utilise une adresse simple avec l'OP_RETURN pour la notification, la version 2 utilise un script multisig (bloom-multisig) avec l'OP_RETURN et la version 3 et 4 utilisent simplement un script multisig (cfilter-multisig). Les mécanismes évoqués dans cet article, et notamment les méthodes cryptographiques étudiées, sont donc applicables aux quatre versions. À date, l'implémentation PayNym sur Samourai Wallet et Sparrow utilise la première version du BIP47.



Sommaire :


1- Le problème de la réutilisation d'adresse.

2- Principes du BIP47 et de PayNym.

3- Tutoriels : utilisation de PayNym.

4- Les rouages du BIP47.

5- Utilisations dérivées de PayNym.

6- Mon avis personnel sur le BIP47.





Le problème de la réutilisation d'adresse.

Une adresse de réception est utilisée pour recevoir des bitcoins. Elle est générée à partir d'une clé publique en la hachant et en lui appliquant un format spécifique. Ainsi, elle permet de créer une nouvelle condition de dépense sur une pièce afin d'en modifier le propriétaire.


Pour en savoir plus sur la génération d'une adresse de réception, je vous conseille de lire la dernière partie de cet article : Le portefeuille Bitcoin - extrait ebook Bitcoin Démocratisé 2.

Par ailleurs, vous avez sûrement déjà entendu de la part d'un bitcoiner avisé que les adresses de réception sont à usage unique, et qu'il faut de ce fait en générer une nouvelle pour tout nouveau paiement entrant vers votre portefeuille. D'accord, mais pourquoi ?


Fondamentalement, la réutilisation d'adresse ne met pas en danger directement vos fonds. L'utilisation de la cryptographie sur les courbes elliptiques permet de prouver au réseau que vous êtes bien en possession d'une clé privée sans pour autant révéler cette clé. Vous pouvez donc bloquer plusieurs UTXO différents sur une même adresse et les dépenser à différents moments. Si vous ne révélez pas la clé privée associée à cette adresse, personne ne pourra accéder à vos fonds. Le problème de la réutilisation d'adresse est plutôt de l'ordre de la vie privée.


Comme évoqué en introduction, la transparence et la distribution du réseau Bitcoin font que n'importe quel utilisateur, pourvu qu'il ait accès à un nœud, est en capacité d'observer les transactions du système de paiement. De ce fait, il peut voir les différents soldes des adresses. Satoshi Nakamoto a alors évoqué la possibilité de générer de nouvelles paires de clés, et ainsi de nouvelles adresses, pour tout nouveau paiement entrant vers un portefeuille. L'objectif serait d'avoir un pare-feu supplémentaire en cas d'association entre l'identité de l'utilisateur et une de ses paires de clés.


Aujourd'hui, avec la présence de sociétés d'analyse de chaine et le développement du KYC, l'utilisation d'adresses vierges n'est plus un pare-feu supplémentaire, mais une obligation pour quiconque se soucie un minimum de sa vie privée.


La recherche de confidentialité n'est pas un confort ni un fantasme de bitcoiner maximaliste. C'est un paramètre spécifique qui touche directement à votre sécurité personnelle et à la sécurisation de vos fonds. Pour vous le faire comprendre, voici un exemple très concret :


- Bob achète du bitcoin en DCA (Dollars Cost Average), c'est-à-dire qu'il acquière une petite somme de bitcoins à intervalle régulier afin de lisser son prix d'entrée. Bob envoie systématiquement les fonds achetés sur la même adresse de réception. Il achète 0,01 bitcoin toutes les semaines et les envoie vers cette même adresse. Au bout de deux ans, Bob a accumulé un bitcoin entier sur cette adresse.

- Le boulanger au coin de sa rue accepte les paiements en bitcoins. Tout heureux de pouvoir dépenser des bitcoins, Bob s'en va acheter sa baguette en sats. Pour payer, il utilise les fonds bloqués avec son adresse. Son boulanger sait dorénavant qu'il possède un bitcoin. Cette somme importante pourrait faire des envieux, et Bob risque potentiellement de subir une attaque physique par la suite.


La réutilisation d'adresse permet donc à un observateur de faire un lien indéniable entre vos différents UTXO, et donc parfois, entre votre identité et tout votre portefeuille.


C'est pour cette raison que la majorité des logiciels de portefeuille Bitcoin vous génèrent automatiquement une nouvelle adresse de réception lorsque vous cliquez sur le bouton « Recevoir ». Pour l'utilisateur régulier, prendre l'habitude d'utiliser des adresses vierges n'est de ce fait pas d'un grand inconvénient. En revanche, pour un commerce en ligne, un exchange ou une campagne de donation, cette contrainte peut rapidement devenir ingérable.


Il existe de nombreuses solutions pour ces organisations. Chacune d'entre elles dispose de ses avantages et de ses inconvénients, mais à ce jour, et comme nous le verrons plus loin, le BIP47 se différencie réellement des autres.


Ce problème de la réutilisation d'adresse est loin d'être négligeable sur Bitcoin. Comme vous pouvez le voir sur le graphique ci-dessous extrait du site oxt.me, le taux global de réutilisation d'adresse par les utilisateurs de Bitcoin est actuellement de 52% :

Graphique OXT.me évolution du taux global de réutilisation d'adresses sur le réseau Bitcoin.
Crédit : https://oxt.me/charts

La majorité de ces réutilisations provient des exchanges qui, pour des raisons d'efficacité et de facilité, réutilisent une même adresse de nombreuses fois. À ce jour, le BIP47 serait la meilleure solution pour endiguer ce phénomène chez les exchanges. Cela permettrait d'engager à la baisse ce taux global de réutilisation d'adresse, sans pour autant occasionner trop de frictions pour ces entités.


Cette mesure globale sur l'ensemble du réseau est une donnée particulièrement cohérente dans ce cas-là. En effet, la réutilisation d'adresse n'est pas uniquement un problème pour la personne qui réalise ce type de pratique, mais également pour toute personne qui réalise des transactions avec celle-ci. La perte de confidentialité sur Bitcoin agit comme virus, et se propage d'utilisateurs en utilisateurs. Étudier une mesure globale sur toutes les transactions du réseau nous permet de prendre conscience de l'ampleur de ce phénomène.





Principes du BIP47 et de PayNym.


BIP47 vise à proposer une façon simple de recevoir de nombreux paiements tout en ne faisant pas de réutilisation d'adresse. Son fonctionnement est fondé sur l'utilisation d'un code de paiement réutilisable.


Ainsi, plusieurs émetteurs pourront envoyer plusieurs paiements vers un unique code de paiement réutilisable d'un autre utilisateur, sans que le destinataire ait besoin de transmettre une nouvelle adresse vierge pour chaque nouvelle transaction.


Un utilisateur peut alors communiquer librement son code de paiement (sur les réseaux sociaux, sur son site web...) sans risque de perte de confidentialité, contrairement à une adresse de réception classique ou à une clé publique.


Pour réaliser un échange, les deux utilisateurs devront disposer d'un portefeuille Bitcoin avec une implémentation du BIP47, comme PayNym sur Samourai Wallet ou Sparrow Wallet. L'association des codes de paiements des deux utilisateurs va permettre d'établir un canal secret entre eux. Pour instaurer proprement ce canal, l'émetteur va devoir réaliser une transaction sur la chaîne Bitcoin : la transaction de notification (je vous en parle un peu plus loin).


L'association des codes de paiements des deux utilisateurs génère des secrets partagés permettant eux-mêmes de générer un grand nombre d'adresses de réception Bitcoin uniques (2^32 exactement). Ainsi, en réalité, le paiement avec BIP47 n'est pas envoyé à destination du code de paiement, mais bien à destination d'adresses tout à fait classiques, elle-mêmes dérivées depuis les codes de paiements des protagonistes.


Le code de paiement agit donc comme un identifiant virtuel, dérivé depuis la graine du portefeuille. Dans la structure de dérivation du portefeuille HD, le code de paiement se trouve en profondeur 3, au niveau des comptes de portefeuille.


Structure du portefeuille HD et placement du code de paiement réutilisable BIP47

Son objectif de dérivation se note 47' (0x8000002F) en référence au BIP47. Un chemin de dérivation d'un code de paiement réutilisable sera par exemple :

m/47'/0'/0'/


Afin que vous puissiez imaginer à quoi ressemble un code de paiement, voici le mien :

PM8TJSBiQmNQDwTogMAbyqJe2PE2kQXjtgh88MRTxsrnHC8zpEtJ8j7Aj628oUFk8X6P5rJ7P5qDudE4Hwq9JXSRzGcZJbdJAjM9oVQ1UKU5j2nr7VR5 

Celui-ci peut également être encodé en QRcode pour en faciliter la communication :

Code de paiement réutilisable BIP47 de PayNym en QR Code


Quant aux PayNym Bots, ces robots que l'on aperçoit sur Twitter, ce sont simplement des représentations visuelles de votre code de paiement, réalisées par Samouraï Wallet. Ils sont créés grâce à une fonction de hachage, ce qui les rend presque uniques. Voici le mien avec son identifiant :

+throbbingpond8B1
PayNym Bot

Ces Bots n'ont aucune réelle utilité technique. Au lieu de cela, ils permettent de faciliter les interactions entre les utilisateurs en créant une identité visuelle virtuelle.



Pour l'utilisateur, le processus d'un paiement BIP47 avec l'implémentation PayNym est extrêmement simple. Imaginons qu'Alice souhaite envoyer des paiements à Bob :

  1. Bob diffuse son QR code, ou directement son code de paiement réutilisable. Il peut le placer sur son site web, sur ses différents réseaux sociaux publics ou encore l'envoyer à Alice grâce à un autre moyen de communication.

  2. Alice ouvre son logiciel Samourai ou Sparrow, et scanne, ou colle, le code de paiement de Bob.

  3. Alice relie son PayNym avec celui de Bob ("Follow" en anglais). Cette opération se fait en dehors de la blockchain et demeure complètement gratuite.

  4. Alice connecte son PayNym avec celui de Bob ("Connect" en anglais). Cette opération se fait "on chain". Alice doit payer les frais de minage de la transaction ainsi qu'un frais fixe de 15 000 sats pour le service sur Samourai. Les frais de service sont offerts sur Sparrow. Cette étape, c'est ce que l'on appelle la transaction de notification.

  5. Une fois la transaction de notification confirmée, Alice peut créer une transaction de paiement BIP47 à destination de Bob. Son portefeuille va automatiquement générer une nouvelle adresse de réception vierge pour laquelle seul Bob dispose de la clé privée.

Réaliser la transaction de notification, c'est-à-dire connecter son PayNym, est une étape préalable obligatoire pour réaliser des paiements BIP47. En revanche, une fois que celle-ci est effectuée, l'envoyeur pourra réaliser de multiples paiements vers le destinataire (2^32 exactement), sans pour autant avoir besoin de réaliser de nouveau une transaction de notification.


Vous avez pu voir qu'il existe deux opérations différentes qui permettent de lier des PayNym entre eux : relier et connecter. L'opération de connexion ("connecter") correspond à la transaction de notification du BIP47 qui est simplement une transaction Bitcoin avec certaines informations transmises grâce à une sortie OP_RETURN. Ainsi, elle aide à établir une communication chiffrée entre les deux utilisateurs afin de produire les secrets partagés nécessaires pour générer de nouvelles adresses de réception vierges.


En revanche, l'opération de liaison ("follow" ou "relier") permet d'établir un lien sur Soroban, un protocole de communication chiffré fondé sur Tor, spécialement développé par les équipes de Samourai.


Pour résumer :

  • Le fait de relier deux PayNym ("follow") est totalement gratuit. Cela aide à établir des communications "off chain" chiffrées, notamment afin d'utiliser les outils de transactions collaboratives de Samourai (Stowaway ou StonewallX2). Cette opération est spécifique à PayNym. Elle n'est pas décrite dans le BIP47.

  • Le fait de connecter deux PayNym est payant. Cela implique de réaliser la transaction de notification dans le but de lancer la connexion. Son coût est constitué d'éventuels frais de service, des frais de minage de la transaction et de 546 sats envoyés sur l'adresse de notification du destinataire pour le prévenir de l'ouverture du tunnel. Cette opération est liée au BIP47. Une fois effectuée, l'envoyeur peut réaliser plusieurs paiements BIP47 vers le destinataire.

Afin de pouvoir connecter deux PayNym, ceux-ci doivent déjà être déjà reliés.





Tutoriels : utilisation de PayNym.


Maintenant que nous avons vu la théorie, étudions ensemble la pratique. L'idée des tutoriels ci-dessous est de relier mon PayNym sur mon portefeuille Sparrow avec mon PayNym sur mon portefeuille Samourai. Le premier tutoriel vous montre comment faire une transaction grâce au code de paiement réutilisable depuis Samourai vers Sparrow, et le second tutoriel décrit le même mécanisme depuis Sparrow vers Samourai.


J'ai effectué ces tutoriels sur le Testnet. Ce ne sont pas de vrais bitcoins.



Construire une transaction BIP47 avec Samourai Wallet.


Pour commencer, vous allez évidemment avoir besoin de l'application Samourai Wallet. Vous pouvez directement la télécharger depuis le Google Play Store, ou bien avec le fichier APK disponible sur le site officiel de Samourai.


Une fois le portefeuille initialisé, si vous ne l'avez pas déjà fait, demandez votre PayNym en cliquant sur le plus (+) en bas à droite, puis sur "PayNym".


La première étape pour faire un paiement BIP47 va être de récupérer le code de paiement réutilisable de notre destinataire. Ensuite, on va pouvoir se relier avec celui-ci, et par la suite se connecter :




Une fois la transaction de notification confirmée, je peux envoyer plusieurs paiements à mon destinataire. Chaque transaction se fera automatiquement avec une nouvelle adresse vierge pour laquelle le destinataire possède les clés. Ce dernier n'a aucune action à effectuer, tout est calculé de mon côté.


Voici comment réaliser une transaction BIP47 sur Samourai Wallet :




Construire une transaction BIP47 avec Sparrow Wallet.


De la même manière que pour Samourai, vous devez évidemment disposer du logiciel Sparrow. Celui-ci est disponible sur ordinateur. Vous pouvez le télécharger depuis leur site web officiel.


Pensez à bien vérifier la signature du développeur et l'intégrité du logiciel téléchargé avant de l'installer sur votre machine.


Créez-vous un portefeuille et demandez votre PayNym en cliquant sur "Show PayNym" depuis le menu "Tool" dans la barre supérieure :


Ouverture du menu PayNym sur Sparrow


Ensuite, vous devrez lier et connecter votre PayNym avec celui de votre destinataire. Pour ce faire, entrez son code de paiement réutilisable dans la fenêtre "Find Contact", suivez-le, puis réalisez la transaction de notification en cliquant sur "Link Contact" :


Recherche et connexion avec un PayNym sur Sparrow


Une fois la transaction de notification confirmée, on peut envoyer des paiements vers le code de paiement réutilisable. Voici la marche à suivre :




Maintenant que nous avons pu étudier l'aspect pratique de l'implémentation PayNym du BIP47, voyons ensemble comment tous ces mécanismes fonctionnent, et quelles sont les méthodes cryptographiques utilisées.





Les rouages du BIP47.


Pour étudier les mécanismes du BIP47, il est essentiel de comprendre la structure du portefeuille déterministe hiérarchique (HD), les mécanismes de dérivation de paires de clés filles, ainsi que les principes de la cryptographie sur les courbes elliptiques. Fort heureusement, vous pouvez retrouver sur mon blog toutes ces informations nécessaires à la compréhension de cette partie :



Le code de paiement réutilisable.


Comme expliqué dans la deuxième partie de ce papier, le code de paiement réutilisable se trouve en profondeur trois du portefeuille HD. Il est finalement quelque peu assimilable à une xpub, autant dans son placement et dans sa structure que dans son rôle.


Voici les différentes parties qui composent un code de paiement de 80 octets :

  • L'octet 0 : La version. Si l'on utilise la première version du BIP47 alors cet octet sera égal à 0x01.

  • L'octet 1 : Le champ de bits. Cet espace est réservé pour donner des indications supplémentaires en cas d'utilisation spécifique. Si l'on utilise simplement PayNym, cet octet sera égal à 0x00.

  • L'octet 2 : La parité de y. Cet octet indique 0x02 ou 0x03 en fonction de la parité (nombre pair ou nombre impair) de la valeur de l'ordonnée de notre clé publique. Pour avoir plus d'informations sur cette pratique, veuillez lire l'étape 1 de la partie "dérivation d'une adresse" de cet article.

  • De l'octet 3 à l'octet 34 : La valeur de x. Ces octets indiquent l'abscisse de notre clé publique. La concaténation de x et de la parité de y nous donne notre clé publique compressée.

  • De l'octet 35 à l'octet 66 : Le code de chaine. Cet espace est réservé pour le code de chaine associé à la clé publique susmentionnée.

  • De l'octet 67 à l'octet 79 : Le rembourrage. Cet espace est réservé pour de possibles futures évolutions. Pour la version 1 on y met simplement des zéros afin de remplir jusqu'à 80 octets, soit la taille des données d'une sortie OP_RETURN.


Voici la représentation hexadécimale de mon code de paiement réutilisable, présenté dans la partie précédente, avec les couleurs correspondant aux octets présentés ci-dessus :

0x010002a0716529bae6b36c5c9aa518a52f9c828b46ad8d907747f0d09dcd4d9a39e97c3c5f37c470c390d842f364086362f6122f412e2b0c7e7fc6e32287e364a7a36a00000000000000000000000000

Ensuite, il faut également ajouter l'octet du préfixe "P" permettant d'identifier d'un coup d'œil que l'on a affaire à un code de paiement. Cet octet est 0x47.

0x47010002a0716529bae6b36c5c9aa518a52f9c828b46ad8d907747f0d09dcd4d9a39e97c3c5f37c470c390d842f364086362f6122f412e2b0c7e7fc6e32287e364a7a36a00000000000000000000000000

Enfin, on calcule la somme de contrôle de ce code de paiement avec HASH256, c'est-à-dire un double hachage avec la fonction SHA256. On récupère les quatre premiers octets de ce condensat et on les concatène à la fin (en rose).

0x47010002a0716529bae6b36c5c9aa518a52f9c828b46ad8d907747f0d09dcd4d9a39e97c3c5f37c470c390d842f364086362f6122f412e2b0c7e7fc6e32287e364a7a36a00000000000000000000000000567080c4

Le code de paiement est prêt, il ne reste plus qu'à le convertir en Base 58 :

PM8TJSBiQmNQDwTogMAbyqJe2PE2kQXjtgh88MRTxsrnHC8zpEtJ8j7Aj628oUFk8X6P5rJ7P5qDudE4Hwq9JXSRzGcZJbdJAjM9oVQ1UKU5j2nr7VR5 

Comme vous pouvez le remarquer, cette construction ressemble fortement à la structure d'une clé publique étendue de type "xpub".

Durant ce processus permettant de déboucher sur notre code de paiement, nous avons utilisé une clé publique compressée et un code de chaîne. Ces deux éléments sont le fruit d'une dérivation déterministe et hiérarchique, depuis la graine du portefeuille, en suivant le chemin de dérivation suivant : m/47'/0'/0'/.


Concrètement, pour obtenir la clé publique et le code de chaîne du code de paiement réutilisable, on va calculer la clé privée maîtresse depuis la graine, puis dériver une paire fille avec l'index 47 + 2^31 (dérivation renforcée). Ensuite, on dérive deux fois des paires filles avec l'index 2^31 (dérivation renforcée).


Si vous souhaitez en savoir plus sur la dérivation de paires de clés filles au sein d'un portefeuille déterministe hiérarchique Bitcoin, je vous conseille de lire cet article.



La méthode cryptographique : l'échange de clés Diffie-Hellman établi sur les courbes elliptiques (ECDH).


La méthode cryptographique utilisée à la base du BIP47 est ECDH (Elliptic-Curve Diffie-Hellman = Échange de clés Diffie-Hellman établi sur les courbes elliptiques). Ce protocole est une variante de l'échange de clés Diffie-Hellman classique.


Diffie-Hellman, dans sa première version, est un protocole d'accord de clés présenté en 1976 qui permet à deux personnes, à partir de deux paires (clés publiques et clés privées), de déterminer un secret partagé en échangeant sur un canal de communication non sécurisé.


Schéma génération d'un secret partagé avec Diffie-Hellman

Ce secret partagé (la clé rouge) peut ensuite être utilisé pour réaliser d'autres tâches. Typiquement, on peut utiliser ce secret partagé pour chiffrer et déchiffrer une communication sur un réseau non sécurisé :

Communication chiffrée grâce au secret partagé Diffie-Hellman

Pour réussir cet échange, Diffie-Hellman utilise l'arithmétique modulaire afin de calculer le secret commun. Voici son fonctionnement vulgarisé :

  • Alice et Bob déterminent une couleur commune, ici le jaune. Cette couleur est connue de tous. C'est une donnée publique.

  • Alice choisi une couleur secrète, ici le rouge. Elle mélange les deux couleurs ce qui lui donne de l'orange.

  • Bob choisi une couleur secrète, ici le bleu canard. Il mélange les deux couleurs ce qui lui donne du bleu ciel.

  • Alice et Bob peuvent s'échanger les couleurs obtenues : l'orange et le bleu ciel. Cet échange peut se faire sur un réseau non sécurisé et observé par des attaquants.

  • Alice mélange la couleur bleu ciel reçue de Bob avec sa couleur secrète (rouge). Elle obtient du marron.

  • Bob mélange la couleur orange reçue d'Alice avec sa couleur secrète (bleu canard). Il obtient cette même couleur marron.


Schéma de vulgarisation du fonctionnement de Diffie-Hellman
Crédit : Idée originale : A.J. Han VinckVersion vectorielle : FlugaalTraduction : Dereckson, Public domain, via Wikimedia Commons. https://commons.wikimedia.org/wiki/File:Diffie-Hellman_Key_Exchange_(fr).svg

Dans cette vulgarisation, la couleur marron représente le secret partagé entre Alice et Bob. Il faut imaginer qu'en réalité, il est impossible pour l'attaquant de séparer les couleurs orange et bleu ciel, afin de retrouver les couleurs secrètes d'Alice ou de Bob.


Maintenant, étudions son fonctionnement réel. À première vue, Diffie-Hellman parait complexe à appréhender. En réalité, le principe de fonctionnement est presque enfantin. Avant de vous détailler ses mécanismes, je vous rappelle rapidement deux notions mathématiques dont nous allons avoir besoin (et qui accessoirement, sont également utilisées dans de nombreuses autres méthodes cryptographiques).

  1. Un nombre premier est un entier naturel qui n'admet que deux diviseurs : 1 et lui-même. Par exemple, le chiffre 7 est premier, car on ne peut le diviser que par 1 et 7 (lui-même). En revanche, le chiffre 8 n'est pas premier, car on peut le diviser par 1, 2, 4 et 8. Il n'admet donc pas uniquement deux diviseurs, mais bien quatre diviseurs entiers et positifs.

  2. Le "modulo" (noté "mod" ou "%") est une opération mathématique qui permet entre deux nombres entiers de renvoyer le reste de la division euclidienne du premier par le second nombre. Par exemple, 16 mod 5 est égal à 1.


L'échange de clés Diffie-Hellman entre Alice et Bob fonctionne de telle façon :

  • Alice et Bob déterminent deux nombres communs : p et g. p est un nombre premier. Au plus ce nombre p est grand, au plus Diffie-Hellman sera sécurisé. g est une racine primitive de p. Ces deux nombres peuvent être communiqués en clairs sur un réseau non sécurisé, ce sont les équivalents de la couleur jaune dans la vulgarisation ci-dessus. Il faut simplement qu'Alice et Bob aient exactement les mêmes valeurs p et g.

  • Une fois les paramètres choisis, Alice et Bob déterminent chacun de leur côté un nombre aléatoire secret. Le nombre aléatoire obtenu par Alice est nommé a (équivalent de la couleur rouge) et le nombre aléatoire obtenu par Bob est nommé b (équivalent de la couleur bleu canard). Ces deux nombres doivent rester secrets.

  • Au lieu d'échanger ces nombres a et b, chaque partie va calculer A (majuscule) et B (majuscule) tels que :

# A est égal à g puissance a modulo p :
A = g^a % p 

# B est égal g puissance b modulo p :
B = g^b % p
  • Ces nombres A (équivalent de la couleur orange) et B (équivalent de la couleur bleu ciel) vont être échangés entre les deux parties. L'échange peut se faire en clair sur un réseau non sécurisé.

  • Alice, qui est maintenant en connaissance de B, va calculer la valeur de z tel que :

 # z est égal à B puissance a modulo p :
 z = B^a % p
  • Pour rappel, B = g^b % p. On a donc :

z = B^a % p
z = (g^b)^a % p

# Conformément aux règles de calculs sur les puissances : 
(x^n)^m = x^nm

# On a donc :
z = g^ba % p
  • Bob, qui est maintenant en connaissance de A, va également calculer la valeur de z tel que :

 # z est égal à A puissance b modulo p :
 z = A^b % p
 
 # On a donc :
 z = (g^a)^b % p
 z = g^ab % p
 z = g^ba % p

Grâce notamment à la distributivité de l'opérateur modulo, Alice et Bob trouvent exactement la même valeur z. Ce nombre représente leur secret commun, c'est-à-dire l'équivalent de la couleur marron dans la vulgarisation précédente. Ils peuvent utiliser ce secret commun pour chiffrer une communication entre eux-deux sur un réseau non sécurisé.


Schéma fonctionnement technique Diffie-Hellman


Un attaquant en possession de p, g, A et B sera dans l'impossibilité de calculer a, b ou z. Faire cette opération reviendrait à inverser l'exponentiation. Ce calcul est impossible à réaliser autrement qu'en essayant toutes les possibilités une par une puisque l'on travaille sur un corps fini. Cela reviendrait à calculer le logarithme discret, c'est-à-dire la réciproque de l'exponentielle dans un groupe cyclique fini.


Ainsi, du moment que l'on choisit un a, un b et un p assez grands, Diffie-Hellman est sécurisé. Typiquement, avec des paramètres de 2 048 bits (nombre de 600 chiffres en décimal), tester toutes les possibilités pour a et b serait chimérique. À ce jour, avec des nombres de cette taille, l'algorithme est considéré comme sûr.


C'est justement à ce niveau que réside le principal inconvénient du protocole Diffie-Hellman. Pour être sécurisé, l'algorithme doit utiliser des nombres de grande taille. En conséquence, on préfère aujourd'hui utiliser l'algorithme ECDH, une variante de Diffie-Hellman utilisant une courbe algébrique, et en l'occurrence, une courbe elliptique. Cela va nous permettre de travailler sur des nombres beaucoup plus petits tout en conservant une sécurité équivalente, et donc de réduire les ressources nécessaires pour le calcul et le stockage.


Le principe général de l'algorithme reste le même. Mais, au lieu d'utiliser un nombre aléatoire a et un nombre A calculé depuis a avec l'exponentiation modulaire, on va utiliser une paire de clés établies sur une courbe elliptique. Au lieu de s'appuyer sur la distributivité de l'opérateur modulo, nous allons utiliser ici la loi de groupe sur les courbes elliptiques, et plus précisément l'associativité de cette loi.


Si vous ne disposez d'aucune notion sur le fonctionnement des clés privées et des clés publiques sur une courbe elliptique, je vous explique les bases de cette méthode dans les six premières parties de cet article.

Pour résumer grossièrement, une clé privée est un nombre aléatoire compris entre 1 et n-1 (n étant l'ordre de la courbe), et une clé publique est un point unique sur la courbe déterminé grâce à la clé privée par addition et doublement de points depuis le point générateur tel que :

K =G

K est la clé publique, k est la clé privée et G est le point générateur.


Une des propriétés de cette paire de clés est qu'il est très facile de déterminer K en ayant connaissance de k et de G, mais il est aujourd'hui impossible de déterminer k en ayant connaissance de K et de G. C'est une fonction à sens unique.


Autrement dit, on peut facilement calculer la clé publique en ayant connaissance de la clé privée, mais il est impossible de calculer la clé privée en ayant connaissance de la clé publique. Cette sécurité est encore une fois fondée sur l'impossibilité de calcul du logarithme discret.


On va donc se servir de cette propriété pour adapter notre algorithme Diffie-Hellman. Ainsi, le principe de fonctionnement d'ECDH est le suivant :

  • Alice et Bob conviennent ensemble d'une courbe elliptique cryptographiquement sûre et de ses paramètres. Ces informations sont publiques.

  • Alice génère un nombre aléatoire ka qui sera sa clé privée. Cette clé privée doit rester secrète. Elle détermine sa clé publique Ka par addition et doublement de points sur la courbe elliptique choisie.

Ka = ka·G
  • Bob génère également un nombre aléatoire qui sera sa clé privée kb. Et, il calcule la clé publique associée Kb.

Kb = kb·G
  • Alice et Bob s'échangent leurs clés publiques Ka et Kb sur un réseau public non sécurisé.

  • Alice calcule un point (x,y) sur la courbe en appliquant sa clé privée ka depuis la clé publique de Bob Kb.

(x,y) = ka·Kb
  • Bob calcule un point (x,y) sur la courbe en appliquant sa clé privée kb depuis la clé publique d'Alice Ka.

(x,y) = kb·Ka
  • Alice et Bob obtiennent le même point sur la courbe elliptique. Le secret partagé sera l'abscisse x de ce point.


Ils obtiennent bien le même secret partagé car :

(x,y) = ka·Kb = ka·kb·G = kb·ka·G = kb·Ka

Un éventuel attaquant qui observe le réseau public non sécurisé pourra uniquement obtenir les clés publiques de chacun et les paramètres de la courbe choisie. Comme expliqué précédemment, ces deux informations seules ne permettent pas de déterminer les clés privées, et donc l'attaquant ne peut pas accéder au secret.


ECDH est de ce fait un algorithme permettant un échange de clés. On va souvent l'utiliser aux côtés d'autres méthodes cryptographiques afin de définir un protocole. Par exemple, ECDH est utilisé au cœur de TLS (Transport Layer Security), un protocole de chiffrement et d'authentification utilisé pour la couche de transport d'internet. TLS utilise ECDHE pour l'échange de clés, une variante d'ECDH où les clés sont éphémères afin d'apporter de la confidentialité persistante. En plus de ce dernier, TLS utilise également un algorithme d'authentification comme ECDSA, un algorithme de chiffrement tel qu'AES et une fonction de hachage telle que SHA256.


TLS défini notamment le "s" dans "https", ainsi que le petit cadenas que vous voyez sur votre navigateur internet en haut à gauche, qui vous garantissent un chiffrement de la communication. Vous êtes donc en train d'utiliser ECDH en lisant cet article, et vous l'utilisez sans doute quotidiennement sans vous en rendre compte.




La transaction de notification.


Comme nous l'avons découvert dans la partie précédente, ECDH est une variante de l'échange Diffie-Hellman impliquant des paires de clés établies sur une courbe elliptique. Cela tombe bien, des paires de clés respectant ce standard, nous en avons plein nos portefeuilles Bitcoin !


L'idée va donc être d'utiliser les paires de clés des portefeuilles déterministes hiérarchiques Bitcoin des deux parties prenantes pour établir des secrets partagés et éphémères entre eux. Au sein du BIP47, on utilise donc plutôt ECDHE (Elliptic Curve Diffie-Hellman Ephemeral).


ECDHE est utilisé une première fois dans le BIP47 pour transmettre le code de paiement de l'expéditeur vers le destinataire. C'est la fameuse transaction de notification. En effet, pour que BIP47 puisse être utilisé, il faut que chacune des deux parties (l'expéditeur qui envoie des paiements, et le destinataire qui reçoit des paiements) soient au courant du code de paiement de l'autre partie. Cela sera nécessaire pour dériver les clés publiques éphémères, et donc les adresses de réception dédiées.


Avant cet échange, l'expéditeur est logiquement déjà en connaissance du code de paiement du destinataire puisqu'il a pu le récupérer off-chain, par exemple, sur son site web ou sur ses réseaux sociaux. En revanche, le destinataire n'est pas nécessairement en connaissance du code de paiement de l'expéditeur. Il va falloir le lui transmettre, sans quoi il ne pourra pas dériver ses clés éphémères, et donc il sera en incapacité de savoir où sont ses bitcoins et de débloquer ses fonds. On pourrait ainsi le lui transmettre off-chain, avec un autre système de communication, mais cela poserait un problème en cas de récupération du portefeuille depuis la graine.


En effet, comme je l'ai déjà évoqué, les adresses BIP47 ne sont pas dérivées depuis la graine du destinataire (sinon autant utiliser une de ses xpub directement), mais sont le fruit d'un calcul impliquant les deux codes de paiement : celui du destinataire et celui de l'expéditeur. C’est pourquoi, si le destinataire perd son portefeuille et essaie de le récupérer depuis sa graine, il devra nécessairement disposer de tous les codes de paiement des personnes qui lui ont envoyé des bitcoins via BIP47.


On pourrait donc facilement utiliser le BIP47 sans cette transaction de notification, mais il faudrait que chaque utilisateur fasse une sauvegarde des codes de paiement de ses pairs. Cette situation restera ingérable tant que l'on n'aura pas trouvé un moyen simple et résilient de réaliser, de stocker et de tenir à jour ces sauvegardes. La transaction de notification est donc quasiment obligatoire dans l'état actuel des choses.


En plus de ce rôle de sauvegarde des codes de paiement, comme son nom l'indique, cette transaction joue également un rôle de notification du destinataire. Elle permet de signaler à son client qu'un tunnel vient d'être ouvert.


Avant de vous expliquer plus en détail le fonctionnement technique de la transaction de notification, je souhaite vous parler un peu de modèle de confidentialité. En effet, celui du BIP47 va justifier certaines précautions prises lors de la construction de cette transaction initiale.


Le code de paiement en lui-même ne constitue pas directement un risque de perte de confidentialité. Contrairement au modèle classique de Bitcoin qui permet de casser le flux d'information entre l'identité de l'utilisateur et les transactions, notamment en gardant les clés publiques anonymes, le code de paiement peut être associé directement à une identité. Ce n'est évidemment pas une obligation, mais ce lien n'est pas dangereux.


En effet, le code de paiement ne dérive pas directement les adresses utilisées pour recevoir des paiements BIP47. Au lieu de cela, les adresses sont obtenues en appliquant ECDHE entre des clés filles des codes de paiements des deux parties.


Un code de paiement seul ne constitue donc pas un risque direct de perte de confidentialité puisque l'on ne dérive que l'adresse de notification depuis celui-ci. On peut en tirer certaines informations, mais on ne pourra normalement pas savoir avec qui vous faites des transactions.


Il est donc essentiel de maintenir cette séparation stricte entre les codes de paiements des utilisateurs. Dans cet objectif, l'étape de communication initiale du code est un moment critique pour la confidentialité du paiement, et pourtant obligatoire pour le bon fonctionnement du protocole. Si un des deux codes de paiements peut être récupéré publiquement (par exemple, sur un site web), le second code, c'est-à-dire celui de l'envoyeur, ne doit pas être associé au premier.


Par exemple, imaginons que je souhaite faire un don avec BIP47 à un mouvement de protestation pacifique au Canada :

  • Cette organisation a publié son code de paiement directement sur son site web ou sur ses réseaux sociaux.

  • Ce code est donc associé au mouvement.

  • Je récupère ce code de paiement.

  • Avant de pouvoir leur envoyer une transaction, je dois m'assurer qu'ils sont en connaissance de mon code de paiement personnel qui est également associé à mon identité puisque je l'utilise pour recevoir des transactions depuis mes réseaux sociaux.

Comment puis-je le leur transmettre ? Si je leur envoie avec un moyen de communication classique, l'information risque de fuiter, et je risque d'être fiché comme une personne qui soutient des mouvements pacifiques.


La transaction de notification n'est certes pas la seule solution pour transmettre le code de paiement de l'expéditeur secrètement, mais elle remplit pour l'instant parfaitement ce rôle en appliquant plusieurs couches de sécurité.


Dans le schéma ci-dessous, les traits rouges représentent le moment où le flux d'information doit être cassé, et les flèches noires représentent les liens indéniables qui peuvent être faits par un observateur extérieur :

Schéma modèle de confidentialité code de paiement réutilisable

En réalité, pour le modèle de confidentialité classique de Bitcoin, il est souvent difficile de casser complètement le flux d'information entre la paire de clés et l'utilisateur, notamment lorsque l'on réalise des transactions à distance. Par exemple, dans le cas d'une campagne de donation, le destinataire sera obligé de révéler une adresse ou une clé publique sur son site web ou ses réseaux sociaux. L'utilisation propre du BIP47, c'est-à-dire avec la transaction de notification, permet de résoudre cela grâce à ECDHE et à la couche de chiffrement que nous allons étudier.


Évidemment, le modèle de confidentialité classique de Bitcoin s'observe toujours au niveau des clés publiques éphémères dérivées à partir de l'association des deux codes de paiements. Les deux modèles sont interdépendants. Je souhaite simplement mettre en lumière ici que, contrairement à l'utilisation classique d'une clé publique pour recevoir des bitcoins, le code de paiement peut être associé à une identité, car l'information « Bob fait une transaction avec Alice » est cassée à un autre moment. Le code paiement est utilisé pour générer les adresses de paiements, mais en observant uniquement la blockchain, il est impossible d'associer une transaction de paiement BIP47 aux codes de paiement utilisés pour réaliser celle-ci.




Construction de la transaction de notification.


Maintenant, voyons comment fonctionne cette transaction de notification. Imaginons qu'Alice souhaite envoyer des fonds à Bob avec BIP47. Dans mon exemple, Alice agit ainsi comme l'expéditrice et Bob comme le destinataire. Ce dernier a publié son code de paiement sur son site web. Alice est donc déjà en connaissance du code de paiement de Bob.


1. Alice calcule un secret partagé avec ECDH :

  • Elle sélectionne une paire de clés au sein de son portefeuille HD se trouvant sur une branche différente de son code de paiement. Attention, cette paire ne doit pas être associée facilement à l'adresse de notification d'Alice, ni à l'identité d'Alice (voir partie précédente).

  • Alice sélectionne la clé privée de cette paire. Nous la nommons "a" (minuscule).

a
  • Alice récupère la clé publique associée à l'adresse de notification de Bob. Cette clé est la première fille dérivée depuis le code de paiement de Bob (index 0). Nous nommons cette clé publique "B" (majuscule). La clé privée associée à cette clé publique est nommée "b" (minuscule). "B" est déterminé par addition et doublement de points sur la courbe elliptique depuis "G" (le point générateur) avec "b" (la clé privée).

B =G
  • Alice calcule un point secret "S" (majuscule) sur la courbe elliptique par addition et doublement de points en appliquant sa clé privée "a" à partir de la clé publique de Bob "B".

S =B
  • Alice calcule le facteur aveuglant "f" qui va permettre de chiffrer son code de paiement. Pour cela, elle va déterminer un nombre pseudo aléatoire avec la fonction HMAC-SHA512. En seconde entrée de cette fonction, elle utilise une valeur que seul Bob sera en capacité de retrouver : (x) qui est l'abscisse du point secret calculé précédemment. La première entrée est (o) qui est l'UTXO consommé en input de cette transaction (outpoint).

f = HMAC-SHA512(o, x)

2. Alice convertit son code de paiement personnel en base 2 (binaire).


3. Elle utilise ce facteur aveuglant comme clé pour réaliser un chiffrement symétrique sur la charge utile de son code de paiement. L'algorithme de chiffrement utilisé est simplement un XOR. L'opération effectuée est comparable au chiffre de Vernam, également nommé le « masque jetable » (en anglais : "One-Time Pad") :

  • Alice sépare dans un premier temps son facteur aveuglant en deux : les 32 premiers octets sont nommés "f1" et les 32 derniers octets sont nommés "f2". On a donc :

f = f1 || f2
  • Alice calcule le chiffré (x') de l'abscisse de la clé publique (x) de son code de paiement, et le chiffré (c') de son code de chaine (c) séparément. "f1" et "f2" agissent respectivement comme clés de chiffrement. L'opération utilisée est le XOR (ou exclusif).

x' = x XOR f1
c' = c XOR f2
  • Alice remplace les valeurs réelles de l'abscisse de la clé publique (x) et du code de chaine (c) dans son code de paiement par les valeurs chiffrées (x') et (c').


Avant de continuer la description technique de cette transaction de notification, attardons-nous quelques instants sur cette opération XOR. Le XOR est un opérateur logique au niveau des bits fondé sur l'algèbre de Boole. À partir de deux opérandes en bits, il renvoie 1 si les bits de même r