Proposition d'un modèle de portefeuilles "HD"

C’est assez complexe, mais ça se base sur des opération sur courbes elliptiques. Le côté géométrique de ces opérations ont des propriétés permettant ce genre de choses. J’ai une idée de comment ça fonctionne, mais pas assez détaillée pour vous expliquer le fonctionnement complet. Je vais essayer de retrouver un article que j’avais lu qui expliquait comment ça marchait avec les opérations sur courbes.

Au niveau de la “vérification” : si je signe un message avec la clé privée de dérivation 1/4 (dérivation d’index 1, puis de nouveau dérivée d’index 4), la clé publique 1/4 permettra de vérifier la signature.

EDIT : Voila le lien qui propose des schémas et les calculs.

EDIT 2 : Autre utilisation que je viens de voir dans le lien ce dessus : un site commerçant peut générer une nouvelle adresse par client pour facilement identifier le paiement, et ce sans générer de clés privés. De ce fait le serveur web peut être compromis sans risquer de récupérer les clés privés et de voler l’argent. La clé mère est stockée en lieu sûr et peut être utilisée pour générer toutes les clés privées correspondantes au clés publiques proposées par le site.

1 « J'aime »

On peut prendre les paramètres N,r,p que l’on veut, supposons 4096,16,1 par exemple. Pour la concision je donne donc juste les paramètres salt et password.

Ce que tu peux déjà tout à fait faire avec scrypt:

Moi, patron, génère ma clé maîtresse avec mon salt_secret1 et password_secret1, générant alors sk1 (secret key 1) et pk1 (public key 1).

De là je dérive n clés pour mes n employés, à l’aide de la fonction :

Pour i de 0 à n    
    dériveSousControleDuPatron(i,pk1,sk1)
        = scrypt(pk1 + i, sk1)
        = sk_e_i, pk_e_i

De là l’employé peut lui-même continuer à dériver une suite de clés en réutilisant cette fonction (avec ses propres paramètres sk_e_i et pk_e_i), et en respectant le même protocole de dérivation “pour i de 0 à n”.

1 « J'aime »

Les HD wallets permettent de générer une hiérarchie de clés publiques à partir de pk1 sans connaitre sk1, et inversement pour une hiérarchie de clés privées; les 2 correspondant entre elles. Or ici scrypt a bien besoin d’avoir les deux clés d’une paire pour générer la paire fille, non ?

“Fonctionnement” plus formel :
Soit la clé m la clé maître privée, et M la clé maître publique associée.
Avec m tu peux générer m/i pour tout i, sans connaître M.
Avec M tu peux générer M/i pour tout i, sans connaître m.
Et ce de manière récursive.

Il y a un autre composant (le chain code) qui est utilisé en interne et qui peut permettre ou non de dériver un niveau de plus.

1 « J'aime »

Je ne vois toujours pas en quoi le résultat final serait différent d’un point de vue fonctionnel : à la fin, on a une hiérarchie de trousseaux où un détenteur d’une sous partie ne peut pas remonter vers les trousseaux parents.

Je ne dis pas qu’il n’y a pas un intérêt supplémentaire à l’utilisation de scrypt que je ne vois pas, par contre il faudrait le révéler pour qu’on puisse comprendre :slight_smile:

Dans aucune de vos suggestions je ne vois de manière d’implémenter :

Soit m/i la clé dérivée de M
Comment vérifier, avec l’info de dérivation, que m est une clé dérivée de M ?

Je l’ai fait plusieurs fois :

Tu peux générer la partie publique de la hiérarchie sans connaître la clé privée, ce que l’on ne peut pas faire avec les exemples de code que tu me propose avec scrypt. Ce point là permet notamment de générer des clés publiques sur un site web de commerce sans qu’il ne stocke jamais une seule clé privée sur le serveur.

