Protocole pour les commentaires de transaction

J’ouvre ce sujet important.

  • Faut-il conserver cette fonctionnalité ?
  • Si oui, comment ? Sur quel stockage ?
  • Faut-il toujours du chiffrement ? Ou en option ?

Mes réflexions :

Utilité :

Stockage :

  • L’indexeur pourrait-il jouer ce rôle ? Faut-il passer par un événement Subtrate ?

Chiffrement :

  • Le chiffrement avec les clefs des deux parties (émetteur et destinataire de la transaction) présente un risque en cas de perte des identifiants. Il est alors impossible de retrouver les références de facture dans l’historique et la comptabilité devient aveugle.
  • Le chiffrement peut-être utile, mais en option. Avec le risque que les commentaires soient utilisés comme une messagerie chiffrée.
  • L’ anonymisation n’est elle pas préférable au chiffrement si on veut masquer des informations ?
2 Likes

On pourrait envoyer le commentaire à un indexeur en faisant référence à la transaction avec un hash.

La DHT rattachée à la blockchain risque d’être longue à développer, en attendant on peut faire un truc centralisé si on veut aller vite ?

Le wallet pourrait conserver les commentaires en local.

Il pourrait y avoir plusieurs méthodes de chiffrement :

  • aucun
  • clé publique
  • clé symétrique (les wallets doivent alors s’échanger des clés)

Les commentaires ne seraient pas limités aux transferts, mais à tout call. On pourrait indiquer par exemple son identité IRL sur une certification.

Le commentaire sera toujours signé par l’expéditeur, donc il peut y avoir des frais. L’indexeur peut exiger de réserver une somme proportionnelle au nombre de commentaires par jour, par exemple.

Il faut router les messages, donc faire le lien entre un message et son destinataire, et même à son expéditeur pour les frais. Pour anonymiser il faudrait passer soit par de la crypto ad hoc, soit du routage en oignons.

L’anonymisation sans chiffrement est risquée car il est facile de désanonymiser des données non standardisées (orthographe, habitudes, etc.).

1 Like

Je vois ce sujet un peu tard.

Avec @ManUtopiK nous proposons d’ajouter ces commentaires dans l’indexer v2s.
Ce champ est déjà présent pour les transactions importés depuis la blockchain Ğ1.

Il nous suffit de développer un plugin de vérification de signature pour insert de commentaire en DB via l’api GraphQL, de la même manière que Cs+ le fait pour ses données offchain.

Ceci est une solution simple et efficace, qui se passe de la complexité d’une DHT qui me semble non nécessaire avant la migration Ğ1.

Concernant le chiffrement, dans l’optique de garder cette migration KISS, je propose de ne pas chiffrer ces commentaires avant la migration, de manière à rester coller le plus possible au protocole DUBP actuellement en vigueur.

3 Likes

Je relance le sujet puisque ça concernera les datapods.

Je n’aborde pas les multisignatures ni le déchiffrement à seuil, c’est assez compliqué comme ça. (un jour !)

Niveaux de sécurité

Il y a plusieurs niveaux de sécurité adaptés à différents usages. Disons que A (Anatole) envoie un message M à B (Bernadette).

Notes :

  • Ce raisonnement s’étend à tout type de message, pas seulement aux commentaires de tx.
  • Je donne des cas d’usage non exhaustifs pour prouver la pertinence d’implémenter ces niveaux de sécurité.
  • La payload finale est nécessairement signée par A, pour satisfaire l’antispam.
  • sign(x) est le couple de x et de la signature de x par la clé privée de A.
  • crypt(x) est le chiffré de x pour la clé privée de B.

Signature à clé publique

Description : sign(A)

Propriétés : Tout le monde a la preuve que A a envoyé M à B, et que B y a accès. B a la preuve que le message est intègre (non modifié) et authentique (écrit par A).

Cas d’usage : dépenses d’une asso

Signature à clé publique + Chiffrement

Description : sign(crypt(sign(M)))

Propriétés : Idem, mais seule B connaît M. B peut révéler publiquement M et prouver que A en est l’auteur.

Cas d’usage : B n’a pas sollicité la transaction de la part de A, les deux ne se font pas confiance a priori. B peut donc accuser publiquement A de harcèlement ou autre, grâce à la signature.

