Résumé
Une Preuve Zero-Knowledge permet à une partie (un vérificateur) de déterminer la validité d’une affirmation donnée par une autre partie (le prouveur), sans avoir connaissance du contenu de l’affirmation. Binance peut par exemple vouloir prouver l’adossement de l’intégralité des fonds de ses utilisateurs et utilisatrices à des réserves, sans avoir à révéler les soldes individuels de ceux-ci.
Une « Preuve de Réserves » pourrait être construite avec un arbre de Merkle qui empêche la falsification de ses données internes. Dans ce cas, les soldes nets totaux des clients, qui sont les passifs de l’exchange vis-à-vis de ses utilisateurs. Cela peut ensuite être combiné avec une zk-SNARK (un protocole de Preuves Zero-Knowledge) qui assure aux utilisateurs qu’ils peuvent vérifier que leur solde fait bien partie du solde total net des actifs des utilisateurs, sans connaître les soldes des autres utilisateurs.
Introduction
Au vu des récents évènements du marché, la sécurité des crypto-actifs en garde (custody) est devenue un sujet critique. Les utilisateurs de la blockchain apprécient la transparence et l’ouverture, mais sont également des défenseurs de la confidentialité et de la vie privée. Cela crée un dilemme lors de l’apport de preuves des réserves détenus par les dépositaires (custodians). Il existe d’ailleurs souvent un compromis entre transparence, confiance et confidentialité des données.
Mais, cela n’a pas besoin d’être le cas. En combinant des protocoles de Preuves Zero-Knowledge comme les zk-SNARKs avec les arbres de Merkle, nous pouvons trouver une solution répondant aux attentes de toutes les parties.
Qu’est-ce qu’une Preuve Zero-Knowledge ?
Une Preuve Zero-Knowledge permet à une partie (un vérificateur) de déterminer la validité d’une affirmation faite par une autre partie (le prouveur), sans avoir connaissance du contenu de l’affirmation. Prenons un exemple simple.
Vous avez un coffre-fort verrouillé dont vous êtes le seul à connaître la combinaison. Ce coffre-fort ne peut pas être crocheté, forcé ou ouvert d’une autre manière qu’en connaissant sa combinaison. Ce fait est également établi, vérifié et connu de votre ami participant à l’expérience.
Vous affirmez à votre ami que vous connaissez la combinaison, mais vous ne voulez pas la divulguer ou ouvrir le coffre en sa présence. Sur le dessus du coffre se trouve un trou dans lequel votre ami peut glisser une note. Pour en faire une Preuve Zero-Knowledge, votre ami ne devrait pas avoir d’information supplémentaire sur le processus et devra se contenter de votre déclaration.
Vous pouvez prouver à votre ami que vous connaissez la combinaison en ouvrant le coffre, puis en lui disant ce qui était écrit sur la note, avant de le refermer. Bien évidemment, vous ne révèlerez pas la combinaison.
Pour un exemple plus avancé, consultez notre article Qu’est-ce qu’une Preuve Zero-Knowledge et quel effet a-t-elle sur la blockchain ?.
Pourquoi utilisons-nous des Preuves Zero-Knowledge ?
Les Preuves Zero-Knowledge sont parfaites pour prouver quelque chose sans révéler d’informations ou de détails sensibles. Cela pourrait convenir à vos besoins si vous ne voulez pas divulguer vos informations financières ou personnelles, afin d’éviter qu’elles ne soient utilisées de manière inappropriée.
Dans le monde de la crypto, vous pourriez prouver que vous possédez une clé privée sans la révéler, ou sans devoir signer numériquement quelque chose. Un exchange de cryptomonnaie peut également vouloir prouver l’état de ses réserves sans révéler d’informations confidentielles sur ses utilisateurs, y compris le solde individuel de leurs comptes.
Dans ces exemples (et dans beaucoup d’autres), une Preuve Zero-Knowledge utiliserait des algorithmes qui prennent des données en entrée et renvoient « vrai » ou « faux » en sortie.
Définition des Preuves Zero-Knowledge en termes techniques
Une Preuve Zero-Knowledge, en termes techniques, suit une structure utilisant des critères précis. Nous avons déjà examiné les rôles du prouveur et du vérificateur, mais une Preuve Zero-Knowledge doit également satisfaire trois autres critères :
Complétude. Si l’affirmation est vraie, un vérificateur sera convaincu par la preuve fournie, sans besoin d’autres informations ou d’autres vérifications.
Fiabilité. Si l’affirmation est fausse, un vérificateur ne sera pas convaincu de sa véracité par la preuve fournie.
Zero-knowledge (sans connaissance). Si l’affirmation est vraie, le vérificateur n’apprend aucune information, hormis que l’affirmation est vraie.
Qu’est-ce qu’une Zk-Snarks ?
Une Zk-Snarks (Zero-Knowledge Succinct Non-Interactive Argument of Knowledge) est un protocole de preuve qui suit les principes de divulgation nulle de connaissance précédemment énoncés. Avec une zk-SNARK, vous pourriez prouver que vous connaissez la valeur hachée originale (discutée plus bas) sans devoir la révéler. Vous pouvez également prouver la validité d’une transaction sans révéler d’informations sur les montants, les valeurs ou les adresses concernés.
Les zk-SNARKs sont couramment utilisées et discutées dans le monde de la blockchain et des cryptomonnaies. Vous vous demandez peut-être pourquoi quelqu’un se donnerait la peine d’utiliser une zk-SNARK lorsqu’il pourrait utiliser une simple méthode de paire de clés publique/privée pour sécuriser l’information. Avec cette paire de clés, nous ne serions pas en mesure de mettre en œuvre la preuve mathématique garantissant qu’aucun solde négatif n’est inclus dans la somme de l’arbre de Merkle.
Dans le cas des réserves d’une plateforme d’exchange, nous voulons prouver un ratio 1 : 1 des soldes des clients, sans que les identifiants et les soldes des comptes de ceux-ci ne soient rendus publics. De plus, la technologie zk-SNARK rend encore moins probable la falsification des données.
Qu’est-ce qu’un arbre de Merkle ?
Présenter la somme des fonds des comptes des utilisateurs de Binance nécessite de travailler avec un grand nombre de données. Une façon de présenter cette grande quantité de données de manière cryptographique est d’utiliser un arbre de Merkle. Une grande quantité d’informations peut être stockée efficacement à l’intérieur de celui-ci et sa nature cryptographique rend son intégrité facilement vérifiable.
Fonctions de hachage
Pour encoder succinctement une entrée, un arbre de Merkle utilise des fonctions de hachage. Pour faire simple, le hachage est le processus de génération d’une sortie de taille fixe à partir d’une entrée de taille variable. En d’autres termes, lorsqu’une entrée de n’importe quelle longueur est hachée par un algorithme, elle produira une sortie chiffrée de longueur fixe.
Tant que l’entrée reste la même, la sortie le sera aussi. Cela signifie que nous pouvons prendre d’énormes quantités de données transactionnelles et les hacher en une sortie plus facile à gérer. La sortie sera radicalement différente si une information est modifiée dans l’entrée.
Nous pourrions par exemple prendre le contenu de 100 livres et les entrer dans la fonction de hachage SHA-256. Celle-ci fournirait alors quelque chose comme ceci en sortie :
801a9be154c78caa032a37b4a4f0747f1e1addb397b64fa8581d749d704c12ea
Si nous modifions ne serait-ce qu’un seul caractère de l’entrée (ces 100 livres), le hachage sera complètement différent :
abc5d230121d93a93a25bf7cf54ab71e8617114ccb57385a87ff12872bfda410
Cette propriété importante des fonctions de hachage permet une vérification facile de l’exactitude des données. Si quelqu’un reproduit le processus de hachage de ces mêmes 100 livres en utilisant l’algorithme SHA-256, il obtiendra exactement le même hachage en sortie. Si la sortie est différente, nous pouvons affirmer avec certitude que l’entrée a été modifiée. Cela signifie qu’il n’est pas nécessaire de vérifier individuellement ou manuellement les différences entre les entrées, ce qui peut être laborieux.
Les arbres de Merkle dans le monde des cryptomonnaies
Lors de la sauvegarde des données de transaction sur une blockchain, chaque nouvelle transaction est soumise à travers une fonction de hachage, qui génère des valeurs de hachage uniques. Imaginez que nous ayons huit transactions (de A à H) que nous hachons individuellement pour obtenir leurs sorties hachées. Ce sont ce que nous appelons les nœuds feuilles de Merkle. Dans l’image ci-dessous, vous pouvez voir la valeur de hachage unique de chaque lettre : hA pour A, hB pour B, hC pour C, etc.
Nous pouvons ensuite prendre des paires de sorties hachées, les combiner et obtenir une nouvelle sortie hachée. Les hachages de hA et hB hachés ensemble, nous donneraient par exemple une nouvelle sortie hachée de hAB connue sous le nom de branche de Merkle. Veuillez remarquer qu’à chaque fois qu’une nouvelle sortie est générée, celle-ci dispose d’une une longueur et d’une taille fixe, qui dépend de la fonction de hachage utilisée.
Maintenant, nous avons les données de deux transactions (ex : A et B) combinées en un seul hachage (hAB). Veuillez remarquer que si nous changeons une quelconque information de A ou B et répétons le processus, notre sortie hachée hAB serait complètement différente.
Le processus continue alors que nous combinons de nouvelles paires de hachages pour les hacher à nouveau (voir l’image ci-dessous). Nous hachons hAB avec hCD pour obtenir un hachage unique hABCD et faisons de même avec hEF et hGH pour obtenir hEFGH. À la fin, nous recevons un seul hachage représentant les sorties hachées de tous les hachages des transactions précédentes. En d’autres termes, la sortie hachée hABCDEFGH représente toutes les informations qui l’ont précédée.
Le graphe affiché ci-dessus est appelé un arbre de Merkle. La sortie hachée hABCDEFGH est la racine de Merkle. Nous utilisons les racines de Merkle dans les en-têtes de blocs, car elles résument succinctement cryptographiquement toutes les données de transaction dans un bloc. Nous pouvons également vérifier rapidement si des données ont été falsifiées ou modifiées à l’intérieur du bloc.
Les Limites des Arbres de Merkle
Revenons à notre exemple de réserves d’un CEX. Un CEX veut prouver l’adossement 1 : 1 de tous les actifs de ses clients et construit un arbre de Merkle qui hache ensemble les UID de ses clients avec leurs avoirs nets en actifs (compensant les actifs et les passifs) au niveau d’un token. Une fois publié (et signé pour prouver la propriété de la racine de Merkle fournie), un utilisateur individuel ne pourrait pas vérifier si l’arbre de Merkle est valide sans accéder à toutes ses entrées.
Un exchange aurait pu manquer d’inclure certaines entrées. Il pourrait également créer de faux comptes avec des soldes négatifs pour modifier le passif total. Par exemple, bien que les actifs des clients puissent totaliser 1 000 000 $, un faux compte pourrait être ajouté avec un solde de - 500 000 $. Cela créerait une cible de réserves de seulement 500 000 $.
Le cas de la preuve de réserves est différent de celui de la racine de Merkle d’un bloc, car les utilisateurs peuvent voir toutes les transactions qu’un bloc contient sur un explorateur de blockchain. Cependant, un CEX ne voudra pas divulguer chaque solde de compte pour des raisons de sécurité et de confidentialité des données. Les clients ne seraient pas non plus heureux que le solde de leur compte soit rendu public. Dans ce cas, le CEX ne peut pas prouver que le total des soldes des utilisateurs est correct, sans rendre visibles les soldes des autres utilisateurs.
Une solution que les exchanges pourraient envisager d’employer consiste à avoir recours un auditeur tiers de confiance. L’auditeur peut vérifier les comptes individuels et les réserves avant de certifier la validité de la racine de Merkle fournie. Cependant, pour les utilisateurs, cette méthode nécessite de faire confiance à l’auditeur et aux données utilisées pour l’audit. Vous n’avez pas besoin de faire confiance à un tiers lorsque vous pouvez faire confiance aux données.
Combinaison des zk-SNARKs avec les arbres de Merkle
Le problème mentionné précédemment est un cas parfait pour l’utilisation des zk-SNARKs. Nous voulons prouver que les réserves couvrent entièrement les passifs des utilisateurs et qu’elles ne sont pas falsifiées. Cependant, pour des raisons de confidentialité et de sécurité, nous ne voulons pas montrer au vérificateur la composition exacte des soldes et des réserves des utilisateurs.
En utilisant une zk-SNARK, un exchange de cryptomonnaie peut prouver que tous les ensembles de soldes des nœuds feuilles de l’arbre de Merkle (c’est-à-dire, les soldes des comptes utilisateurs) contribuent au total du solde d’actifs des utilisateurs revendiqué par l’exchange. Chaque utilisateur peut facilement accéder à son nœud feuille, celui-ci ayant été inclus dans le processus. Le zk-SNARK garantit également qu’aucun arbre de Merkle généré ne contient d’utilisateurs avec un solde net total d’actifs négatif (ce qui impliquerait une falsification des données, car tous les prêts sont sur-collatéralisés). Nous utilisons également un calcul de l’état global de Binance, c’est-à-dire, une liste du solde net total de chaque actif détenu par chaque client de Binance.
Examinons comment Binance aborde la situation. Pour commencer, Binance définit les contraintes du calcul qu’il souhaite prouver et les définit comme un circuit programmable. Voici l’ensemble des trois contraintes que Binance utilise dans son modèle.
Pour chaque ensemble de soldes d’utilisateur (nœud feuille de l’arbre de Merkle), notre circuit assure que :
Les soldes d’actifs d’un utilisateur sont inclus dans le calcul de la somme des soldes nets totaux des utilisateurs de Binance.
Le solde net total de l’utilisateur est supérieur ou égal à zéro.
Le changement de la racine de l’arbre de Merkle est valide (c’est-à-dire, n’utilise pas d’informations falsifiées) après la mise à jour des informations d’un utilisateur vers le hachage du nœud feuille.
Binance peut ensuite générer une preuve zk-SNARK pour la construction de l’arbre de Merkle selon le circuit. Cela implique que l’exchange exécute le calcul lourd du hachage des identifiants et des soldes des utilisateurs, tout en s’assurant que la preuve respecte les contraintes.
Un vérificateur examinera la preuve (et son code source publié publiquement) pour être convaincu que le calcul est exécuté avec toutes les contraintes respectées. Le calcul de vérification prend un temps extrêmement court comparé au temps de preuve.
À chaque publication de la Preuve de Réserves, l’exchange publiera :
1. La preuve de Merkle pour chaque utilisateur.
2. La preuve zk-SNARK et l’entrée publique (un hachage de la liste du solde net total de chaque actif et de la racine de Merkle) du circuit pour tous les utilisateurs.
Les parties intéressées peuvent vérifier la preuve de Merkle, en s’assurant que leurs soldes individuels ont contribué à la racine de l’arbre de Merkle. Elles peuvent également vérifier la preuve zk-SNARK pour s’assurer que la construction de l’arbre de Merkle répond aux contraintes définies dans le circuit. Pour une explication plus détaillée de la solution zk-SNARK et de ses performances, consultez notre blog Comment les zk-SNARK améliorent-elles le système de preuve de réserves de Binance ?
Conclusion
Les zk-SNARK fournissent la technologie nécessaire pour assurer à la fois l’intégrité des données et la confidentialité en même temps. Son application pour prouver les réserves et augmenter la transparence des CEX devrait aider à renforcer la confiance dans l’industrie de la blockchain. Pour beaucoup, un développement comme celui-ci a été longuement attendu et arrive à un moment crucial pour les CEX.
Il s’agit de la première version de notre zk-SNARK et nous avons hâte de recevoir les avis de la communauté afin de pouvoir continuer à améliorer notre système.