De même pour le minage avec clé dérivée (ou accès à compte membre par clés dérivées), avec la clé publique les utilisateurs pourront générer les clés publiques filles sans connaître la clé privée (heureusement), et du coup vérifier la signature produite par la clé privée dérivée utilisée par le membre. La clé privée dérivée est compromise ? On la révoque avec un nouveau type de document dans ce but, et on en utilise une nouvelle dérivée avec un autre index. Avec la clé publique mère, la signature et le chemin de dérivation, les utilisateurs pourront vérifier le message signé.

Le public ne connait que M et peux calculer M/0, M/1, M/1/0 etc, et du coup vérifier les signatures issues des clés privées m/0, m/1, m/1/0.

En plus de ça il y a la possibilité d’avoir des clés “renforcées” qui empêche certaines dérivations, noté par exemple M/0'. Cela permet d’empecher de remonter ou de decendre dans la hierarchie si on ne connait pas clé publique + chain code (appelée clé étendue). Tout ça est très bien expliqué dans ce lien que j’ai déjà donné au dessus. :wink:

Une clé dérivée de M (publique) se note M/i, m c’est la clé privée.
Mais si tu définie m comme étant M/0 par exemple, alors tu peux dériver M/0 à partir de M, ce qui ne sert pas à grande chose.
Ce qui est beaucoup plus intéressant et non faisable avec scrypt (il me semble) :

  • Dériver m/i à partir de m.
  • Dériver M/i à partir de M.
  • Signer un message avec m/i
  • Vérifier le message avec M/i

Et ce peu importe i, m et M tant que (m;M) est une paire de clés.

Le but ce n’est pas de prouver que A est dérivé de B (il suffit de dériver B pour le savoir), mais de pouvoir vérifier un message signé par a dérivé de b avec la clé A.

Dans ces cas là je ne parle pas des clés “renforcées” (m/i' et M/i') qui permettent justement de restreindre les dérivation pour rajouter des “barrages” en cas de fuites d’informations.

2 « J'aime »

Qu’est-ce qu’apporte le fait que a soit dérivé de b ?

Par exemple :

  • l’utilisateur Bob, génère une clé a pour Alice.
  • l’utilisateur Bob, dérive une clé a depuis sa clé b pour Alice

Qu’est-ce que ça change, fonctionnellement ? Est-ce que ça apporte quelque chose à un utilisateur Chris qui chercherait à échanger avec Alice ou Bob ?

Cette fonctionnalité m’intéresse fortement, notamment le fait de pouvoir générer a la volée une clé publique pour chaque client sans stocker de clé privée correspondante, c’est un réel besoin pour ceux qui souhaitent vendre des services en Ğ1 payables en ligne et de façon anonyme, hors c’est mon cas, et nul doute que ce sera le cas de beaucoup de monde à terme.

Ça me semble être une raison nécessaire et suffisante pour justifier d’implémenter les portefeuilles HD :slight_smile:

2 « J'aime »

Je ne comprend pas ton cas exposé qui ne correspond pas à ce que j’ai présenté.

C’est une des possibilités en effet, et c’est une des raisons pour laquelle je pense qu’il serait bien de le développer.
Dans ce cas là c’est simple pour le vendeur de voir que le client correspondant à bien payé, mais en plus chaque client ne peux pas voir directement qui à déjà acheté au vendeur, vu que dans ce cas là le vendeur ne vas pas donner la clé publique mère, ni le chemin de dérivation.


Le cas où le chemin de dérivation peut être utile c’est pour des clés privées dérivées pour les mineurs voir pourquoi pas pour les comptes membres avec un accès révocable sans révoquer le compte en lui même.


Ca me fait penser qu’au vu de la façon dont sont gérée les signatures, ça pourrait être des opérateurs en plus de ceux utilisant scrypt, sans avoir besoin de remplacer scrypt en lui même. C’est juste une autre solution, potentiellement avec un autre format d’adresse.

1 « J'aime »

Révoquer une clé fille ou déclarer une nouvelle clé revient à la même chose (c’est une opération de changement de clé). Donc, on peut tout à fait se passer de ce mécanisme de dérivation, qui tout au plus fait gagner 1 coup sur N (le 1er, car on n’aurait pas besoin de déclarer la clé fille).