La signature “extérieure” sert au datapod. Elle est suffisante pour que B puisse s’assurer de l’intégrité et de l’authenticité de M. La signature “intérieure” (qui n’est accessible qu’après déchiffrement) sert à B pour prouver publiquement l’authenticité et l’intégrité.

Il me semble dangereux d’autoriser des messages chiffrés sans cette signature “intérieure”, car cela permettrait du spam généralisé impossible à dénoncer preuve à l’appui.

Chiffrement authentifié

Description : Un échange de secret partagé K est nécessaire au préalable (Diffie-Hellman).
sign(AE(K, M))
(où AE(k, x) est le chiffrement symétrique authentifié par la clé k du message x, par exemple AES-AEAD)

Propriétés : Tout le monde sait que A a envoyé un message à B. Seule B connaît M ainsi que sa preuve d’intégrité et d’authenticité. B ne peut prouver à personne que A est l’auteur de M. La responsabilité de A n’est toujours pas prouvée même si la clé privée de B et K sont révélées. Si le chiffrement symétrique est bien choisi, un même K peut servir plusieurs fois.

Cas d’usage : Transaction d’ordre privé entre deux personnes se faisant au moins un peu confiance.

L’échange Diffie-Hellman peut prendre la forme d’une “demande de contact” dans l’UI. La demande contient un facteur, la réponse positive aussi. Le secret partagé peut soit être stocké chiffré dans un datapod, soit être conservé dans l’appareil, selon le besoin. On peut s’inspirer de Matrix qui permet de stocker ses clés dans l’appareil et de les partager avec ses autres appareils.

Suppression

On parlait des modalités de suppression des données à caractère personnel. Le cas d’une communication est particulier, car le destinataire pourrait aussi vouloir supprimer la donnée (ce qui pourrait aussi accuser réception), ou au contraire pourrait vouloir que A ne puisse pas effacer le message.

Dans le niveau Chiffrement authentifié, je ne vois pas de raison à l’interdire. Le message est de toute façon inutile à d’autres personnes que A et B. Aucune preuve publique n’est détruite par l’effacement.

Dans le niveau Signature à clé publique + Chiffrement :

  • si A efface avant réception par B, personne ne saura jamais M.
  • si A efface après réception par B, B pourra toujours prouver publiquement que A a dit M.
  • si B efface, cela peut-il gêner A ? (vraie question, je ne sais pas encore :wink: ) :question:

Dans le niveau Signature à clé publique : (raisonnement peu rigoureux, probablement sujet à plus de discussion)

  • si M a porté quelconque préjudice, alors il a été lu, et donc peu importe quand A le supprime, des gens ont la preuve qu’il a écrit M.
  • sinon, c’est un cas où la suppression par A ne devrait pas poser problème.
  • si B le supprime, alors A ne peut plus prouver qu’il avait écrit M à la date d’envoi, à moins qu’il puisse reconstruire le message d’origine et tomber sur le même cid (puisque le cid reste public après suppression il me semble). :question:

Dans certains cas il peut être utile que les datapods (ou d’autres services) signent tous les cid des contenus publiés, dès leur publication, si le timestamp est suffisamment récent. Cela permettrait de prouver que tel message n’a pas été publié a posteriori et antidaté. Cette preuve (signature d’une dizaine de membres différents) serait plus fiable que la simple règle de pin individuelle aux datapods.

3 Likes

Où est la métadonnée du destinataire ? Dans le cas d’un message non chiffré, j’imagine qu’elle est accessible en clair comme le message. Mais dans le cas d’un message chiffré, il faudrait qu’elle soit à la fois à l’intérieur et à l’extérieur pour que B puisse se limiter à essayer de déchiffrer tous les messages qui lui sont adressés plutôt que l’intégralité des messages présents dans le système qui pourraient aussi bien être chiffrés pour C.

De même, où est la métadonnée de l’émetteur qui permet de vérifier la signature du message (chiffré ou non) ?

