10. Considérations de sécurité
Cette section contient des considérations de sécurité supplémentaires sur les mécanismes de hachage vers courbe décrits dans ce document.
10.1. Propriétés des encodages
Chaque type d'encodage (section 3) accepte une chaîne d'octets arbitraire et la mappe vers un point sur la courbe échantillonné à partir d'une distribution qui dépend du type d'encodage. Il est important de noter que l'utilisation d'un encodage non uniforme ou l'évaluation directe de l'un des mappages de la section 6 produit une sortie qui est facilement distinguable d'un point aléatoire uniforme. Les applications qui utilisent un encodage non uniforme DEVRAIENT analyser soigneusement les implications de sécurité de la non-uniformité. Lorsque l'encodage requis n'est pas clair, les applications DEVRAIENT utiliser un encodage uniforme.
Les deux encodages donnés dans la section 3 peuvent produire l'élément identité du groupe G. La probabilité que l'une ou l'autre fonction d'encodage produise l'élément identité est d'environ 1/r pour une entrée aléatoire, ce qui est négligeable pour les courbes elliptiques cryptographiquement utiles. De plus, il est infaisable d'un point de vue calculatoire de trouver une entrée pour l'une ou l'autre fonction d'encodage dont la sortie correspondante est l'élément identité. (Ces deux propriétés sont valables lorsque les fonctions d'encodage sont instanciées avec une fonction hash_to_field qui suit toutes les directives de la section 5.) Les protocoles qui utilisent ces fonctions d'encodage ne DEVRAIENT PAS ajouter de cas spécial pour détecter et « corriger » l'élément identité.
Lorsque la fonction hash_to_curve (section 3) est instanciée avec une fonction hash_to_field qui est indifférenciable d'un oracle aléatoire (section 5), la fonction résultante est indifférenciable d'un oracle aléatoire ([MRH04] [BCIMRT10] [FFSTV13] [LBB19] [H20]). Dans de nombreux cas, une telle fonction peut être utilisée en toute sécurité dans des protocoles cryptographiques dont l'analyse de sécurité suppose un oracle aléatoire qui produit des points uniformément aléatoires sur une courbe elliptique. Comme Ristenpart et al. le discutent dans [RSS11], cependant, toutes les preuves de sécurité qui reposent sur des oracles aléatoires ne restent pas valables lorsque ces oracles sont remplacés par des fonctionnalités indifférenciables. Cette limitation doit être prise en compte lors de l'analyse de la sécurité des protocoles reposant sur la fonction hash_to_curve.
10.2. Hachage de mots de passe
Lors du hachage de mots de passe à l'aide de toute fonction décrite dans ce document, un adversaire qui apprend la sortie de la fonction de hachage (ou potentiellement toute valeur intermédiaire, par exemple la sortie de hash_to_field) peut être en mesure d'effectuer une attaque par dictionnaire. Pour atténuer de telles attaques, il est recommandé d'exécuter d'abord une fonction de dérivation de clé plus coûteuse (par exemple, PBKDF2 [RFC8017], scrypt [RFC7914], ou Argon2 [RFC9106]) sur le mot de passe, puis de hacher la sortie de cette fonction vers la courbe elliptique cible. Pour la résistance aux collisions, le hachage sous-jacent à la fonction de dérivation de clé doit être choisi selon les directives énumérées dans la section 5.3.1.
10.3. Exigences de temps constant
Des implémentations en temps constant de toutes les fonctions de ce document sont FORTEMENT RECOMMANDÉES pour toutes les utilisations, afin d'éviter les fuites d'informations via des canaux auxiliaires. Il est particulièrement important d'utiliser une implémentation en temps constant lorsque les entrées d'un encodage sont des valeurs secrètes ; dans de tels cas, des implémentations en temps constant sont REQUIRES pour la sécurité contre les attaques temporelles (par exemple, [VR20]). Lorsque des implémentations en temps constant sont requises, toutes les opérations de base et les fonctions utilitaires doivent être implémentées en temps constant, comme discuté dans la section 4. Dans certaines applications (par exemple, les systèmes embarqués), les fuites via d'autres canaux auxiliaires (par exemple, les canaux auxiliaires de puissance ou électromagnétiques) peuvent être pertinentes. La défense contre de telles fuites dépasse le cadre de ce document, car la nature de la fuite et la défense appropriée dépendent de l'application.
10.4. encode_to_curve : Distribution de sortie et indifférenciabilité
La fonction encode_to_curve (section 3) renvoie des points échantillonnés à partir d'une distribution qui est statistiquement éloignée de l'uniformité. Cette distribution est bornée approximativement comme suit : d'abord, elle inclut au moins un huitième des points de G, et ensuite, la probabilité de points dans la distribution varie d'au plus un facteur quatre. Ces bornes sont valables lorsque encode_to_curve est instanciée avec n'importe laquelle des fonctions map_to_curve de la section 6.
Les bornes ci-dessus sont dérivées de plusieurs travaux de la littérature. Plus précisément :
-
Shallue et van de Woestijne [SW06] et Fouque et Tibouchi [FT12] dérivent des bornes sur le mappage Shallue-van de Woestijne (section 6.6.1).
-
Fouque et Tibouchi [FT10] et Tibouchi [T14] dérivent des bornes pour le mappage SWU simplifié (sections 6.6.2 et 6.6.3).
-
Bernstein et al. [BHKL13] dérivent des bornes pour le mappage Elligator 2 (sections 6.7.1 et 6.8.2).
L'indifférenciabilité de encode_to_curve découle d'un argument similaire à celui donné par Brier et al. [BCIMRT10] ; nous esquissons brièvement cet argument comme suit. Considérons un oracle aléatoire idéal Hc() qui échantillonne à partir de la distribution induite par la fonction map_to_curve appelée par encode_to_curve, et supposons pour simplifier que la courbe elliptique cible a un cofacteur 1 (un argument similaire s'applique pour des cofacteurs non unitaires). L'indifférenciabilité est vérifiée s'il est possible de simuler efficacement l'oracle aléatoire « interne » dans encode_to_curve, à savoir hash_to_field. Le simulateur fonctionne comme suit : sur une nouvelle requête msg, le simulateur interroge Hc(msg) et reçoit un point P dans l'image de map_to_curve (si msg est identique à une requête antérieure, le simulateur renvoie simplement la valeur qu'il a donnée en réponse à cette requête). Le simulateur calcule ensuite les préimages possibles de P sous map_to_curve, c'est-à-dire les éléments u de F tels que map_to_curve(u) == P (Tibouchi [T14] montre que cela peut être fait efficacement pour les mappages Shallue-van de Woestijne et SWU simplifié, et Bernstein et al. montrent la même chose pour Elligator 2). Le simulateur sélectionne une de ces préimages au hasard et renvoie cette valeur comme la sortie simulée de l'oracle aléatoire « interne ». Par hypothèse, Hc() échantillonne à partir de la distribution induite par map_to_curve sur un élément d'entrée de F uniformément aléatoire, donc cette valeur est uniformément aléatoire et induit le point correct P lorsqu'elle est passée à travers map_to_curve.
10.5. Sécurité de hash_to_field
La fonction hash_to_field, définie dans la section 5, est indifférenciable d'un oracle aléatoire [MRH04] lorsque expand_message (section 5.3) est modélisé comme un oracle aléatoire. Étant donné que les preuves d'indifférenciabilité sont composables, cela est également vrai lorsque expand_message est prouvé indifférenciable d'un oracle aléatoire par rapport à une primitive sous-jacente qui est modélisée comme un oracle aléatoire. En suivant les directives de la section 5.3, les deux variantes de expand_message définies dans cette section répondent à cette exigence (voir aussi la section 10.6).
Nous esquissons très brièvement l'argument d'indifférenciabilité pour hash_to_field. Notez que chaque entier mod p que hash_to_field renvoie (c'est-à-dire chaque élément de la représentation vectorielle de F) est membre d'une classe d'équivalence d'environ 2^k entiers de longueur log2(p) + k bits, qui sont tous égaux modulo p. Pour chaque entier mod p que hash_to_field renvoie, le simulateur échantillonne un membre de cette classe d'équivalence au hasard et produit la chaîne d'octets renvoyée par I2OSP. (Notez que c'est essentiellement l'inverse de la procédure hash_to_field.)
10.6. Sécurité de expand_message_xmd
La fonction expand_message_xmd, définie dans la section 5.3.1, est indifférenciable d'un oracle aléatoire [MRH04] lorsque l'une des conditions suivantes est remplie :
-
H est indifférenciable d'un oracle aléatoire,
-
H est une fonction de hachage basée sur une éponge dont la fonction interne est modélisée comme une transformation aléatoire ou une permutation aléatoire [BDPV08], ou
-
H est une fonction de hachage Merkle-Damgaard dont la fonction de compression est modélisée comme un oracle aléatoire [CDMP05].
Pour les cas (1) et (2), l'indifférenciabilité de expand_message_xmd découle directement de l'indifférenciabilité de H.
Pour le cas (3), c'est-à-dire lorsque H est une fonction de hachage Merkle-Damgaard, l'indifférenciabilité découle de [CDMP05], théorème 5. En particulier, expand_message_xmd calcule b_0 en faisant précéder le message d'un bloc de zéros plus des informations auxiliaires (longueur, compteur et DST). Ensuite, chacun des blocs de sortie b_i, i >= 1 dans expand_message_xmd est le résultat de l'invocation de H sur un encodage unique et sans préfixe de b_0. Ceci est vrai, d'abord parce que la longueur de l'entrée de toutes ces invocations est égale et fixée par le choix de H et DST, et ensuite parce que chacune de ces entrées possède un suffixe unique (en raison de l'inclusion de l'octet de compteur I2OSP(i, 1)).
La différence essentielle entre la construction discutée dans [CDMP05] et expand_message_xmd est que cette dernière hache un compteur ajouté à strxor(b_0, b_(i - 1)) (étape 10 de la section 5.3.1) plutôt qu'à b_0. Cette approche augmente la distance de Hamming entre les entrées de différentes invocations de H, ce qui réduit la probabilité que des non-idéalités dans H affectent la distribution des valeurs b_i.
Nous notons que expand_message_xmd peut être utilisée pour instancier une fonctionnalité indifférenciable à usage général avec une sortie de longueur variable basée sur n'importe quelle fonction de hachage répondant à l'un des critères ci-dessus. Les applications qui utilisent expand_message_xmd en dehors de hash_to_field devraient assurer la séparation de domaine en choisissant une valeur distincte pour DST.
10.7. Séparation de domaine pour les variantes expand_message
Comme discuté dans la section 2.2.5, le but de la séparation de domaine est de garantir que les analyses de sécurité des protocoles cryptographiques qui interrogent plusieurs oracles aléatoires indépendants restent valables même si tous ces oracles aléatoires sont instanciés sur la base d'une seule fonction sous-jacente H.
Les variantes expand_message de ce document (section 5.3) assurent la séparation de domaine en ajoutant une étiquette de séparation de domaine encodée sans suffixe DST_prime à toutes les chaînes hachées par H, un hachage sous-jacent ou une fonction à sortie extensible. (On s'attend à ce que d'autres variantes de expand_message qui suivent les directives de la section 5.3.4 se comportent de manière similaire, mais celles-ci devraient être analysées au cas par cas.) Pour la sécurité, les applications qui utilisent la même fonction H en dehors de expand_message devraient imposer une séparation de domaine entre ces utilisations de H et de expand_message, et elles devraient séparer toutes celles-ci des utilisations de H dans d'autres applications.
Cette section suggère quatre méthodes pour imposer la séparation de domaine à partir des variantes de expand_message, explique comment chaque méthode réalise la séparation de domaine et liste les situations dans lesquelles chacune est appropriée. Ces méthodes partagent une structure de haut niveau : le concepteur de l'application fixe une étiquette DST_ext distincte de DST_prime et augmente les appels à H avec DST_ext. Chaque méthode augmente les appels à H différemment, et chacune peut imposer des exigences supplémentaires sur DST_ext.
Ces méthodes peuvent être utilisées pour instancier plusieurs fonctions séparées par domaine (par exemple, H1 et H2) en sélectionnant des valeurs DST_ext distinctes pour chacune (par exemple, DST_ext1, DST_ext2).
-
(Séparation de domaine par suffixe uniquement.) Cette méthode est utile lors de la séparation par domaine des invocations de H de expand_message_xmd ou expand_message_xof. Elle n'est pas appropriée pour séparer par domaine expand_message de HMAC-H [RFC2104] ; à cette fin, voir la méthode 4.
Pour instancier une fonction Hso séparée par domaine par suffixe uniquement, calculez :
Hso(msg) = H(msg || DST_ext)
DST_ext devrait être encodée sans suffixe (par exemple, en ajoutant un octet encodant la longueur de DST_ext) pour rendre infaisable la recherche de paires (msg, DST_ext) distinctes qui se hachent vers la même valeur.
Cette méthode assure la séparation de domaine car toutes les invocations distinctes de H ont des suffixes distincts, puisque DST_ext est distincte de DST_prime.
-
(Séparation de domaine préfixe-suffixe.) Cette méthode peut être utilisée dans les mêmes cas que la méthode par suffixe uniquement.
Pour instancier une fonction Hps séparée par domaine par préfixe-suffixe, calculez :
Hps(msg) = H(DST_ext || msg || I2OSP(0, 1))
DST_ext devrait être encodée sans préfixe (par exemple, en ajoutant un préfixe d'un octet qui encode la longueur de DST_ext) pour rendre infaisable la recherche de paires (msg, DST_ext) distinctes qui se hachent vers la même valeur.
Cette méthode assure la séparation de domaine car l'ajout de l'octet I2OSP(0, 1) garantit que les entrées de H à l'intérieur de Hps sont distinctes de celles à l'intérieur de expand_message. Plus précisément, le dernier octet de DST_prime encode la longueur de DST, qui doit être non nulle (section 3.1, exigence 2), et DST_prime est toujours ajouté aux invocations de H à l'intérieur de expand_message.
-
(Séparation de domaine par préfixe uniquement.) Cette méthode n'est utile que pour séparer par domaine les invocations de H de expand_message_xmd. Elle ne permet pas la séparation de domaine pour expand_message_xof ou HMAC-H.
Pour instancier une fonction Hpo séparée par domaine par préfixe uniquement, calculez :
Hpo(msg) = H(DST_ext || msg)
Pour que cette méthode assure la séparation de domaine, DST_ext devrait être longue d'au moins b bits, où b est le nombre de bits produits par la fonction de hachage H. En outre, au moins l'un des premiers b bits doit être non nul. Enfin, DST_ext devrait être encodée sans préfixe (par exemple, en ajoutant un préfixe d'un octet qui encode la longueur de DST_ext) pour rendre infaisable la recherche de paires (msg, DST_ext) distinctes qui se hachent vers la même valeur.
Cette méthode assure la séparation de domaine de la manière suivante. Premièrement, comme DST_ext contient au moins un bit non nul parmi ses premiers b bits, elle est garantie être distincte de la valeur Z_pad (section 5.3.1, étape 4), ce qui garantit que toutes les entrées de H sont distinctes de l'entrée utilisée pour générer b_0 dans expand_message_xmd. Deuxièmement, comme DST_ext est longue d'au moins b bits, elle est presque certainement distincte des valeurs b_0 et strxor(b_0, b_(i - 1)), et par conséquent toutes les entrées de H sont distinctes des entrées utilisées pour générer b_i, i >= 1, avec une probabilité élevée.
-
(Séparation de domaine XMD-HMAC.) Cette méthode est utile pour séparer par domaine les invocations de H à l'intérieur de HMAC-H (c'est-à-dire HMAC [RFC2104] instancié avec la fonction de hachage H) de expand_message_xmd. Elle s'applique également à HKDF-H (c'est-à-dire HKDF [RFC5869] instancié avec la fonction de hachage H), comme discuté ci-dessous.
Plus précisément, cette méthode s'applique lorsque HMAC-H est utilisé avec une clé non secrète pour instancier un oracle aléatoire basé sur une fonction de hachage H (notez que expand_message_xmd peut également être utilisée à cette fin ; voir la section 10.6). Lors de l'utilisation de HMAC-H avec une clé secrète à haute entropie, la séparation de domaine n'est pas nécessaire ; voir la discussion ci-dessous.
Pour choisir une clé HMAC non secrète DST_key qui assure l'écart de domaine par rapport à expand_message_xmd, calculez :
DST_key_preimage = "DERIVE-HMAC-KEY-" || DST_ext || I2OSP(0, 1) DST_key = H(DST_key_preimage)
Ensuite, pour instancier l'oracle aléatoire Hro en utilisant HMAC-H, calculez :
Hro(msg) = HMAC-H(DST_key, msg)
L'octet zéro final dans DST_key_preimage garantit que cette valeur est distincte des entrées de H à l'intérieur de expand_message_xmd (car toutes ces entrées ont le suffixe DST_prime, qui ne peut pas se terminer par un octet zéro comme discuté ci-dessus). Cela assure la séparation de domaine car, avec une probabilité écrasante, toutes les entrées de H à l'intérieur de HMAC-H utilisant la clé DST_key ont des préfixes qui sont distincts des valeurs Z_pad, b_0 et strxor(b_0, b_(i - 1)) à l'intérieur de expand_message_xmd.
Pour les utilisations de HMAC-H qui instancient un oracle aléatoire privé en fixant une clé secrète à haute entropie, la séparation de domaine par rapport à expand_message_xmd n'est pas nécessaire. En effet, de manière similaire au cas ci-dessus, toutes les entrées de H à l'intérieur de HMAC-H utilisant cette clé secrète ont presque certainement des préfixes distincts de toutes les entrées de H à l'intérieur de expand_message_xmd.
Enfin, cette méthode peut être utilisée avec HKDF-H [RFC5869] en fixant l'entrée salt de HKDF-Extract à DST_key, calculée comme ci-dessus. Cela assure la séparation de domaine pour HKDF-Extract par le même argument que pour HMAC-H utilisant DST_key. De plus, en supposant que le matériel de clé d'entrée (IKM) fourni à HKDF-Extract possède une entropie suffisamment élevée (disons, proportionnée au paramètre de sécurité), l'étape HKDF-Expand est séparée par domaine par le même argument que pour HMAC-H avec une clé secrète à haute entropie (puisqu'une clé pseudo-aléatoire est exactement cela).
10.8. Niveaux de sécurité cibles
Chaque suite cryptographique spécifie un niveau de sécurité cible (en bits) pour la courbe sous-jacente. Ce paramètre garantit que l'instanciation de hash_to_field correspondante est conservatrice et correcte. Nous soulignons que ce paramètre n'est qu'une borne supérieure du niveau de sécurité de la courbe et n'est ni une garantie ni une approbation de son adéquation pour une application donnée. Les progrès mathématiques et cryptographiques peuvent réduire le niveau de sécurité effectif de n'importe quelle courbe.