Si “avoir en mémoire le temps de la dérivation” tu appelles cela « stocker », alors en effet, mais dans ce cas je trouve l’intérêt très limité.

J’essaie de percevoir les différences entre “dériver à partir de” et “générer pour autrui”.

Et comment est déverrouillée la monnaie de ces clés publiques ensuite ?

1 « J'aime »

Non … Vous n’avez pas besoin de la partie privée pour dériver la partie publique, et inversement. Les hierarchies publiques et privées peuvent être générées sans connaitre l’autre. Tant que (m,M) est une paire de clés valide, alors (m/1,M/1), (m/2,M/2), (m/2/3/18,M/2/3/18) le seront aussi.

Il n’y a pas de “générer pour autrui”. Tu dérive une clé à partir d’une autre, c’est tout. Si c’est une clé publique, tu peux la donner à autrui pour qu’il fasse un paiement dessus, auquel cas tu pourras t’en servir en utilisant la clé privée ayant le même chemin de dérivation.

Du coup je ne vois pas la différence avec des clés classiques ?

Ca me parait équivalent à :

Tu génères une clé publique pour autrui, tu pourras t’en servir en utilisant la clé privée qui correspond

Depuis m/1 ou M/1, peut-on retrouver m et M, ou du moins vérifier que (m/1,M/1) corresponde à (m/M) ?

Elle ne sont pas différente dans leur utilisation, mais dans leur génération. A partir de la clé publique mère tu peux générer toutes les filles qui correspondront aux filles de la clé privée mère.

Pour un système de commerce plus anonyme, voila la procédure :

  • Tu génère une paire (m,M) (privé/publique)
  • Sur le site de commerce, tu donne uniquement ta clé publique M
  • Pour chaque client, le site va dériver M/1, M/2, etc
  • Si tu veux accéder à cet argent, tu dérive m/1, m/2, etc en local pour signer les transactions.

Au final tu n’as mis qu’une seule clé publique sur le site qui peut être dérivée pour une “infinité” de clients, chaqu’un en ayant une différente.

Pour le vérifier il te suffit de dériver M à l’index 1 pour trouver M/1. Mais ce n’est pas le but de ce système.
On note M/1 la “dérivée” de M avec comme paramètre 1. Il y a la formule pour calculer M/1 à partir de M dans le document que j’ai donné. (pareil pour m)

2 « J'aime »

Donc il faut connaitre M, ok. Je me demandais si M/1 pouvait prouver qu’il était bien le descendant de M :slight_smile: Ce n’est donc pas le cas.

Ok, je comprends mieux l’intérêt. Si la clé M est compromise, on peut connaitre toutes les clés publiques M/i mais pas les dévérouiller. Et seulement la clé M est fournie aux agents qui vont héberger le système sensible. La partie privée reste hébergée dans une zone sécurisée, offline par exemple.

2 « J'aime »

Je parle de la partie qui utilise scrypt. Car tu me dis « l’intérêt de la dérivation HD c’est qu’on n’a pas besoin de la clé privée », or, l’intérêt de qui est-ce que cela sert ?

Si c’est l’intérêt du web-commerçant, c’est un intérêt économique particulier qu’on n’a pas besoin de favoriser, surtout s’il peut déjà établir un comportement similaire via d’autres méthodes comme scrypt (ou autre, peu importe).

Si c’est l’intérêt des membres de la Ğ1 pour la clé déléguée, alors j’ai déjà répondu qu’on ne gagne qu’un coup sur N, ce qui est négligeable. D’ailleurs cela restreint les clés utilisables à celles dérivées de la clé mère, tandis qu’un mécanisme de déclaration permet de déclarer n’importe quelle clé.

Mais de manière générale, si ce mécanisme peut être obtenu sans rien modifier au protocole Duniter, alors vous faites ce que vous voulez.

Donc en fait si l’une des clé est identifiée comme appartenant au site S, alors on connaît tous ses clients instantanément. Bien.

