Polkadot.js multilang mnemonic?

Attention, à l’attention des codeurs python :bangbang:

En travaillant sur la création de compte avec mnémonique en langue non anglaise, avec le module keypair du client python substrateinterface j’obtenais toujours la même adresse entre un mnémonique français et son équivalent en anglais (équivalent selon notre bidouille). Ce qui ne devrait pas être selon le protocole bip39…

J’ai donc découvert avec stupeur que le module keypair de substrateinterface fait aussi et déjà ce que nous avons décidé de faire, en utilisant la lib rust compilée pour python bip39.

Pour générer l’adresse, la seed n’est pas générée depuis le texte du mnémonique, mais depuis l’entropie (l’équivalent des mots en numéro de 0 à 2048), sans mot de passe. Ils appellent la seed “mini secret”.

.venv/lib/python3.7/site-packages/substrateinterface/keypair.py:211

seed_array = bip39_to_mini_secret(mnemonic, "", language_code)

Exemple avec deux mnémoniques équivalents (les mots ont la même valeur dans les wordlists) :

import bip39
bip39.bip39_to_mini_secret('foil apple tribe renew cry risk same trumpet long destroy glare analyst', '', 'en')
[175, 53, 82, 102, 183, 63, 22, 231, 16, 61, 6, 187, 2, 62, 72, 129, 168, 208, 39, 49, 95, 85, 146, 39, 54, 163, 219, 23, 74, 44, 224, 100]
bip39.bip39_to_mini_secret('esquiver alpaga tasse pénurie coiffer pixel potager teneur intense cubique farceur aider', '', 'fr')
[175, 53, 82, 102, 183, 63, 22, 231, 16, 61, 6, 187, 2, 62, 72, 129, 168, 208, 39, 49, 95, 85, 146, 39, 54, 163, 219, 23, 74, 44, 224, 100]

Je me demande donc si c’est une liberté du client python ou aussi des développeurs qui utilisent la lib rust bip39 ?

1 Like

Ce comportement semble spécifique à cette fonction bip39_to_mini_secret, mais elle ne semble pas faite pour générer la seed, si ?

bip39_to_seed semble plus indiquée, et utiliser la suite de mots.

Serait-il utile d’avoir une bibliothèque à nous implémentant la bidouille, pour assurer une bonne compatibilité ? Étant donnée la simplicité de l’implémentation (un petit wrapper autour d’une lib bip39 quelconque) je me dis que c’est plus simple que chaque langage ait la sienne (plutôt qu’un unique binding Rust qui va compliquer la stack de tout le monde).

Duniter-connect génère la même adresse que le client python substrateinterface :

foil apple tribe renew cry risk same trumpet long destroy glare analyst

V1: LFVtJvBt6dp1vPuy6zejFqCF9Uu1VoGRpLnqXihN17f
V2: 5CBAsoVagE4HpFTBG6KPmdFWBJkBZcnwwuewU1fyb9TscMbH

Donc utilise le mini-secret issu de l’entropie au lieu de la phrase mnémonique… :scream:

Je pense qu’il faut que l’on soit sûr de la seed générée par nos clients pour assurer une compatibilité. Et comprendre pourquoi la communauté substrate et son client javascript utilise le mini-secret pour les SR25519.

1 Like

J’avais vu hier que la lib Rust sp-core utilise les “mini secrets” de Schnorrkel pour générer la seed. Je ne sais pas si ce sont les mêmes, si c’est standardisé.

Dans Schnorrkel, la seed fait 32 octets, la clé privée 64 (32 de clé et 32 de nonce).

En fait c’est vraiment la jungle : des standards de fait, des bibliothèques de crypto écrites par une seule personne avec des commentaires dans lesquels ils se plaignent que tout ça n’a aucun sens, le code pour seule documentation… et tout un écosystème conçu “par des experts” qui repose dessus.

1 Like

Ok, bah dans ce cas walou, rfc bidouille let’s gooo
Puis on mettrà à disposition des phrases de restauration converti pour exporter vers tel ou tel système.

1 Like

Tout est expliqué dans l’encart rouge et confirme ma découverte.

Not all wallets use the same algorithm to convert from mnemonic phrase to private key

Subkey and Polkadot-JS based wallets use the BIP39 dictionary for mnemonic generation, but use the entropy byte array to generate the private key, while full BIP39 wallets (like Ledger) use 2048 rounds of PBKDF2 on the mnemonic. The same mnemonic may generate different private keys on other wallets due to the various cryptographic algorithms used. See Substrate BIP39 Repo for more information.

