De l'idée à la mise en œuvre: nous modifions le schéma de signature numérique existant sur une courbe elliptique afin qu'il soit déterministe, et nous fournissons sur sa base les fonctions d'obtention de nombres pseudo-aléatoires vérifiés au sein de la blockchain.

Idée
À l'automne 2018, les premiers contrats intelligents ont été activés sur la blockchain Waves, immédiatement la question s'est posée de la possibilité d'obtenir des numéros pseudo-aléatoires auxquels vous pouvez faire confiance.
Briser la tête sur cette question, je suis finalement arrivé à la conclusion: toute blockchain est une cellule, il est impossible d'obtenir une source fiable d'entropie dans un système fermé.
Mais j'aimais toujours une idée: si un oracle aléatoire fait de la signature des données utilisateur un algorithme déterministe, l'utilisateur sera toujours en mesure de vérifier une telle signature avec la clé publique et sera sûr que la valeur reçue est unique. L'oracle, avec tout le désir, n'a aucun pouvoir de changer quoi que ce soit, l'algorithme produit un résultat clair. En fait, l'utilisateur capture le résultat, mais ne le sait pas jusqu'à ce que l'oracle le publie. Il s'avère que vous ne pouvez pas du tout faire confiance à l'oracle, mais vérifiez le résultat de son travail. Ensuite, dans le cas d'une vérification réussie, une telle signature peut être considérée comme une source d'entropie pour un nombre pseudo-aléatoire.
La plate-forme blockchain Waves utilise le schéma de signature EdDSA, une variante de Ed25519 . Dans ce schéma, la signature se compose des valeurs de R et S, où R dépend d'une valeur aléatoire, et S est calculé sur la base du message en cours de signature, de la clé privée et du même nombre aléatoire que R. Il s'avère qu'il n'y a pas de dépendance un à un pour le même Un message personnalisé possède de nombreuses signatures valides.
De toute évidence, dans sa forme pure, une telle signature ne peut pas être utilisée comme source de nombres pseudo-aléatoires, car elle n'est pas déterministe et, par conséquent, peut facilement être sujette à manipulation par l'oracle.
Mais, comme il s'est avéré, le rendre déterminé est en fait possible.
J'avais de grands espoirs pour une fonction aléatoire testée (VRF) , mais après avoir étudié le matériel, j'ai dû refuser cette option. Bien que VRF propose une version déterministe de la signature et de sa preuve, l'algorithme a une place étrange qui ouvre un trou noir pour manipuler l'oracle (il s'agit d'une déclaration incorrecte, voir Mise à jour ). À savoir, lors du calcul de la valeur de k ( section 5.1 ), une clé privée est utilisée, qui reste inconnue de l'utilisateur, puis l'utilisateur ne peut pas vérifier l'exactitude du calcul de k, puis l'oracle peut utiliser n'importe quelle valeur de k dont il a besoin et en même temps maintenir une base de données de correspondances k et les données signées toujours pouvoir recalculer le résultat correct du point de vue du VRF. Vous verrez un tirage basé sur VRF sans divulguer la clé privée, vous pouvez y penser: souligner le besoin ou ouvrir la clé, ou l'exclure du calcul de k, puis la clé privée s'ouvrira automatiquement lorsque la première signature apparaît. En général, comme déjà mentionné, un schéma étrange pour un oracle aléatoire.
Avec un peu de réflexion et l'obtention du soutien d'analystes locaux, le workflow VECRO est né.
VECRO est l'abréviation de Verifiable Elliptic Curve Random Oracle, qui en russe signifie un oracle aléatoire vérifié sur les courbes elliptiques.
Tout s'est avéré assez simple, pour atteindre le déterminisme, il faut fixer la valeur de R avant l'apparition d'un message signé. Si R est fixe et fait partie d'un message signé, ce qui garantit en outre que R est fixe dans le message signé lui-même, la valeur de S est uniquement déterminée par le message utilisateur et, par conséquent, peut être utilisée comme source de numéros pseudo-aléatoires.
Dans un tel schéma, peu importe la façon dont R est fixé, il reste dans la zone de responsabilité de l'oracle. Il est important que S soit uniquement déterminé par l'utilisateur, mais sa valeur est inconnue jusqu'à ce que l'oracle le publie. Tout ce que nous voulions!
En parlant de R fixe, notez que R réutilisé lors de la signature de divers messages révèle uniquement la clé privée dans le schéma EdDSA. Pour le propriétaire de l'oracle, il devient extrêmement important d'exclure la possibilité de réutiliser R pour signer différents messages utilisateur. Autrement dit, lors de toute manipulation ou complot, l'oracle risque toujours de perdre sa clé privée.
Au total, l'oracle devrait fournir aux utilisateurs deux fonctions: l'initialisation, qui fixe la valeur de R, et une signature, qui renvoie la valeur de S.De plus, la paire R, S est une signature vérifiée régulière d'un message utilisateur contenant une valeur fixe de R et des données utilisateur arbitraires.
On peut affirmer que ce schéma pour la blockchain n'est rien de plus qu'un schéma normal de validation et de divulgation . En fait, oui, c'est elle. Mais il y a quelques nuances. Premièrement, l'oracle fonctionne toujours avec la même clé dans toutes les opérations, par exemple, il est pratique à utiliser dans les contrats. Deuxièmement, il y a un risque de perdre la clé privée par l'oracle en raison d'un comportement incorrect, par exemple, l'oracle vous permet de faire des échantillons du résultat, puis il suffit de faire seulement deux tests pour découvrir la clé privée et obtenir un accès complet au portefeuille. Troisièmement, la signature qui est vérifiée nativement dans la blockchain, qui est une source de hasard, est belle.
Pendant six mois, l'idée de mise en œuvre était dans ma tête, jusqu'à ce qu'il y ait finalement une motivation sous la forme d'une subvention de Waves Labs . Avec une subvention importante, une grande responsabilité vient, ce qui signifie que le projet sera!
Implémentation
Ainsi, dans ce projet, VECRO a été implémenté sur la blockchain Waves en mode requête-réponse en utilisant des transactions de transfert entre l'utilisateur et l'oracle. Dans le même temps, un script est installé sur le compte Oracle qui surveille le fonctionnement strictement conformément à la logique décrite ci-dessus. Les transactions Oracle sont vérifiées pour restaurer l'intégralité de la chaîne d'interaction utilisateur. Les quatre transactions participent à la vérification de la valeur finale, le contrat intelligent les a fixées sur un fil de vérification strict, vérifiant pas à pas toutes les valeurs et ne laissant aucune place à aucune manipulation.
Encore une fois, à reporter et à clarifier. L'oracle ne fonctionne pas seulement selon le schéma proposé. Son travail est entièrement contrôlé au niveau de la blockchain par un contrat intelligent bien établi. Un pas à gauche, et la transaction ne fonctionnera tout simplement pas. Donc, si la transaction est tombée dans la blockchain, l'utilisateur n'a même pas besoin de vérifier quoi que ce soit, des centaines de nœuds de réseau ont déjà tout vérifié pour lui.
Pour le moment, un VECRO fonctionne sur le réseau principal Waves (vous pouvez exécuter le vôtre, ce n'est pas difficile, regardez simplement l'exemple de configuration ). Le code actuel fonctionne en PHP (dans WavesKit , dont j'ai parlé plus tôt ).
Pour utiliser le service Oracle, vous devez:
- Fix R;
- Envoyer un minimum de 0,005 vagues à l'alias Oracle init @ vecr;
- Obtenez le code R dans le champ de pièce jointe lors du transfert de 1 jeton R-vecr de l'oracle à l'utilisateur;
- Obtenez une signature
- Envoyez un minimum de 0,005 vagues à l'alias Oracle random @ vecr, et spécifiez TOUJOURS le code R précédemment reçu et les données utilisateur supplémentaires dans le champ de pièce jointe;
- Obtenez le code S dans le champ de pièce jointe lors du transfert de 1 jeton S-vecr de l'oracle à l'utilisateur;
- Utilisez le code S comme source de nombres pseudo-aléatoires.
Les nuances de la mise en œuvre actuelle:
- Les vagues envoyées à l'oracle sont utilisées comme une commission pour une transaction inverse à l'utilisateur, jusqu'à un maximum de 1 vagues;
- Le code R est la concaténation de l'octet du caractère «R» et de la valeur de 32 octets de R dans le codage base58;
- Le code R en pièce jointe doit être le premier, les données utilisateur viennent après le code R;
- Le code S est la concaténation de l'octet du caractère «S» et de 32 octets de la valeur S dans le codage base58;
- S est le résultat de la division modulo, vous ne pouvez donc pas utiliser S comme un nombre pseudo-aléatoire à 256 bits à part entière (ce nombre peut être considéré comme un nombre pseudo-aléatoire de 252 bits au maximum);
- L'option la plus simple consiste à utiliser le hachage du code S comme un nombre pseudo-aléatoire.
Un exemple d'obtention de code S:
D'un point de vue technique, l'oracle est complètement prêt pour le travail, vous pouvez l'utiliser en toute sécurité. Du point de vue de l'utilisation par un utilisateur ordinaire, une interface graphique pratique ne suffit pas, il faudra attendre.
Je serai heureux de répondre aux questions et d'accepter les commentaires, merci.
Mise à jour du 8 mai 2019
J'avais tort à propos de VRF. Oui, en effet, la signature ECVRF ne peut pas être utilisée comme source d'un nombre pseudo-aléatoire, mais elle n'est pas utilisée à cette fin. Une signature est nécessaire pour construire une preuve de l'unicité de la valeur Gamma ( section 5.3 , étape 6). Mais la valeur Gamma vérifiée à l'aide de la signature participe déjà comme source d'un nombre pseudo-aléatoire ( section 5.2 , étape 5). Merci à Oleg Taraskin Crittografo de l' avoir souligné à ce stade, j'avoue mon erreur. L'ECVRF a tous les droits à la vie.
Malheureusement, il n'y a toujours pas d'opportunité d'utiliser ECVRF au niveau de la chaîne de blocs Waves, en raison du manque de l'appareil mathématique nécessaire dans les contrats intelligents.
Lorsque cette fonctionnalité ou le support RSA devient disponible, vous pouvez écrire de nouveaux oracles. Quant au schéma VECRO, en tout cas, il occupe sa propre niche et vous permet de travailler sans aucune fonctionnalité supplémentaire.