Comment chiffrer les commentaires de transactions on chain

Je suis d’accord, et puis comme vu avec @matograine , la RFC actuelle permet déjà de mentir sur la longueur réelle du commentaire si on le souhaite, donc certains clients avancés pourraient exposer cette fonctionnalité, mais pour le grand public ça me semble overkill.

L’idée c’est que ce champ ne soit évidemment pas rempli par un humain. Je trouve juste qu’il peut être bien qu’un programme émettant des transactions avec commentaire (par exemple ğmixer) puisse indiquer que le commentaire n’est pas destiné à être lu par un humain.
Disons que ce champ pourrait devenir un booléen pour indiquer si le commentaire doit être affiché par défaut ou non, et que dans les cas de saisie humaine il vaudrait toujours «oui le commentaire doit être affiché».

Dans le cas où le champ vaut non, le logiciel client pourrait quand même afficher le commentaire mais ne l’afficherait pas dans la vue historique, il faudrait cliquer sur le détail de la transaction pou en voir le commentaire. Ça permettrait au logiciel client de ne déchiffrer que les commentaires pertinents dans la vue historique, tout en permettant de voir dans tous les cas le commentaire d’une transaction en allant dans la vue détaillée de cette transaction.

Su on part sur scrypt ça risque d’être long de déchiffrer plusieurs dizaines de commentaires dans la vue « historique de mon compte ». C’est pour cela que je préférerai qu’on utilise PBKDF2 au lieu de scrypt, c’est une KDF bien plus rapide à calculer, et qui reste d’une sécurité satisfaisante pour le chiffrement d’un commentaire.
La seule raison pour laquelle j’ai choisi scrypt dans la RFC c’est pour limiter les nouvelles primitives cryptographiques par encore utiliser par les logiciels clienets existants pour permettre aux développeurs des clients d’implémenter la RFC plus facilement )

Mais si vous êtes tous ok pour du PBKDF2, on peut swtcher dessus :slight_smile:

En fait c’est R = crypto_box_beforenm(Sb, Pa) je viens de corriger :slight_smile:

crypto_box_beforenm est une fonction officielle de la lib C NaCl, si ton binding ne l’expose pas, il faut ouvrir une issue ou/et utiliser un autre binding.

1 Like

crypto_box_beforenm est bien disponible dans la lib Python Libnacl. J’ai ignoré la fonction beforenm pour tester, en me disant à juste titre que c’était une typo, et j’ai un problème. Il faut que j’investigue. Je te demanderai peut-être des valeurs intermédiaires sur un exemple pour déboguer.

[EDIT] POC réussi en Python !

2 Likes

@vit il y a un truc que j’ai oublié de préciser dans la RFC, c’est qu’il faut transformer les clés Ed25519 en clés x25519, parfois aussi nommées trop vaguement curve25519. Il s’agit en fait de passer de la représentation d’ Edwards a celle de Montgomery.

Pour les clés publiques, je vois que tu fais déjà ça dans duniterpy avec la fonction crypto_sign_ed25519_pk_to_curve25519 :slight_smile:

Pour les clés privées, il faut transmettre directement le scalaire, soit les 32 premiers octets de la clé privée étendue. Je vais mettre à jour la RFC :wink:

EDIT: c’est fait.

1 Like

Je viens de complètement refondre la RFC:

  • Remplacement du préfixe par deux nouveaux champ: magicValue et version. L’idée est de répondre proprement et séparément aux 2 besoins suivant:
    • Besoin de reconnaître de quel format il s’agit: assuré par le champ magicValue
    • Besoin de versionner le format pour pouvoir le faire évoluer: assuré par le champ version
  • Passage à la base64 sans padding afin de gagner 2 octets.
  • Déplacement du champ messageLength dans la partie chiffrée, et renommage en realMessageLength.
  • Ajout d’un champ facultatif randomExtraBytes, permettant de brouiller la longueur réelle du message sans trop alourdir la blockchain. L’idée est de rajouter un nombre aléatoire d’octets en trop au lieu de remplir nécessairement les 255 caractères autorisés par DUBP, afin que l’impact du brouillage sur le poids de la blockchain soit allégé.
  • Suppression du caractère séparateur \0, devenu inutile grâce au fait que la longueur réelle du message est désormais chiffrée.
  • Développement plus précis de l’algo de lecture, et ajout de l’algo d’écriture.

