Certains ont peut-être suivi mes échanges rapprochés avec @cgeek lors des RML14 concernant un écart entre Dunitrust et Duniter sur la génération des signatures et leur vérification.
Afin de ne pas créer d’inquiétudes inutiles, j’attendais de découvrir le fin mots de l’histoire avant de communiquer sur le sujet.
Après de nombreuses fausses pistes, des dizaines d’heure de recherche et de tests, un gros plongeon dans le C et son binding avec Rust (j’avais oublié à quel point c’est moche et chiant a gérer le C ), j’ai enfin trouvé le fin mots de l’histoire, et j’ai une mauvaise nouvelle comme le titre vous le fait deviner.
Dans Duniter, cgeek utilise un binding custom de tweetnacl-usable. Le problème avec les binding custom c’est que l’on ne bénéficie pas des correctif.
Or, le 16 février 2015, le dépôt tweetnacl-usable a été mis a jours pour intégrer un correctif d’un bug dans TweetNaCl : updated to latest tweetnacl · ultramancool/tweetnacl-usable@a8dcaa7 · GitHub
Cet update est cassant et change le comportement. J’ai bindé en Rust les 2 versions du dépôt tweetnacl-usable (a8dcaa7 avec correctif et 9a160106 sans correctif).
La version a8dcaa7 avec correctif a exactement le même comportement que les 4 autres lib de crypto que j’ai testé, a savoir: ring, cryptoxide, rust-crypto et sodiumoxide (oui j’en ai pris 4 pour être vraiment sûr). Le comportement étant : environ une signature sur 15000 est invalide dans la blockchain g1 (toujours les mêmes pour chaque lib).
A savoir que certaines signatures invalides correspondent a des blocs que j’ai forgé moi-même, notamment le #15144, j’en ai donc profité pour re-signer ce bloc avec Dunitrust :
Duniter signature : fJusVDRJA8akPse/sv4uK8ekUuvTGj1OoKYVdMQQAACs7OawDfpsV6cEMPcXxrQTCTRMrTN/rRrl20hN5zC9DQ==
Dunitrust signature (avec tweetnacl-usable a8dcaa7, + 4 autres lib de crypto) : aZusVDRJA8akPse/sv4uK8ekUuvTGj1OoKYVdMQQ/3+VMaDJ02I795GBBaLgjypZFEKYlPMssJMn/X+F/pxgAw==
Dunitrust signature (avec tweetnacl-usable 9a160106) :
fJusVDRJA8akPse/sv4uK8ekUuvTGj1OoKYVdMQQAACs7OawDfpsV6cEMPcXxrQTCTRMrTN/rRrl20hN5zC9DQ==
J’ai réussi a binder la version 9a160106 sans correctif (intégrée dans Duniter), et Dunitrust a alors la même anomalie, ce qui lui permet d’être parfaitement ISO avec Duniter.
Mais utiliser une ancienne version buggée de TweetNaCl n’est pas envisageable sur le long-terme, personne* ne s’en ai rendu compte en 2 ans et demi car cela ne concerne qu’une signature sur 15000 et que seuls les serveurs blockchain vérifient les signatures, les clients se contentent de les émettre, et générer un document sur 15000 qui ne passe pas ça peut passer inaperçu longtemps.
*En fait si, junidev s’en est forcément rendu compte en développant Juniter puisqu’il vérifiait les signatures, d’ailleurs @cgeek tu m’a bien dit aux rml14 que “Junidev avait rencontré le même problème”. Il semble s’être contenté de se baser sur le même code C que Duniter sans creuser le pourquoi du comment, car il n’aurait pas du avoir de problème (et moi non plus).
Je me rend compte que le développement de Dunitrust vas être l’occasion de faire un audit au peigne fin de Duniter, pour chaque écart constaté je ne vais pas me contenter de copier Duniter pour que ça marche, je vais a chaque fois chercher a comprendre le pourquoi du comment de chaque écart.
Cela permettra a terme d’avoir beaucoup plus confiance en le fait que les serveurs blockchain font bien ce qu’il sont censés faire.
La blockchain Ğ1 n’est pas conforme au standard Ed25519 et tôt ou tard d’autres s’en rendrons comptes.
De plus, il n’est pas envisageable pour moi d’utiliser une lib de crypto buguée et non auditée (l’audit de TweetNaCl ayant eu lieu après le correctif).
Ça me pose aussi des problèmes de performances, TweetNaCl étant une implémentations de Ed25519 assez lente.
Proposition a court-terme
Ma proposition : Intégrer les 2 versions de tweetNaCl dans Duniter, réaliser un passage en V12 coordonné.
Proposition à moyen-terme
Une fois que les réseaux ĞT et Ğ1 seront en V12, ne plus vérifier la signature des blocs V10 et V11 (ce n’est déjà pas vérifié en sync rapide de toute façon).
La sync vérifiant tout les hashs, et la signature du bloc genesis étant reconnu valide dans les 2 versions de TweetNaCl, on pourra maintenir la vérification de la signature du bloc genesis en mode cautious pour conserver une garantie sur l’origine.
Dunitrust ne vérifiera les signatures que en V12 directement.
J’ai quelques questions pour les développeurs des clients @Moul @vit @kimamila : quelle lib de crypto utilisez vous ? N’avez vous jamais essayer de vérifier les signatures des blocs ? Pouvez vous essayer de vérifier la signature du bloc #15144 avec votre lib de crypto ?
message:
InnerHash: 8B194B5C38CF0A38D16256405AC3E5FA5C2ABD26BE4DCC0C7ED5CC9824E6155B\nNonce: 30400000119992\n
pubkey: D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx
sig: fJusVDRJA8akPse/sv4uK8ekUuvTGj1OoKYVdMQQAACs7OawDfpsV6cEMPcXxrQTCTRMrTN/rRrl20hN5zC9DQ==