S’il s’agit d’un commentaire de transaction en blockchain et que le document faire référence à cette transaction, on peut dériver émetteur et destinataire, mais s’il s’agit d’une donnée totalement hors chaîne, il faut les préciser dans le message.
Je pense que ces cas d’usage de messagerie chiffrée ne doivent pas se faire de manière publique car

  • soit les métadonnées émetteur et récepteur sont publiques, et quelqu’un qui écoute sur le réseau peut ajouter sa propre métadonnée timestamp, et ça me paraît assez sensible comme set de données dans le cas où des clés sont réutilisées plusieurs fois ou associées à des transferts non anonymisés
  • soit les métadonnées sont privées et ça demande trop de calcul parce qu’il faudrait vérifier la signature contre toutes les clés publiques connues pour espérer retrouver la clé publique émettrice (et ça ne fonctionne que si la clé publique est effectivement partagée publiquement), et il faudrait tenter de déchiffrer tous les messages pour trouver ceux qui nous sont adressés

C’est la raison pour laquelle je préfère dédier les datapods aux données publiques (donc le premier cas) et reposer sur un autre système pour ce qui est privé (je suis toujours mitigé sur une messagerie Cesium+ basée sur des datapods plutôt qu’un autre système comme xmpp).

S’il ne s’agit que du spam, je peux saturer ton historique de transactions avec des milliers de transactions de 1 centime de june. Si je veux joindre un message aux transactions, il faudra passer par un système de confiance ou de contrôle parce que je peux utiliser un oneshot account. Tu pourras montrer que tu as reçu du spam (et des Ğ1) mais ça pourra être difficile de remonter à l’auteur.


J’aurais plein de remarques à faire sur des différences entre théorie et pratique pour ce qui touche au harcèlement, je reviendrai plus tard sur ce sujet.

Pour les trois niveaux je supposais que les adresses de A et de B sont en métadonnées publiques. Pour un commentaire de transaction ce n’est pas un problème (c’est déjà public en blockchain). Il peut être intéressant d’essayer de les cacher dans le cas d’un autre type de message, si on veut l’autoriser.

Pour l’anonymat du destinataire, il lui suffit de donner à A une clé publique dédiée à la conversation, qui n’est pas reliée publiquement à B. Dans le cas d’un commentaire de transaction au niveau Chiffrement authentifié, c’est facile à implémenter, puisque la clé de destination peut être convenue lors de l’échange préalable.

Pour l’anonymat de l’émetteur, je ne vois pas encore d’autre moyen que les preuves zero-knowledge (comme zk-SNARKS) ou des comptes anonymes par GMixer.

Je comprendrais qu’on n’autorise que les messages liés à une transaction (les commentaires, donc) pour éviter de saturer les datapods avec de la messagerie instantanée. Dans ce cas je ne vois pas le problème à implémenter les deux niveaux avec chiffrement. Je pense même que les deux premiers niveaux ne devraient pas être implémentés si le troisième ne l’est pas.

Je ne parlais pas du spam par la quantité (aux conséquences techniques), dont on peut se protéger par d’autres moyens, mais d’un message présidentiel ou de calomnies (aux conséquences sociales, voire judiciaires).

L’utilisation de signature répond en théorie à la question de l’auteur du message mais en pratique :

  • même si on éduque à la vérification de la signature, en pratique les gens se contentent de captures d’écran totalement falsifiables (falsifier des preuves est dangereux d’un point de vue juridique)
  • même en cas de présence d’une signature, il est impossible de prouver que la clé privée n’avait pas fuité (le vol d’identité est également dangereux d’un point de vue juridique)

Ça me paraît peu rentable de déployer beaucoup d’énergie et d’ingéniosité pour une solution satisfaisante d’un point de vue théorique mais qui va finalement tomber à côté de la réalité du terrain. En gros tout ce qui touche au chiffrement est pour moi une problématique client plutôt R&D. Quand je pense à l’implémentation des commentaires de transaction je m’intéresse plutôt aux problématiques serveur pour stocker un message. Ce message peut être un hash, un cid ipfs, il peut pointer vers un serveur qui demande une authentification, etc. Et finalement ça ne change rien aux problématiques serveur mais uniquement à la manière dont le client récupérera et interprétera la donnée.

Donc toutes ces propositions sont intéressantes d’un point de vue théorique, mais tant qu’elles ne sont pas accompagnées d’une interface qui permet de comprendre de quoi il s’agit, elles concerneront un nombre très réduit de personnes. Je pourrais envoyer une référence vers le message suivant dans un commentaire de transaction mais on serait pas très avancés :

message

Message signé puis chiffré et signé pour la clé GPG publiée sur txmn.tk par la clé GPG publiée sur trentesaux.fr