@kimamila @vit @Moul @tuxmain et qui veut, pouvez-vous lire cette nouvelle version de la RFC et me faire part de vos retours ?

Si les retours sont positifs, je coderai une implémentation afin de pouvoir ajouter des exemples avec des vraies données :slight_smile:

Je ne peux pas faire l’implémentation car il y a des erreurs dans la RFC :

La structure des données est censée être :

Magic value Version Message type Salt Real message length Encrypted UTF8 message Random extra bytes
0x27b6 0x01 1 byte 16 bytes 1 byte (encrypted) Any bytes Any bytes

Mais la procédure de chiffrement qui suit contredit cela :

  • Il y a un nonce de 12 octets qui ne sert nulle part et qui n’est pas déclaré dans la structure.
  • Il y a n’y a pas la création du salt de 16 octets présent dans la structure et qui pourtant sert à la commande scrypt.

Je pense que le salt et le nonce sont la même chose, mais leurs tailles diffèrent…

1 Like

Non la taille est la même, c’est une typo. Le nonce est bien la même chose que le salt. C’est un salt du point de vue de scrypt et un nonce du point de vue de notre chiffrement :slight_smile:

1 Like

Dans le tableau de description des datas, tu précises que la taille réelle du message est un octet chiffré.

Or il n’ est pas du tout chiffré dans le tuto de chiffrement. Par contre il est bien extrait de la partie chiffrée dans le tuto de déchiffrement.

Les phases de chiffrement incorrectes :

  1. Push the byte l in b → doit être fait avant le chiffrement
  2. Append m to bencryptedMessaget o b

Bref il faut que tu corriges et relise le tout.

C’est corrigé :slight_smile:

1 Like

Implémentation Python faîtes et fonctionnelle ! C’est OK pour moi ! :wink:

Je vais refaire une relecture pour typos et une MR si besoin.

1 Like

Génial, pour une fois ça peut être toi qui écris des données d’exemple et moi qui essaye de les reproduire :slight_smile:

1 Like

Implémentation faite également ce jour et fonctionnelle avec les données de test que tu a fourni dans la MR :partying_face: :smiley:

2 Likes

L’implémentation est déjà dans une MR (en mode Draft, donc encore modifiable) de DuniterPy :

Attention, pour les Pythonistas qui veulent bidouiller une implémentation, la RFC demande d’utiliser la fonction crypto_sign_ed25519_seed_keypair, mais il faut utiliser la fonction de la libnacl crypto_box_seed_keypair au lieu de crypto_sign_seed_keypair pour que cela fonctionne.

C’est pas réservé aux pythonites c’est moi qui me suis trompé en cherchant quelle fonction NaCl vous deviez utiliser, car je n’utilise pas NaCl mais une lib pur rust dédiée à la cryptographie sur courbes elliptiques dont l’API ne ressemble en rien à NaCl.

Après vérification en lisant le code source en C de NaCl, je confirme que c’est bien crypto_box_seed_keypair que vous devez utiliser et non pas crypto_sign_seed_keypair :slight_smile:

EDIT: @vit merci pour ta MR qui ajoute des données d’exemple, je l’ai mergé manuellement après avoir squash tes commits :slight_smile:

Et j’arrive également à reproduire sans problème tes nouvelles données d’exemple, ça sent bon :grin:

EDIT2: À ce stade la RFC 17 n’est plus un brouillon, elle est finalisé et passe au stade « under discussion » :slight_smile:

2 Likes