J'ai lu l'article Wikipédia sur les hachages md5 mais je ne comprends toujours pas comment un hachage ne peut pas être "reconstitué" dans le texte d'origine.
Quelqu'un pourrait-il expliquer à quelqu'un qui connaît très peu la cryptographie comment cela fonctionne? Quelle partie de la fonction la rend unidirectionnelle?
Puisque tout le monde jusqu'à présent a simplement défini ce qu'était une fonction de hachage, je vais mordre.
Une fonction unidirectionnelle n'est pas seulement une fonction de hachage - une fonction qui perd des informations - mais une fonction f
pour laquelle, étant donné une image y
("SE" ou 294 dans les réponses existantes ), il est difficile de trouver une pré-image x telle que f(x)=y
.
C'est pourquoi ils sont appelés à sens unique: vous pouvez calculer une image mais vous ne pouvez pas trouver une pré-image pour une image donnée.
Aucune des fonctions de hachage ordinaires proposées jusqu'à présent dans les réponses existantes n'a cette propriété. Aucune d'entre elles n'est une fonction de hachage cryptographique à sens unique. Par exemple, étant donné "SE", vous pouvez facilement prendre l'entrée "SXXXE", une entrée avec la propriété que X-encode ("SXXXE") = SE.
Il n'y a pas de fonctions unidirectionnelles "simples". Ils doivent mélanger leurs entrées si bien que non seulement vous ne reconnaissez pas du tout l'entrée dans la sortie, mais vous ne reconnaissez pas une autre entrée Soit.
SHA-1 et MD5 étaient des fonctions unidirectionnelles populaires, mais elles sont presque toutes deux cassées (les spécialistes savent comment créer des pré-images pour des images données, ou sont presque capables de le faire). Un concours est en cours pour en choisir un nouveau standard, qui sera nommé SHA- .
Une approche évidente pour inverser une fonction à sens unique serait de calculer de nombreuses images et de les conserver dans un tableau associant à chaque image la pré-image qui l'a produite. Pour rendre cela impossible en pratique, toutes les fonctions unidirectionnelles ont une sortie importante, au moins 64 bits mais peut-être beaucoup plus grande (jusqu'à, disons, 512 bits).
EDIT: Comment fonctionnent la plupart des fonctions de hachage cryptographiques?
Habituellement, ils ont à leur base une seule fonction qui fait des transformations compliquées sur un bloc de bits (un bloc de chiffrement ). La fonction doit être presque bijective (elle ne doit pas mapper trop de séquences sur la même image, car cela entraînerait des faiblesses plus tard), mais elle ne doit pas être exactement bijective. Et cette fonction est répétée un nombre fixe de fois, suffisamment pour rendre l'entrée (ou toute entrée possible) impossible à reconnaître.
Prenons l'exemple de Skein , l'un des candidats forts pour le contexte SHA-3. Sa fonction principale est répétée 72 fois. Le seul nombre d'itérations pour lesquelles les créateurs de la fonction savent comment relier parfois les sorties à certaines entrées est 25. Ils disent qu'elle a un "facteur de sécurité" de 2,9.
Pensez à un hachage vraiment basique - pour la chaîne d'entrée, retournez la somme des valeurs ASCII de chaque caractère.
hash( 'abc' ) = ascii('a')+ascii('b')+ascii('c')
= 97 + 98 + 99
= 294
Maintenant, étant donné la valeur de hachage de 294, pouvez-vous dire quelle était la chaîne d'origine? Évidemment non, car 'abc' et 'cba' (et d'innombrables autres) donnent la même valeur de hachage.
Les fonctions de hachage cryptographique fonctionnent de la même manière, sauf que, de toute évidence, l'algorithme est beaucoup plus complexe. Il y aura toujours des collisions, mais si vous savez que la chaîne s
est hachée en h
, alors cela devrait être très difficile ("infaisable par calcul") de construire autre chaîne qui hache également en h
.
Prise de vue pour une analogie simple ici au lieu d'une explication complexe.
Pour commencer, décomposons le sujet en deux parties, les opérations à sens unique et le hachage. Qu'est-ce qu'une opération à sens unique et pourquoi en voudriez-vous une?
Les opérations à sens unique sont appelées ainsi car elles ne sont pas réversibles. La plupart des opérations typiques comme l'addition et la multiplication peuvent être inversées tandis que la division modulo ne peut pas être inversée. Pourquoi est-ce important? Parce que vous voulez fournir une valeur de sortie qui 1) est difficile à reproduire sans les entrées d'origine et 2) ne fournit aucun moyen de comprendre les entrées de la sortie.
Ajout:
4 + 3 = 7
Cela peut être inversé en prenant la somme et en soustrayant l'un des addends
7 - 3 = 4
Multiplication:
4 * 5 = 20
Cela peut être inversé en prenant le produit et en le divisant par l'un des facteurs
20 / 4 = 5
division Modulo:
22 % 7 = 1
Cela ne peut pas être inversé car vous ne pouvez effectuer aucune opération sur le quotient et le dividende pour reconstituer le diviseur (ou vice versa).
Pouvez-vous trouver une opération pour remplir où le "?" est?
1 ? 7 = 22
1 ? 22 = 7
Cela étant dit, les fonctions de hachage unidirectionnelles ont la même qualité mathématique que la division modulo.
Disons que je vous ai donné une clé d'un casier dans un terminal de bus qui a mille casiers et vous ai demandé de la remettre à mon banquier. Étant le gars intelligent que vous êtes, sans parler de suspect, vous regarderiez immédiatement la clé pour voir quel numéro de casier est écrit sur la clé. Sachant cela, j'ai fait quelques choses sournoises; d'abord, j'ai trouvé deux nombres qui, lorsqu'ils sont divisés en utilisant la division modulo, me donnent un nombre compris entre 1 et 1000, deuxièmement j'ai effacé le nombre d'origine et écrit dessus le diviseur de la paire de nombres, deuxièmement j'ai choisi un terminal de bus qui a un garde protégeant les casiers des mécréants en ne laissant les gens essayer qu'un seul casier par jour avec leur clé, troisième le banquier connaît déjà le dividende, donc quand il obtient la clé, il peut faire le calcul et comprendre le reste et savoir quel casier ouvrir.
Si je choisis judicieusement les opérandes, je peux me rapprocher d'une relation un à un entre le quotient et le dividende qui vous oblige à essayer chaque casier car la réponse répartit les résultats des entrées possibles sur la plage de nombres souhaités, les casiers disponible dans le terminal. Fondamentalement, cela signifie que vous ne pouvez pas acquérir de connaissances sur le reste, même si vous connaissez l'un des opérandes.
Donc, maintenant, je peux vous "faire confiance" pour remettre la clé à son propriétaire légitime sans vous soucier de savoir à quel casier il appartient. Bien sûr, vous pourriez fouiller par force tous les casiers, mais cela prendrait près de 3 ans, beaucoup de temps pour mon banquier pour utiliser la clé et vider le casier.
Voir les autres réponses pour plus de détails sur les différentes fonctions de hachage.
Voici un exemple très simple. Supposons que je suis un cryptographe débutant et que je crée une fonction de hachage qui fait ce qui suit:
int SimpleHash(file) {
return 0 if file.length is even;
return 1 if file.length is odd;
}
Voici maintenant le test. SimpleHash(specialFile)
est 0. Quel était mon fichier d'origine?
Évidemment, il n'y a aucun moyen de savoir (bien que vous puissiez probablement découvrir assez facilement que mon hachage est basé sur la longueur du fichier). Il n'y a aucun moyen de "reconstituer" mon fichier en fonction du hachage car le hachage ne contient pas tout ce que mon fichier contenait.
En termes simples, une fonction de hachage fonctionne en créant un gros gâchis emmêlé des données d'entrée.
Voir MD5 par exemple. Il traite les données d'entrée par blocs de 512 bits. Chaque bloc est divisé en 16 mots de 32 bits. Il y a 64 étapes, chaque étape utilisant l'un des 16 mots d'entrée. Ainsi, chaque mot est utilisé quatre fois au cours de l'algorithme. C'est de là que vient le sens unique: n'importe quel bit d'entrée est entré à plusieurs endroits, et entre deux de ces entrées, la fonction mélange toutes les données actuelles de sorte que chaque bit d'entrée affecte la plupart de l'état de fonctionnement de 128 bits. Cela vous empêche d'inverser la fonction ou de calculer une collision en ne regardant qu'une partie des données. Vous devez regarder l'ensemble des 128 bits, et l'espace des blocs de 128 bits est trop large pour être parcouru efficacement.
Maintenant, MD5 ne fait pas un bon travail, car des collisions pour cette fonction peuvent être trouvées. D'un point de vue cryptographique, MD5 est une fonction de cryptage rotatif. Le traitement d'un bloc de messages M (512 bits) utilise un état d'entrée V (une valeur de 128 bits) et calcule le nouvel état V 'comme V' = V + E (M, V) où '+' est un mot- addition sage, et "E" se trouve être une fonction de chiffrement symétrique (alias un "chiffrement par blocs") qui utilise M comme clé et V comme message à chiffrer. À y regarder de plus près, E can est une sorte de "réseau Feistel étendu", semblable au chiffrement par blocs DES, avec quatre quarts au lieu de deux moitiés. Les détails ne sont pas importants ici; mon point est que ce qui rend une "bonne" fonction de hachage, parmi les fonctions de hachage qui utilisent cette structure (appelée "Merkle-Damgård"), est similaire à ce qui rend un chiffrement de bloc "sécurisé". Les attaques par collision réussies sur MD5 utilisent la cryptanalyse différentielle, un outil qui a été conçu pour attaquer les chiffres de bloc en premier lieu.
D'un bon chiffrement de bloc à une bonne fonction de hachage, il y a une étape qui ne doit pas être ignorée. Avec la structure Merkle-Damgård, la fonction de hachage est sécurisée si le chiffrement de bloc sous-jacent est résistant aux "attaques de clés associées", une propriété plutôt obscure contre laquelle les chiffrements de blocs sont rarement renforcés car, pour le chiffrement symétrique, les attaques de clés associées n'ont pratiquement aucune pratique impact. Par exemple, le cryptage AES s'est avéré ne pas être aussi résistant aux attaques de clés associées que l'on pouvait souhaiter, et cela n'a pas déclenché de panique générale. Cette résistance ne faisait pas partie des propriétés recherchées lors de la conception de l'AES. Cela empêche simplement de transformer l'AES en fonction de hachage. Il existe une fonction de hachage appelée Whirlpool, qui s'appuie sur un dérivé de Rijndael, "Rijndael" étant le nom initial de ce qui est devenu l'AES; mais Whirlpool prend soin de modifier les parties de Rijndael qui sont faibles aux attaques clés associées.
En outre, il existe d'autres structures qui peuvent être utilisées pour créer une fonction de hachage. Les fonctions standard actuelles (MD5, SHA-1 et la famille "SHA-2", alias SHA-224, SHA-256, SHA-384 et SHA-512) sont des fonctions de Merkle-Damgård, mais la plupart des potentiels les successeurs ne le sont pas. Il y a un concours en cours, organisé par le NIST (l'organisation fédérale américaine qui s'occupe de ce genre de choses), pour sélectionner une nouvelle fonction de hachage standard, baptisée "SHA-3". Voir cette page pour plus de détails. À l'heure actuelle, ils sont à 14 candidats sur les 51 initiaux (sans compter une douzaine supplémentaires qui ont échoué au test administratif d'envoi d'une soumission complète avec un code qui se compile et s'exécute correctement).
Ayons maintenant un aspect plus conceptuel. Une fonction de hachage sécurisée devrait ressembler à un Oracle aléatoire : un Oracle est une boîte noire qui, lorsqu'elle reçoit un message [~ # ~] m [~ # ~] en entrée, génère une réponse h (M) qui est choisis au hasard, uniformément, dans l'espace de sortie (c'est-à-dire toutes n - chaînes de bits si la longueur de sortie de la fonction de hachage est n ). S'il reçoit à nouveau le même message [~ # ~] m [~ # ~] en entrée, Oracle sort la même valeur que précédemment. En dehors de cette restriction, la sortie d'Oracle sur une entrée non utilisée précédemment [~ # ~] m [~ # ~] est imprévisible. On peut imaginer l'Oracle comme un conteneur pour un gnome qui jette des dés et enregistre soigneusement les messages d'entrée et les sorties correspondantes dans un grand livre, afin qu'il honore son contrat Oracle. Il n'y a aucun moyen de prédire quelle sera la prochaine sortie car le gnome lui-même ne le sait pas.
Si un Oracle aléatoire existe, alors inverser la fonction de hachage a un coût 2 ^ n : pour avoir une sortie donnée, il n'y a pas de meilleure stratégie que d'utiliser des messages d'entrée distincts jusqu'à ce que l'un donne la valeur attendue. En raison de la sélection aléatoire uniforme, la probabilité de réussite est de 1/(2 ^ n) à chaque essai, et le nombre moyen de demandes aux dés- lancer gnome sera 2 ^ n . Pour les collisions (trouver deux entrées distinctes qui produisent la même valeur de hachage), le coût est d'environ * 1,4 * 2 ^ (n/2) * (grosso modo, avec * 1,4 * 2 ^ (n/2) * sorties, nous pouvons assembler environ 2 ^ n paires de sorties, chacune ayant une probabilité de 1/(2 ^ n) d'appariement, c'est-à-dire ayant deux entrées distinctes qui ont la même sortie). Ce sont les meilleurs que l'on puisse faire avec un Oracle aléatoire.
Par conséquent, nous recherchons des fonctions de hachage qui sont aussi bonnes qu'un Oracle aléatoire: elles doivent mélanger les données d'entrée de telle manière que nous ne pouvons pas trouver une collision plus efficacement que ce qu'il en coûterait pour simplement invoquer la fonction 2 ^ (n/2) fois. Le fléau de la fonction de hachage est une structure mathématique, c'est-à-dire des raccourcis qui permettent à l'attaquant de visualiser l'état interne de la fonction de hachage (qui est grand, au moins n bits) comme une variation sur un objet mathématique qui vit dans un espace beaucoup plus court. 30 ans de recherche publique sur les systèmes de chiffrement symétrique ont produit tout un attirail de notions et d'outils (diffusion, avalanche, différentiels, linéarité ...) applicables. En bout de ligne, cependant, nous n'avons aucune preuve qu'un Oracle aléatoire puisse réellement exister. Nous voulons une fonction de hachage qui ne peut pas être attaquée. Ce que nous avons sont des candidats à la fonction de hachage, pour lesquels aucune attaque n'est actuellement connue , et, un peu mieux, nous avons certaines fonctions pour lesquelles certains types d'attaques peuvent s'avérer ne pas fonctionner.
Il y a encore des recherches à faire.
Un hachage est un encodage (très) avec perte.
Pour vous donner un exemple plus simple, imaginez un encodage fictif à 2 lettres d'un mot à 5 lettres appelé X-encoding. L'algorithme pour l'encodage X est simple: prenez les première et dernière lettres du mot.
Alors,
X-encode( SAUCE ) = SE
X-encode( BLOCK ) = BK
De toute évidence, vous ne pouvez pas reconstruire SAUCE à partir de son encodage SE (en supposant que notre gamme d'entrées possibles est composée de 5 mots). La Parole pourrait tout aussi bien être ESPACE.
Soit dit en passant, le fait que SAUCE et SPACE produisent tous deux SE comme un encodage est appelé collision, et vous pouvez voir que l'écodage X ne ferait pas un très bon hachage. :)
tableau
Avec quelques strabisme, les tableaux associatifs ressemblent beaucoup à des hachages. Les principales différences étaient l'absence de symbole% sur les noms de hachage, et que l'on ne pouvait leur affecter qu'une clé à la fois. Ainsi, on dirait $foo{'key'} = 1;
, Mais seulement @keys = keys(foo);
. Les fonctions familières comme chacune, les clés et les valeurs fonctionnaient comme elles le font maintenant (et la suppression a été ajoutée en Perl 2).
Perl 3 avait trois types de données entiers: il avait le symbole% sur les noms de hachage, permettait d'affecter un hachage entier à la fois, et ajoutait dbmopen (maintenant déconseillé en faveur de la liaison). Perl 4 a utilisé des clés de hachage séparées par des virgules pour émuler des tableaux multidimensionnels (qui sont désormais mieux gérés avec des références de tableau).
Perl 5 a fait le grand saut en faisant référence aux tableaux associatifs comme des hachages. (Pour autant que je sache, c'est la première langue à avoir fait référence à la structure de données ainsi, plutôt qu'à "table de hachage" ou quelque chose de similaire.) Ironiquement, il a également déplacé le code pertinent de hash.c à hv.c.
Nomenclature
Les dictionnaires, comme expliqué précédemment, sont des collections non ordonnées de valeurs indexées par des clés uniques. Ils sont parfois appelés tableaux ou cartes associatifs. Ils peuvent être implémentés de plusieurs manières, dont l'une en utilisant une structure de données connue sous le nom de table de hachage (et c'est ce que Perl appelle un hachage).
L'utilisation par Perl du terme "hachage" est une source de confusion potentielle, car la sortie d'une fonction de hachage est aussi parfois appelée hachage (en particulier dans des contextes cryptographiques), et parce que les tables de hachage ne sont généralement pas appelées hachages ailleurs.
Pour être sûr, faites référence à la structure de données comme une table de hachage et n'utilisez le terme "hachage" que dans des contextes évidents et spécifiques à Perl.