Quel algorithme de hachage est le meilleur pour l'unicité et la vitesse? Les exemples (bons) utilisations incluent les dictionnaires de hachage.
Je sais qu'il existe des éléments tels que SHA-256 et autres, mais ces algorithmes sont conçus pour être sécurisés , ce qui signifie généralement qu'ils sont plus lents que des algorithmes moins uniques . Je veux un algorithme de hachage conçu pour être rapide, tout en restant assez unique pour éviter les collisions.
algorithms
hashing
Earlz
la source
la source
Réponses:
J'ai testé différents algorithmes, mesurant la vitesse et le nombre de collisions.
J'ai utilisé trois jeux de clés différents:
"1"
à"216553"
(pensez aux codes postaux et à la manière dont un hachage pauvre a été pris par msn.com )Pour chaque corpus, le nombre de collisions et le temps moyen de hachage ont été enregistrés.
J'ai testé:
xor
plutôt que+
)Résultats
Chaque résultat contient le temps de hachage moyen et le nombre de collisions
Notes :
Les collisions se produisent-elles réellement?
Oui. J'ai commencé à écrire mon programme de test pour voir si les collisions de hachage se produisaient réellement - et ne constituaient pas simplement un concept théorique. Ils se produisent effectivement:
Collisions FNV-1
creamwove
entre en collision avecquists
Collisions FNV-1a
costarring
entre en collision avecliquid
declinate
entre en collision avecmacallums
altarage
entre en collision aveczinke
altarages
entre en collision aveczinkes
Collisions Murmur2
cataract
entre en collision avecperiti
roquette
entre en collision avecskivie
shawl
entre en collision avecstormbound
dowlases
entre en collision avectramontane
cricketings
entre en collision avectwanger
longans
entre en collision avecwhigs
Collisions DJB2
hetairas
entre en collision avecmentioner
heliotropes
entre en collision avecneurospora
depravement
entre en collision avecserafins
stylist
entre en collision avecsubgenera
joyful
entre en collision avecsynaphea
redescribed
entre en collision avecurites
dram
entre en collision avecvivency
Collisions DJB2a
haggadot
entre en collision avecloathsomenesses
adorablenesses
entre en collision avecrentability
playwright
entre en collision avecsnush
playwrighting
entre en collision avecsnushing
treponematoses
entre en collision avecwaterbeds
Collisions CRC32
codding
entre en collision avecgnu
exhibiters
entre en collision avecschlager
Collisions SuperFastHash
dahabiah
entre en collision avecdrapability
encharm
entre en collision avecenclave
grahams
entre en collision avecgramary
night
entre en collision avecvigil
nights
entre en collision avecvigils
finks
entre en collision avecvinic
Aléatoire
L’autre mesure subjective est la distribution aléatoire des hachages. Le mappage des tables de hachage obtenues montre comment les données sont distribuées. Toutes les fonctions de hachage montrent une bonne distribution lors du mappage linéaire de la table:
Ou comme une carte de Hilbert ( XKCD est toujours pertinent ):
Sauf lorsque les chaînes numériques (hashing
"1"
,"2"
, ...,"216553"
) (par exemple, des codes postaux ), où commencent à émerger des modèles dans la plupart des algorithmes de hachage:SDBM :
DJB2a :
FNV-1 :
Tous sauf FNV-1a , qui me semble toujours assez aléatoire:
En fait, Murmur2 semble avoir encore mieux son caractère aléatoire avec
Numbers
queFNV-1a
:Le supplément
*
dans le tableau indique à quel point le caractère aléatoire est mauvais. AvecFNV-1a
être le meilleur, etDJB2x
étant le pire:Au départ, j’avais écrit ce programme pour décider si je devais même me soucier des collisions: c’est le cas.
Et ensuite, il s’est assuré que les fonctions de hachage étaient suffisamment aléatoires.
Algorithme FNV-1a
Le hachage FNV1 est proposé dans des variantes qui renvoient des hachages de 32, 64, 128, 256, 512 et 1024 bits.
L' algorithme FNV-1a est:
Où les constantes
FNV_offset_basis
etFNV_prime
dépendent de la taille de hachage de retour souhaitée:Voir la page principale FNV pour plus de détails.
Tous mes résultats sont avec la variante 32 bits.
FNV-1 meilleur que FNV-1a?
FNV-1a est tout à fait mieux. Il y avait plus de collisions avec FNV-1a en utilisant le mot anglais corpus:
Maintenant, comparez les minuscules et les majuscules:
Dans ce cas, FNV-1a n'est pas "400%" pire que FN-1, seulement 20% pire.
Je pense que le point le plus important à retenir est qu’il existe deux classes d’algorithmes en matière de collision:
Et puis il y a la façon dont les hachages sont distribués uniformément:
Mise à jour
Murmure? Bien sûr, pourquoi pas
Mise à jour
@whatshisname s'est demandé comment se comporterait un CRC32 , ajoutait des chiffres à la table.
CRC32 est très bon . Peu de collisions, mais plus lentes, et les frais généraux d’une table de recherche 1k.
Snip tous les trucs erronés sur la distribution du CRC - mon mauvais
Jusqu'à aujourd'hui, j'allais utiliser FNV-1a comme algorithme de hachage de facto de table de hachage. Mais maintenant je passe à Murmur2:
Et j'espère vraiment qu'il y a quelque chose qui ne va pas avec l'
SuperFastHash
algorithme que j'ai trouvé ; c'est dommage d'être aussi populaire que ça.Mise à jour: depuis la page d'accueil MurmurHash3 sur Google :
Donc je suppose que ce n'est pas juste moi.
Mise à jour: j'ai compris pourquoi
Murmur
c'est plus rapide que les autres. MurmurHash2 fonctionne sur quatre octets à la fois. La plupart des algorithmes sont octets par octets :Cela signifie que lorsque les touches s'allongent, Murmur a la chance de briller.
Mise à jour
Les GUID sont conçus pour être uniques et non aléatoires
Dans un article opportun de Raymond Chen, on réitère le fait que les GUID "aléatoires" ne sont pas destinés à être utilisés pour leur caractère aléatoire. Ils, ou un sous-ensemble d’entre eux, ne conviennent pas comme clé de hachage:
Le hasard n'est pas la même chose que d'éviter les collisions; C'est pourquoi ce serait une erreur d'essayer d'inventer votre propre algorithme de "hachage" en prenant un sous-ensemble d'un guid "aléatoire":
Note : Encore une fois, je mets "GUID aléatoire" entre guillemets, car c'est la variante "aléatoire" des GUID. Une description plus précise serait
Type 4 UUID
. Mais personne ne sait ce que sont le type 4 ou les types 1, 3 et 5. Il est donc plus simple de les appeler des GUID "aléatoires".Tous les mots anglais miroirs
la source
Si vous souhaitez créer une carte de hachage à partir d'un dictionnaire immuable, envisagez un hachage parfait https://en.wikipedia.org/wiki/Perfect_hash_function - lors de la construction de la fonction de hachage et de la table de hachage, vous pouvez garantir, pour un ensemble de données donné, il n'y aura pas de collision.
la source
Voici une liste des fonctions de hachage, mais la version courte est:
la source
CityHash de Google est l'algorithme que vous recherchez. Ce n'est pas bon pour la cryptographie, mais c'est bon pour générer des hachages uniques.
Lisez le blog pour plus de détails et le code est disponible ici .
CityHash est écrit en C ++. Il y a aussi un port C simple .
À propos du support 32 bits:
la source
plain C port
le lien est casséJ'ai tracé une comparaison rapide de différents algorithmes de hachage lors du hachage de fichiers.
Les tracés individuels ne diffèrent que légèrement par la méthode de lecture et peuvent être ignorés ici, car tous les fichiers ont été stockés dans un fichier tmpfs. Par conséquent, le repère n'était pas lié aux entrées-sorties si vous vous posez la question.
Les algorithmes comprennent:
SpookyHash, CityHash, Murmur3, MD5, SHA{1,256,512}
.Conclusions:
CRC
instruction SSE 4.2s , que mon CPU n’a pas. SpookyHash était dans mon cas toujours un peu avant CityHash.La source utilisée pour les parcelles:
la source
Les algorithmes SHA (y compris SHA-256) sont conçus pour être rapides .
En fait, leur vitesse peut parfois être un problème. En particulier, une technique courante pour stocker un jeton dérivé d'un mot de passe consiste à exécuter un algorithme de hachage rapide standard 10 000 fois (stocker le hachage du hachage du hachage du hachage du mot de passe ...).
Sortie:
la source
bcrypt
. Utilisez les bons outils..rodata
coûts d' installation, de démontage et / ou d'état élevés. Lorsque vous voulez un algorithme pour une table de hachage, vous avez généralement des clés très courtes et un grand nombre d’entre elles, mais vous n’avez pas besoin des garanties supplémentaires que vous offre un cryptographique. J'utilise moi-même un Jenkins modifié.L'hypothèse selon laquelle les fonctions de hachage cryptographiques sont plus uniques est fausse et, en fait, on peut démontrer qu'elle est souvent rétrograde dans la pratique. En vérité:
Ce qui signifie qu'une fonction de hachage non cryptographique risque d'avoir moins de collisions qu'une fonction cryptographique pour de "bons" ensembles de données - ensembles de données pour lesquels elle a été conçue.
Nous pouvons en faire la démonstration avec les données de la réponse de Ian Boyd et un peu de calcul: le problème de l' anniversaire . La formule pour le nombre attendu de paires en collision si vous choisissez des
n
entiers au hasard dans l'ensemble[1, d]
est la suivante (tirée de Wikipedia):Branchement
n
= 216553 etd
= 2 ^ 32 nous obtenons environ 5,5 collisions attendues . Les tests de Ian montrent principalement des résultats dans ce quartier, à une exception près: la plupart des fonctions n'ont eu aucune collision lors des tests de nombres consécutifs. La probabilité de choisir au hasard 216 553 nombres de 32 bits et d'obtenir zéro collision est d'environ 0,43%. Et ce n'est que pour une fonction - nous avons ici cinq familles de fonctions de hachage distinctes avec zéro collision!Nous constatons donc ici que les hachages testés par Ian interagissent favorablement avec l'ensemble de données de nombres consécutifs, c'est-à-dire qu'ils dispersent très peu d'entrées différentes plus largement qu'une fonction de hachage cryptographique idéale. (Note latérale: cela signifie que l'évaluation graphique de Ian selon laquelle FNV-1a et MurmurHash2 lui "semblent aléatoires" dans l'ensemble de données numériques peut être réfuté à partir de ses propres données. Zéro collisions sur un ensemble de données de cette taille, pour les deux fonctions de hachage, est remarquablement non-aléatoire!)
Ce n'est pas une surprise, car il s'agit d'un comportement souhaitable pour de nombreuses utilisations des fonctions de hachage. Par exemple, les clés de table de hachage sont souvent très similaires. La réponse de Ian mentionne un problème que MSN a déjà rencontré avec les tables de hachage par code postal . Il s'agit d'une utilisation dans laquelle la prévention des collisions sur des entrées probables l' emporte sur un comportement aléatoire.
Une autre comparaison intéressante est le contraste entre les objectifs de conception des fonctions CRC et de hachage cryptographique:
Pour le CRC, il est donc bon d’avoir moins de collisions que de hasard dans des entrées très différentes. Avec crypto hashes, c'est un non-non!
la source
Utilisez SipHash . Il possède de nombreuses propriétés souhaitables:
Vite. Une mise en œuvre optimisée prend environ 1 cycle par octet.
Sécurise. SipHash est une PRF forte (fonction pseudo-aléatoire). Cela signifie qu'il est impossible de distinguer une fonction aléatoire (à moins que vous ne connaissiez la clé secrète de 128 bits). Par conséquent:
Inutile de vous inquiéter de ce que vos sondes de table de hachage deviennent des heures linéaires en raison de collisions. Avec SipHash, vous savez que vous obtiendrez une performance de cas moyen en moyenne, indépendamment des entrées.
Immunité aux attaques par déni de service basées sur le hachage.
Vous pouvez utiliser SipHash (en particulier la version avec une sortie 128 bits) en tant que MAC (code d’authentification de message). Si vous recevez un message et une balise SipHash, et que cette balise est identique à celle obtenue en exécutant SipHash avec votre clé secrète, vous savez que le créateur du hachage était également en possession de votre clé secrète et que ni le message, ni le le hash a été modifié depuis.
la source
Cela dépend des données que vous hachez. Certains hachages fonctionnent mieux avec des données spécifiques telles que le texte. Certains algorithmes de hachage ont été spécifiquement conçus pour être utiles pour des données spécifiques.
Paul Hsieh a déjà fait du hasch rapide . Il énumère le code source et les explications. Mais c'était déjà battu. :)
la source
Java utilise cet algorithme simple multiplier-ajouter:
Il y en a probablement de bien meilleurs, mais ceci est assez répandu et semble constituer un bon compromis entre vitesse et unicité.
la source
Tout d’abord, pourquoi avez-vous besoin de mettre en œuvre votre propre hachage? Pour la plupart des tâches, vous devriez obtenir de bons résultats avec les structures de données d'une bibliothèque standard, en supposant qu'une implémentation soit disponible (à moins que vous ne le fassiez pour votre propre formation).
En ce qui concerne les algorithmes de hachage, mon préféré est FNV. 1
Voici un exemple d'implémentation de la version 32 bits en C:
la source
*
et^
:h = (h * 16777619) ^ p[i]
==>h = (h ^ p[i]) * 16777619