Qu'est-ce qu'une bonne fonction de hachage?

130

Qu'est-ce qu'une bonne fonction de hachage? J'ai vu beaucoup de fonctions et d'applications de hachage dans mes cours sur les structures de données à l'université, mais j'ai surtout compris qu'il est assez difficile de créer une bonne fonction de hachage. En règle générale, pour éviter les collisions, mon professeur a dit que:

function Hash(key)
  return key mod PrimeNumber
end

(mod est l'opérateur% en C et langages similaires)

le nombre premier étant la taille de la table de hachage. Je comprends que c'est une fonction plutôt bonne pour éviter les collisions et une fonction rapide, mais comment puis-je en faire une meilleure? Existe-t-il de meilleures fonctions de hachage pour les touches de chaîne par rapport aux touches numériques?

Hoffmann
la source
34
Avez-vous envisagé d'utiliser une ou plusieurs des fonctions de hachage à usage général suivantes: partow.net/programming/hashfunctions/index.html
Dans le fnv_func, le type de p [i] est char, que se passera-t-il avec h après la première itération? Cela a-t-il été fait dans un but précis?
5
@martinatime a dit: Il y a un tas d'informations sur les fonctions de hachage dans wikipedia en.wikipedia.org/wiki/Hash_function et le bas de cet article partow.net/programming/hashfunctions/index.html a des algorithmes implémentés dans différentes langues.
2501

Réponses:

33

Pour faire des recherches de table de hachage "normales" sur pratiquement n'importe quel type de données - celle de Paul Hsieh est la meilleure que j'ai jamais utilisée.

http://www.azillionmonkeys.com/qed/hash.html

Si vous vous souciez de la sécurité cryptographique ou de toute autre chose plus avancée, alors YMMV. Si vous voulez juste une fonction de hachage à usage général kick ass pour une recherche de table de hachage, c'est ce que vous recherchez.

Chris Harris
la source
Merci pour le lien informatif! Je connais quelques analyses de Bob Jenkins et d'autres qui pointent vers de très bonnes fonctions de hachage universellement acceptables, mais je n'ai pas encore rencontré celle-ci.
Konrad Rudolph
J'avais lu sur le site de Jenkins que SFH était alors l'un des meilleurs, mais je pense que Murmur pourrait faire mieux, voir cette excellente réponse: programmers.stackexchange.com/questions/49550/…
nawfal
2
Que signifie YMMV?
cobarzan
3
@cobarzan Votre kilométrage peut varier
ProgrammerDan
2
La fonction de hachage de Hsieh est horrible, avec un ordre de grandeur plus de collisions que nous ne le souhaitons. En particulier, les chaînes qui ne diffèrent que dans les 4 derniers octets peuvent facilement entrer en collision. Si vous avez une chaîne de 30 caractères, qui diffèrent dans les 4 derniers octets, après que 28 octets ont été traités, les hachages ne diffèrent que dans les 2 derniers octets. Cela signifie que vous êtes GARANTI d'une collision pour l'une des valeurs restantes sur deux octets. (Ouais, c'est rapide. Et alors.)
Andrew Lazarus
51

Il n'y a pas de «bonne fonction de hachage» pour les hachages universels (éd. Oui, je sais qu'il existe un «hachage universel» mais ce n'est pas ce que je voulais dire). En fonction du contexte, différents critères déterminent la qualité d'un hachage. Deux personnes ont déjà mentionné SHA. Il s'agit d'un hachage cryptographique et il n'est pas du tout bon pour les tables de hachage, ce que vous voulez probablement dire.

Les tables de hachage ont des exigences très différentes. Cependant, trouver une bonne fonction de hachage de manière universelle est difficile car différents types de données exposent différentes informations qui peuvent être hachées. En règle générale, il est bon de considérer toutes les informations qu'un type détient de la même manière. Ce n'est pas toujours facile ni même possible. Pour des raisons de statistiques (et donc de collision), il est également important de générer une bonne répartition sur l'espace du problème, c'est-à-dire tous les objets possibles. Cela signifie que lors du hachage de nombres entre 100 et 1050, il n'est pas bon de laisser le chiffre le plus significatif jouer un grand rôle dans le hachage car pour ~ 90% des objets, ce chiffre sera 0. Il est bien plus important de laisser les trois derniers les chiffres déterminent le hachage.

De même, lors du hachage de chaînes, il est important de prendre en compte tous les caractères - sauf s'il est connu à l'avance que les trois premiers caractères de toutes les chaînes seront les mêmes; considérer ces derniers est alors un gaspillage.

C'est en fait l'un des cas où je conseille de lire ce que Knuth a à dire dans The Art of Computer Programming , vol. 3. Une autre bonne lecture est The Art of Hashing de Julienne Walker .

Konrad Rudolph
la source
1
Konrad, vous avez sûrement raison d'un point de vue théorique, mais avez-vous déjà essayé d'utiliser la fonction de hachage de Paul Hsieh que j'ai mentionnée dans mon commentaire? C'est vraiment assez bon contre beaucoup de types de données différents!
Chris Harris
9

Les fonctions de hachage ont deux objectifs principaux:

  • pour disperser les points de données uniformément en n bits.
  • pour identifier en toute sécurité les données d'entrée.

Il est impossible de recommander un hachage sans savoir à quoi vous l'utilisez.

Si vous créez simplement une table de hachage dans un programme, vous n'avez pas à vous soucier de la réversibilité ou du piratage de l'algorithme ... SHA-1 ou AES est complètement inutile pour cela, vous feriez mieux d'utiliser une variante de FNV . FNV réalise une meilleure dispersion (et donc moins de collisions) qu'un simple mod principal comme vous l'avez mentionné, et il est plus adaptable à différentes tailles d'entrée.

Si vous utilisez les hachages pour masquer et authentifier des informations publiques (telles que le hachage d'un mot de passe ou d'un document), vous devez utiliser l'un des principaux algorithmes de hachage examinés par le public. Le salon Hash Function est un bon point de départ.

Myrddin Emrys
la source
lien mis à jour vers The Hash Function Lounge: larc.usp.br/~pbarreto/hflounge.html
Tim Partridge
Dans quelle mesure FNV résiste-t-il à la collision d'anniversaire par rapport, par exemple, au même nombre de bits d'un SHA1?
Kevin Hsu
@Kevin Tant que les caractéristiques d'avalanche d'un hachage sont bonnes (minuscules changements en entrée = gros changements en sortie), les collisions d'anniversaire sont simplement fonction des bits du hachage. FNV-1a est excellent à cet égard, et vous pouvez avoir autant ou aussi peu de bits dans le hachage que vous le souhaitez (bien qu'il faille un petit effort supplémentaire pour obtenir un nombre de bits qui n'est pas une puissance de 2).
Myrddin Emrys
5

Ceci est un exemple de bon et aussi un exemple de pourquoi vous ne voudriez jamais en écrire un. C'est un hachage Fowler / Noll / Vo (FNV) qui est à la fois génie de l'informatique et pur vaudou:

unsigned fnv_hash_1a_32 ( void *key, int len ) {
    unsigned char *p = key;
    unsigned h = 0x811c9dc5;
    int i;

    for ( i = 0; i < len; i++ )
      h = ( h ^ p[i] ) * 0x01000193;

   return h;
}

unsigned long long fnv_hash_1a_64 ( void *key, int len ) {
    unsigned char *p = key;
    unsigned long long h = 0xcbf29ce484222325ULL;
    int i;

    for ( i = 0; i < len; i++ )
      h = ( h ^ p[i] ) * 0x100000001b3ULL;

   return h;
}

Éditer:

  • Landon Curt Noll recommande sur son site l'algorithme FVN-1A par rapport à l'algorithme FVN-1 original: L'algorithme amélioré disperse mieux le dernier octet dans le hachage. J'ai ajusté l'algorithme en conséquence.
Nick Van Brunt
la source
3
Vous pouvez consulter ce site pour obtenir des informations sur les raisons pour lesquelles ces valeurs sont choisies: isthe.com/chongo/tech/comp/fnv/#fnv-prime
Cthutu
Soyez bénis. Cette fonction de hachage 64 bits courte, simple, efficace, générique et efficace était exactement ce dont j'avais besoin.
mattarod
3

Je dirais que la règle générale est de ne pas rouler le vôtre. Essayez d'utiliser quelque chose qui a été soigneusement testé, par exemple, SHA-1 ou quelque chose du genre.

Einar
la source
Il ne semble pas avoir besoin de quoi que ce soit de sécurité cryptographique, donc SHA-1 serait bien exagéré.
Erik
à propos, même si aucune collision pour SHA-1 n'a été trouvée, on pense que ce n'est qu'une question d'années ou de mois avant qu'une telle collision ne soit trouvée. Je recommanderais d'utiliser SHA-256.
Samuel Allan
1

Une bonne fonction de hachage a les propriétés suivantes:

  1. Étant donné le hachage d'un message, il est impossible à un attaquant de trouver un autre message de telle sorte que ses hachages soient identiques.

  2. Étant donné une paire de messages, m 'et m, il est impossible de trouver deux messages tels que h (m) = h (m')

Les deux cas ne sont pas les mêmes. Dans le premier cas, il existe un hachage préexistant pour lequel vous essayez de trouver une collision. Dans le second cas, vous essayez de trouver les deux messages qui entrent en collision. La deuxième tâche est beaucoup plus facile en raison du «paradoxe» de l'anniversaire.

Lorsque les performances ne sont pas un problème majeur, vous devez toujours utiliser une fonction de hachage sécurisée. Il existe des attaques très intelligentes qui peuvent être effectuées en forçant des collisions dans un hachage. Si vous utilisez quelque chose de fort dès le départ, vous vous protégerez contre ceux-ci.

N'utilisez pas MD5 ou SHA-1 dans de nouvelles conceptions. La plupart des cryptographes, moi inclus, les considéreraient comme cassés. La principale source de faiblesse dans ces deux conceptions est que la seconde propriété, que j'ai soulignée ci-dessus, ne vaut pas pour ces constructions. Si un attaquant peut générer deux messages, m et m ', que les deux hachent à la même valeur, ils peuvent utiliser ces messages contre vous. SHA-1 et MD5 souffrent également d'attaques par extension de message, ce qui peut fatalement affaiblir votre application si vous ne faites pas attention.

Un hachage plus moderne tel que Whirpool est un meilleur choix. Il ne souffre pas de ces attaques par extension de message et utilise les mêmes mathématiques que celles utilisées par AES pour prouver la sécurité contre diverses attaques.

J'espère que cela pourra aider!

Simon Johnson
la source
1
Je pense que la recommandation de la fonction de hachage cryptographique est un très mauvais conseil dans ce cas.
Slava
@Slava: Pourquoi? Quelles sont vos raisons pour dire qu'une "fonction de hachage cryptographique est un très mauvais conseil dans ce cas?" Pourquoi est-ce un mauvais conseil? Quels sont les inconvénients relatifs qui en font le cas?
Laissez-moi y réfléchir
2
@Mowzer parce qu'une fonction de hachage utilisée dans une carte de hachage doit être rapide et légère (en supposant qu'elle fournit toujours un bon hachage), les hachages cryptographiques étaient explicitement coûteux en calcul pour éviter les attaques par force brute.
Slava
1

Ce que vous dites ici, c'est que vous voulez en avoir un qui utilise une résistance aux collisions. Essayez d'utiliser SHA-2. Ou essayez d'utiliser un (bon) chiffrement par bloc dans une fonction de compression à sens unique (jamais essayé auparavant), comme AES en mode Miyaguchi-Preenel. Le problème avec cela est que vous devez:

1) avoir une IV. Essayez d'utiliser les 256 premiers bits des parties fractionnaires de la constante de Khinchin ou quelque chose comme ça. 2) ont un schéma de remplissage. Facile. Barrow à partir d'un hash comme MD5 ou SHA-3 (Keccak [prononcé 'ket-chak']). Si vous ne vous souciez pas de la sécurité (quelques autres l'ont dit), regardez FNV ou lookup2 de Bob Jenkins (en fait, je suis le premier à recommander lookup2) Essayez également MurmurHash, c'est rapide (vérifiez ceci: .16 cpb ).

Feria de Gavriel
la source