Exactement.

Dans le cadre du minage ou des comptes membres (dont la clé n’est pas changeable), on peut justement utiliser ce système de dérivation pour créer des “sous-clés” révocables. Tu n’expose pas ta vraie clé privée mais seulement une dérivation, et si cette dernière est compromise, tu pourrais (avec ta clé mère) révoquer cette sous-clé et en utiliser une autre. De cette manière ce n’est pas risqué de miner sur une machine que l’on ne contrôle pas totalement, et pour les wallets mobile/web ça peut permettre d’utiliser son compte membre tout en pouvant révoquer uniquement l’appareil compromis. En tant que membre j’ai ma paire (m,M). J’utilise Cesium avec (m/1,M/1) et mon smartphone avec (m/2,M/2). Si il s’avère que j’ai un keylogger qui à intercepté m/1, je peux avec m publier un document révoquant l’accès avec m/1 sans pour autant révoquer le compte tout entier. C’est comme si tu faisais opposition sur ta carte bancaire sans fermer ton compte (sans les remboursement évidement)

2 « J'aime »

Reste à comprendre comment implémenter ça proprement :slight_smile: Idéalement via libsodium qui est la librairie qui nous sert à faire les clés de signature et de chiffrement. (scrypt ne fait que générer les seeds)

1 « J'aime »

Oui, en cas de hack de la plateforme ou si le vendeur la révèle. Si la personne accepte des paiement sur son site il ne donnera pas M, seulement des dérivés. L’avantage c’est qu’il n’expose jamais les clés privés permettant de voler l’argent.

Il peut très bien y avoir un document “Je mine avec la dérivation /3 de ma clé publique” signé par la clé privée père, ainsi qu’un 2ème pour révoquer cet état.

Pour le côté utilisateur, je ne sais pas si cet algo est pour ed25519 ou curve25519 (ou les 2), mais si ce n’est pas le cas il suffirait de rajouter 1 opcode, voir un 2eme pour payer sur le hash d’une clé (la clé publique est alors demandé en input).

Pour le côté mineur/compte membre, ça serait en effet une modification du protocole pour autoriser les mineurs d’utiliser les sous-clés, de même pour les comptes membres.

C’est une simple proposition d’amélioration du protocole qui pourrait régler certains problèmes (exposition de la clé privé “principale” sur la machine qui mine, exposition de la clé privé “principale” sur un wallet)

Je vais regarder ça.

EDIT : @cgeek J’avais mal lu ta remarque. On pourra connaître tous les clients uniquement si M fuite. De plus si les clients utilisent des HD wallets avec adresses à usage unique, le risque est bien moindre, puisqu’à la prochaine transaction de cette adresse tu pourras difficilement savoir à qui appartient les adresses de destination.

1 « J'aime »

Si le protocole doit être modifié pour autoriser les clés déléguées, je ne vois pas de raison valable de se limiter aux clés dérivées :

  • car déjà il n’y a pas de gain particulier en nombre de documents car soit 1) on utilise des clés dérivées, et alors il faut un document pour les révoquer ; soit 2) on autorise tout type de clé, et alors il faut un document pour les déclarer.

  • mais en plus avec 1), on est contraint de mémoriser en blockchain tout l’historique des révocations pour être sûr qu’une clé déléguée n’a pas déjà été révoquée, ce qui va nous faire stocker inutilement de la donnée et multiplier les accès en lecture. Tandis qu’avec 2), on a juste à mémoriser en blockchain la dernière clé déclarée qui est la seule à pouvoir calculer, on peut aussi revenir sur une clé précédente, et on peut même utiliser une clé générée par nos soins d’une toute autre façon que la dérivation. Bref, on a le choix et une taille constante de clés déléguées possibles en blockchain.

Alors sauf à ce que les clés dérivées apportent un autre bonus vraiment intéressant pour le calcul de blocs, je trouve contre-productive leur utilisation dans ce cadre.

1 « J'aime »