> gpg --sign --armor msg.txt
> gpg --encrypt --sign --armor -r tuxmain@zettascript.org msg.txt.asc
-----BEGIN PGP MESSAGE-----

hQIMA3PAsmw1+QC3AQ/8CphRiShIUcG1XhZ/KgOoEp3ytiLXvvOG8J3SU9I/Q1+5
x+tagE5gLZrhraY8HuKYeZKxrQ+6jER63+w3sZ79NlM31F+7BBriosPyzg0IZCjA
fh/RhOhhNp4wVtT+R6VR+fPe8+5IFfCqm7LRvgYexLSXnbWWTPEcD4N1SKteSVXD
xf2Tjxoo3aovCrjlOiCOLidjKcShfPw709I20LEKMj8dkPhava6+2A0LgQbrC8qs
uMJczhOPDF6LhbG2GpdvvjeqPaT6ifqgaQ7kh6UgPFMwwCqXewdrHgmQ+JUlUajZ
UfEJgUmVenqOqmV/v5l9RwUjnMOgwtiY7LeIOw2k710zHMrdsSWA0izHfa2MIqEf
SbgE6k7dCLqyuFOhadh5wSAp8NXw6Txi7+G9v65eDFeQXfRk84C4CzD4K/v8+gaC
glMJok79dDVe6xgURZlW2/wgwtIJlcmcDK97InP33LmypyG+I3+Bv1DYPibusBL2
4u9Ka+1d1bW97xhtjHf8SXiopKsDkDJCrrAM0Ciefia4eGM+tYYnVPZ4E2RFJOFk
it5iapC1XOOmCpjPM4/OfFGkDeHzRFX9fanDtzVrFiVx57NWfn0DnHAeUbEmsKsE
5BDcRxrlBzJOeX4IET1hoE96PS7/C4FWWlO0rcY5TfpzlyCyijc5CWXrQcc3597S
wQYBba1mtO/J8UEdLjcZcColwRQpr23XR0Upv1ttfr2NLnJn6Ftcghg9vHe+uj6q
rGDYyy1OIiVpamfbUsYg5FGkeCJukTYU5MwcgFm26TG7E8TvuV4NpV7LQDzerQ19
K4vGA5s8v4CkoRhZI2h0jgfiHdeEqxHyCvaYZA1ml2ZAcpPWUZLO6pF+QcaSTqLr
1me+mQrs8GHJg8cYoBqILw7OTJ9kSDH157Pib5h/dqeU7YZJCea3mDu8jHsl9ACI
D03YVnU1I7ptHKbhP/IyF4AzNfZDJA6xfAiTH9s/aIrCzNFPtO2wb98AqMWbiJxr
CDJjFTdtmTLWMR4xCevA+GYhXrxmGO9bW0RpJnQ7JYzpvSBGV3cO+DkGkBCjWtz0
SNvO/xg8bS8HGaYFy+JfhDvwr9k3+AZb8/h2O8OdTX4A9WSNdOvVgQQ2lIG+SoVB
/ATw6l2vcyzOR7nBgbp5ZcGDMkcflAUYMYFLRPlX3AGtYrjbbpLylitj9OqU2hmW
2Cuyxi2hMDBmdipDNV5k8hNon0i7ypQPfMwPihbd6E7yppQS6BrM+sz2u6yLJIaT
T3wzPefOmiepzXwhoPUPROuE1Kc1YRUc
=waU4
-----END PGP MESSAGE-----

Donc on voit bien que la question n’est pas de proposer des protocoles (ils existent pour la plupart déjà) mais d’apporter ces fonctionnalités à l’utilisateur dans un format qu’il comprend, en respectant ses libertés, et en le protégeant de ceux qui abusent des leurs.

Même si le gros du travail est côté client, il faut s’assurer que les protocoles choisis n’empêchent pas aux clients d’implémenter les sécurités voulues. Et comme on parle de protocole, il ne suffit pas de dire que c’est l’affaire des clients, il faut définir un protocole commun. Choisir de n’implémenter que les commentaires signés en clair est déjà un choix de protocole.

Bien sûr toutes les fonctions que je décris doivent être accompagnées d’une UI adéquate et de valeurs par défaut selon la situation, choisies par le dev du client, pour que dans la plupart des cas, l’utilisateur n’ait pas à se poser de question.

