Technique › Cryptographie

Hachages : Keccak, Hs et Hp

Comment Monero transforme des octets quelconques en nombre ou en point

En bref

Monero utilise la fonction de hachage Keccak-256 (le Keccak original, et non le SHA3-256 standardisé). Deux fonctions dérivées en sont construites : Hs — « hachage vers un scalaire » et Hp — « hachage vers un point ».

Keccak-256

Une fonction de hachage prend n’importe quelles données et produit 32 octets d’apparence aléatoire. Modifier un seul bit d’entrée change toute la sortie ; retrouver l’entrée à partir de la sortie, ou trouver deux entrées donnant la même sortie, est irréalisable en pratique.

Monero (comme Ethereum) utilise Keccak tel qu’il a remporté le concours SHA-3 — avant que le NIST ne modifie l’octet de remplissage (padding). À cause de ce détail, sha3_256() d’une bibliothèque standard donne un résultat différent. Si votre code ne correspond pas à Monero, vérifiez d’abord ce point.

FonctionHachage de la chaîne vide
Keccak-256 (Monero)c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
SHA3-256 (NIST)a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a

Dans le code de Monero, cette fonction s’appelle cn_fast_hash.

Hs : hachage vers un scalaire

Souvent, on n’a pas besoin de simples octets mais d’un scalaire — un nombre modulo l (l’ordre du point de base). Hs le fait directement :

Hs(data) = Keccak256(data) mod l les 32 octets du hachage sont lus comme un nombre petit-boutiste et réduits modulo l (dans le code : sc_reduce32)

Où Hs est utilisé :

Hp : hachage vers un point

Parfois, on a besoin d’un point dont personne ne connaît le logarithme discret. On ne peut pas simplement prendre Hs(data)·G — le logarithme serait alors Hs(data), connu de tous. Hp construit un point directement à partir du hachage via une application spéciale (dans Monero, une variante d’Elligator 2, la fonction ge_fromfe_frombytes_vartime), puis multiplie par le cofacteur 8 pour que le point tombe dans le bon sous-groupe.

Hp(data) = 8 · map_to_curve( Keccak256(data) )

Où Hp est utilisé :

  • les key images : I = x·Hp(P) — l’usage principal ;
  • le second générateur H des engagements de Pedersen : H = Hp(G) (aux détails d’encodage près). Personne ne connaît de k tel que H = k·G — et c’est essentiel pour que les montants ne puissent pas être falsifiés.
Séparation de domaine

La bonne pratique consiste à préfixer les données d’une chaîne d’étiquette (« SubAddr », « view_tag », « amount ») avant le hachage, pour qu’un hachage calculé dans un but ne puisse pas être détourné pour un autre. L’ancien code CryptoNote contient peu d’étiquettes ; les parties plus récentes (view tags, Carrot, FCMP++) les utilisent systématiquement.