3 Likes

Ok. Merci d’avoir creusé, ça confirme mon intuition :

Donc il faudra être clair sur l’algo utilisé pour générer les seed et la dérivation des clés. Comme “c’est la jungle”, autant adopter ce qui nous paraît le plus sain. Et pour moi c’est clair que les nombres c’est pour l’ordi et les mots pour l’humain. Ça n’a aucun sens de faire passer du langage naturel en utf8 (les deux étant faits pour l’humain) dans une fonction de hashage pour retrouver un nombre à destination de l’ordi. Autant utiliser directement le nombre.

Et comme il s’agit de nombre entiers naturels plus grands que ce que gère normalement un ordinateur, il faut être clair sur la représentation en byte array qui sera manipulée sur la machine pour pas laisser des ambiguïtés comme l’endianness.

2 Likes

Si c’est la jungle c’est peut être parce que BIP39 a fait n’imp sur ce coup là et que tout le monde préfère faire autrement.

4 Likes

@elois discutions mnemonic multilangue ici

1 Like

Je ne sais pas quel est le processus pour approuver une RFC, c’est prêt à merger pour les mnemonics multilingues : RFC18 Multilang Mnemonic (!17) · Merge requests · documents / RFCs · GitLab

Je ne me souviens pas avoir vu d’opposition donc je pense que ça fait consensus et poka a pu l’implémenter, mais j’aimerais bien un avis d’@elois et de @moul.

2 Likes

Merci pour la demande d’avis.

L’idée d’avoir un mnémonique multi-langue semble intéressante en surface. Voyons-voir si on creuse. Quel est l’objectif de le mettre en place ? L’avoir dans la langue maternelle permettrait à l’utilisateur de se souvenir de son mnémonique ? Quel est son usage ? Est-ce que les utilisateurs l’apprennent par cœur ou bien le note ? Dans le premier cas, l’avoir dans sa langue maternelle aiderait, dans le second cas je ne crois pas que ça aiderait.

Je trouve qu’implémenter cette RFC dans les apps rajoute une complexité non nécessaire. Plus on maintient de choses, plus il y a un risque de bug ou de problème.

Dès qu’une app implémente cette RFC, est-ce que les autres apps doivent également gérer le mnémonique multi-langue ? Autrement l’utilisateur ne peut pas signer d’extrinsics avec son mnémonique non-anglais dans une autre app qui ne l’implémenterait pas ? Cette RFC s’impose donc à toutes les apps une fois entrée en vigueur ?

Autrement, la RFC est en soit correctement formulée. En elle-même, je ne m’y oppose pas fermement. Cependant, ce qui m’embête est le fait est que toutes les apps (imposé) doivent l’implémenter pour avoir un écosystème Ğ1 cohérent. De plus, je préfèrerais ne pas complexifier l’implémentation des apps avec qqch de non-nécessaire.

Si on a fait fausse route et que l’on souhaiterait faire un retour en arrière fait vers l’usage unique des mnémoniques en anglais. Un outil de migration pourrait convertir les mnémoniques non-anglais vers un mnémonique anglais. C’est plutôt simple à faire un retour arrière pour un utilisateur. Coordonner que la communauté Ğ1 migre leurs mnémoniques est un peu plus compliqué. Les apps pourraient toujours accepter les mnémoniques en plusieurs langues, mais ne générer que les mnémoniques en anglais.

L’avantage de cette RFC, justement, c’est que les mnémoniques générés en multilingue peuvent être convertis en anglais à la volée, à tout moment.

Je l’ai implémenté dans Gecko, du coup, si le mnémonique n’est pas en anglais, l’app propose de l’exporter en anglais :

brusque détacher supplier lundi scalpel séance ouvrage injure sarcasme cubique retomber tituber

cause duty tool name strong sudden quick liquid stock destroy solid ugly

Donc tous les outils ne sont pas obligés de l’implémenter, auquel cas il suffit aux gens de l’exporter en anglais pour devenir interprétable avec tous les outils crypto de la planète.


Concernant l’usage, ça m’a été demandé plusieurs fois lors de tests de Gecko par des junistes : « pourquoi c’est en anglais ? ». Les gens se demandent pourquoi choisir l’anglais et pas une autre langue.

Même si, dans la majorité des cas, les gens ne la retiennent pas, ça rassure de voir cette phrase dans leur langue, dans un processus déjà pas évident à faire comprendre, qui peut faire peur.

5 Likes