Il est aussi facile d’accuser d’avoir falsifié une capture d’écran. La signature permet de s’en défendre.

On peut aussi penser aux applications commerciales où la transaction fait partie d’un contrat, pour lequel confidentialité et preuve de responsabilité sont nécessaires.

Ok, dans ce cas pas de problème, mais ça ne fait que déplacer le problème d’un protocole vers un autre.

J’ai l’impression qu’on a bien avancé sur la question depuis… un an gloups.

Faut-il conserver cette fonctionnalité ? :arrow_right: oui, c’est important ça fait partie des fonctionnalités appréciées de la Ğ1 et beaucoup de réflexions aboutissent non seulement à la nécessité de conserver cette fonctionnalité mais également de la soumettre au consensus de la blockchain.

Si oui, comment ? :arrow_right: on publie en blockchain un CID (un hash avec des informations supplémentaires sur son encodage et l’algorithme de hachage utilisé).

Sur quel stockage ? :arrow_right: si le message est suffisamment court, il peut être inliné dans le CID. Exemple :

> ipfs add --only-hash --inline
ipfs: Reading from /dev/stdin; send Ctrl-d to stop.
message court
added bafyaafqkcqeaeeqonvsxg43bm5ssay3povzhicqyby
 14 B / 14 B [======================================] 100.00%
> ipfs cat bafyaafqkcqeaeeqonvsxg43bm5ssay3povzhicqyby
message court

Si le message est trop long, le CID est uniquement un hash et il faut stocker la donnée ailleurs. Ça tombe bien, j’ai créé les Datapods ipfs justement pour ça ! Il faut soumettre une demande d’indexation (IndexRequest) via au choix :

  • IPFS+pubsub directement (c’est décentralisé)
  • un relais HTTP qui se charge de soumettre sur IPFS+pubsub à notre place

À partir de là, le réseau Datapod se charge d’épingler les commentaires de transaction.

Faut-il toujours du chiffrement ? Ou en option ? :arrow_right: il n’est pas possible de forcer le chiffrement côté serveur, ça se jouera côté client. On peut éventuellement chiffrer mais pour des clés connues de tous, mais ça n’a pas d’intérêt, autant laisser en clair ce qui gagne à être en clair ! La transparence pour les associations est un aspect très apprécié et auquel je tiens personnellement !

Faut-il passer par un événement Subtrate ? :arrow_right: Oui, c’est la bonne manière pour transmettre une information au monde extérieur.

L’indexeur pourrait-il jouer ce rôle [stockage] ? :arrow_right: Non, l’indexeur duniter-squid est conçu comme un logiciel centralisé dont la seule source de donnée est Duniter. On peut éventuellement faire un service qui se branche sur l’indexeur (type datapod) et qui va remplir le champ “commentaire” par le contenu du CID sous certaines conditions (assez léger notamment, mais peut-être aussi format connu). Cela permettrait de récupérer les commentaires (pas seulement leur CID) au même endroit que les transactions elles-mêmes plutôt que via IPFS ou une passerelle IPFS. Tout l’intérêt va être les filtres graphql qu’on va faire sur ces commentaires.


Voilà, j’ai l’impression d’avoir enfin des réponses propres à toutes ces questions !!

2 Likes

ce que j’ai compris des interactions de ce topic et conclusions d’hugo, c’est que le chiffrement de ces données apportait plus de questionnements que de solutions, mais qu’il y avait peut-être une autre façon de répondre au besoin. A savoir “disposer de l’option de rendre une transaction anonyme”.

Car ce besoin est légitime, et pour des raisons qui ne regardent personne en rien. Si la fonction existe ce sera un beau cadeau.

En contrepartie, comme les clients de la v1 n’offrent pas cette fonction, il n’est pas d’urgence mvp pour la v2, à mes yeux. Ce sera même un des add-on de la v2 du coup, le cadeau de la v2.03 ;-).
[ RQ : déjà ceux qui gravent dans le marbre tombal de la blockchain une insulte dans l’historique des transactions d’une cible, ne pourront plus le faire. Bonus :+1:

1 Like

Point de vue blockchain, c’est déjà possible onchain en v1 malgré certaines contraintes (cf les discussions sur le quand et le comment). Comme il faut réfléchir à comment implémenter les commentaires de transaction dans la blockchain v2, autant réfléchir à une manière de le faire qui ne réintroduise pas les mêmes contraintes. En soi on pourrait déjà décaler les commentaires de transaction en offchain dès la v1, mais ça nécessiterait un travail sur les outils v1 recyclable en v2 que partiellement. Je viens de t’envoyer une transaction pour démontrer ça. Si tu as suivi mes histoires de pagu.re/ipfs tu devrais comprendre :wink:

À mon avis le débat n’est pas tellement sur le chiffré / non chiffré mais plutôt sur le onchain / offchain. Et pour ce qui est du onchain, souhaite-t-on permettre la donnée elle-même, ou forcer la limitation à une référence ? Les réflexions sur ce qui sera proposé par défaut côté client alimentent la conception de l’aspect serveur.

Actuellement je me dirige vers une solution où tout est possible, c’est-à-dire à la fois onchain et la donnée elle-même, pas une simple référence. Mais même si c’est possible, ce qui sera proposé dans les clients grand public sera de mettre une simple référence onchain, ce qui élimine par ailleurs toute contrainte sur la question du chiffrement. Seuls les clients avancés proposeront de mettre la donnée elle-même onchain, mais ce sera en connaissance de cause (pas de possibilité d’oubli).

J’avais compris le contraire. Que nous protégions la blockchain de l’injection de chaînes libres. Ce qui me paraissait sage.

Même si pour interdire les chaînes libres il faut que la blockchain ne soit pas agnostique de la donnée hash/cid qui est ajoutée. Pour pouvoir la vérifier et la rejeter si ce n’est pas un hash/cid reconnu.

Pour info, est-ce que substrate permet le stockage on block/on chain de chaîne libre dans les pallets par défaut ?

C’est mort, on a déjà les pseudos pour les identités, qui sont des chaînes libres. Il y a aussi les signatures custom pour la révocation et le changement de clé.

On pourrait vérifier que le commentaire est un cid bien formé, ce qui n’empêche pas d’y mettre des octets arbitraires après son entête.

Pour empêcher les chaînes arbitraires d’une manière sémantique (impossibilité de coder de l’information arbitraire en blockchain), il faut que le hash soit généré par le runtime à partir de données non-contrôlables, comme le random id. Ce n’est pas possible si on veut référencer une donnée existante. (le commentaire IPFS devrait alors référencer le bloc, plutôt que l’inverse)

Je viens de tester (bloc 1650560), setSessionKeys peut être appelé par n’importe qui même sans identité, pour écrire bonjour au prix de 40 centimes.

2 Likes

Comme dit tuxmain, ce ne sera pas le cas. Une blockchain est de toute façon une ressource partagée qui laisse une certaine liberté quant à son utilisation.

Pas besoin d’aller jusque là, on peut tout simplement utiliser system.remark(), cf mes avancées sur Implémentation des commentaires de transaction.

Donc réponse : oui. Mais par “stockage” on entend juste “dans un bloc”. Pas de raison de mettre dans le onchain storage des choses qui ne sont pas utiles à l’exécution du runtime.

Cf la longue discussion sur le sujet Options pour gérer les commentaires de transaction côté serveur - #17 by vit que j’ai essayé de résumer dans Élagage de l'état, élagage des blocs, noeuds archive et miroir. Si les incompréhensions sont liées à la documentation substrate, c’est en cours de correction : Rephrase networks-and-nodes.md documentation by Hugo-Trentesaux · Pull Request #2153 · substrate-developer-hub/substrate-docs · GitHub.

1 Like

Pas forcément, le protocole pourrait définir qu’un bloc valide doive respecter un certain format interdisant les chaînes arbitraires.

Ça ne compte pas, il ne sera que dans les monnaies de test.

Ah bon ? Et si on veut s’en servir pour les commentaires de transaction ? C’est vrai que pour l’instant elois l’a interdit :

pub struct BaseCallFilter;
impl Contains<RuntimeCall> for BaseCallFilter {
    fn contains(call: &RuntimeCall) -> bool {
        !matches!(
            call,
            RuntimeCall::System(
                frame_system::Call::remark { .. } | frame_system::Call::remark_with_event { .. }
            ) | RuntimeCall::Session(_)
        )
    }
}

Mais y a-t-il une raison ?