Différences
Ci-dessous, les différences entre deux révisions de la page.
| Les deux révisions précédentes Révision précédente Prochaine révision | Révision précédente | ||
| tc_info:private_s5-tpa2 [2018/12/09 21:48] – edauce | tc_info:private_s5-tpa2 [2020/12/11 11:01] (Version actuelle) – edauce | ||
|---|---|---|---|
| Ligne 1: | Ligne 1: | ||
| + | ==== Fonctions de hachage ==== | ||
| + | |||
| + | **Rappel** | ||
| + | Soit $E$ un ensemble de messages de taille quelconque. On souhaite //indexer// ces messages à l'aide d'une fonction d' | ||
| + | |||
| + | La //fonction de hachage// : | ||
| + | * " | ||
| + | * doit être telle que la probabilité de choisir le même identifiant pour deux messages différents soit extrêmement faible. | ||
| + | |||
| + | === Etape 1 : transcodage binaire des données === | ||
| + | |||
| + | L' | ||
| + | |||
| + | <note important> | ||
| + | Il existe différents encodages binaires possibles pour les caractères : | ||
| + | * le code ASCII code les caractères du clavier anglais sur 7 bits, ce qui permet d' | ||
| + | * ainsi : | ||
| + | <code python> | ||
| + | code = ord('/' | ||
| + | print(code) | ||
| + | </ | ||
| + | * | ||
| + | * affiche la valeur '' | ||
| + | * La norme UTF-8 encode les caractères sur un nombre d' | ||
| + | * Exemple : le smiley ''' | ||
| + | <code python> | ||
| + | code = ord(' | ||
| + | print(code) | ||
| + | </ | ||
| + | * On peut inversement afficher le caractère à partir de son code entier : | ||
| + | <code python> | ||
| + | print(chr(233)) | ||
| + | print(chr(119070)) | ||
| + | </ | ||
| + | </ | ||
| + | | ||
| + | Pour traduire une //chaîne de caractères// | ||
| + | * ainsi, dans le système décimal, la position du chiffre dans le nombre définit à quelle puissance de 10 il appartient (unité, dizaines, centaines, etc...) Le chiffre le plus à gauche a la puissance la plus élevée et celui le plus à droite la puissance la plus faible. | ||
| + | * Si on suppose, pour simplifier, que chaque caractère est codé par un entier entre 0 et 255 (soit le code ASCII " | ||
| + | * Un tel nombre s' | ||
| + | * Il existe une fonction '' | ||
| + | * Exemple : | ||
| + | <code python> | ||
| + | s = ' | ||
| + | b = s.encode() | ||
| + | </ | ||
| + | Un nombre en base 256 est difficile à lire et interpréter. On le traduit en base 10 : | ||
| + | <code python> | ||
| + | i = int.from_bytes(b, | ||
| + | print(" | ||
| + | </ | ||
| + | Ce qui donne : | ||
| + | < | ||
| + | i = 852806586114976881510056778471769180697471859150728801241505293627173168229624211058 | ||
| + | </ | ||
| + | |||
| + | Ce code est difficilement exploitable. Rappelons que l'on souhaite un code relativement compact pour indexer nos données (ici des adresses e-mail) | ||
| + | |||
| + | === Etape 2 : Réduction du code === | ||
| + | |||
| + | L' | ||
| + | |||
| + | Soit '' | ||
| + | <code python> | ||
| + | def H_code(s, n): | ||
| + | b = s.encode() | ||
| + | i = int.from_bytes(b, | ||
| + | | ||
| + | </ | ||
| + | * Avantage : | ||
| + | * le code retourné est plus compact | ||
| + | * Inconvénient: | ||
| + | * si $n$ est une puissance de 2, ce codage revient à sélectionner les bits de poids faible. En effet, pour un nombre exprimé en base 2, la division entière par $2^h$ a pour résultat les bits de poids fort $>h$ et pour reste les $h$ bits de poids faible. | ||
| + | * deux données différentes peuvent alors avoir le même code si elles se terminent de la même façon | ||
| + | * Exemple : $n = 2^{32} = 4294967296$ : | ||
| + | * H_code('' | ||
| + | * H_code('' | ||
| + | * deux données proches ou très similaires auront un index proche ou similaire : si '' | ||
| + | * Exemple : $n = 2^{32} = 4294967296$ : | ||
| + | * H_code('' | ||
| + | * H_code('' | ||
| + | |||
| + | ---> il faut prendre n //premier// : en effet, si n est premier > 2, ses multiples ne sont pas des puissances de 2, et la division entière par $n$ présente un risque faible de ne sélectionner que les bits de poids fort. | ||
| + | **Exemple **: | ||
| + | * $n = 67280421310721$ (premier): | ||
| + | * H_code('' | ||
| + | * H_code('' | ||
| + | |||
| + | Néanmoins, de par les propriétés de la division entière, le reste de '' | ||
| + | |||
| + | **Exemple :** | ||
| + | * $n = 67280421310721$ (premier): | ||
| + | * H_code('' | ||
| + | * H_code('' | ||
| + | |||
| + | === Etape 3 : combiner produit et modulo === | ||
| + | |||
| + | Soient m et n deux nombres premiers entre eux : | ||
| + | <code python> | ||
| + | def H_code(s, m, n): | ||
| + | b = s.encode() | ||
| + | i = int.from_bytes(b, | ||
| + | | ||
| + | </ | ||
| + | * Avantage : | ||
| + | * deux entiers proches donneront auront des codes très différents : si '' | ||
| + | --> il est préférable de prendre $m > n$, pour que les valeurs entières $i$ et $i+1$ produisent des codes arbitrairement éloignés sur l' | ||
| + | * Inconvénient : | ||
| + | * deux données différentes peuvent toujours avoir le même code | ||
| + | * le produit '' | ||
| + | |||
| + | === Collision de codes ==== | ||
| + | |||
| + | On appelle // | ||
| + | $$H(s_1)=H(s_2)\text{ avec }s_1 \neq s_2$$ | ||
| + | |||
| + | On vous donne les fonctions d' | ||
| + | |||
| + | <code python> | ||
| + | def encode(s): | ||
| + | # chaine de caractères --> entiers naturels | ||
| + | if type(s) == bytes: | ||
| + | b = s | ||
| + | else: | ||
| + | b = s.encode() | ||
| + | i = int.from_bytes(b, | ||
| + | return i | ||
| + | </ | ||
| + | |||
| + | <code python> | ||
| + | def decode(i): | ||
| + | # entiers naturels --> chaîne de caractères | ||
| + | h = hex(i) | ||
| + | try: | ||
| + | b = bytes.fromhex(h[2: | ||
| + | except: | ||
| + | b = bytes.fromhex(' | ||
| + | try: | ||
| + | s = b.decode() #" | ||
| + | except: | ||
| + | s = b | ||
| + | return s | ||
| + | </ | ||
| + | |||
| + | ainsi que la fonction de hachage : | ||
| + | <code python> | ||
| + | P1 = 67280421310721 | ||
| + | P2 = 32416188517 | ||
| + | def H_code(s, p = P1, m = P2): | ||
| + | i = encode(s) | ||
| + | return (i * p) % m | ||
| + | </ | ||
| + | |||
| + | Il est assez simple de trouver deux messages de même code en modifiant les derniers caractères. | ||
| + | |||
| + | Par exemple, si on part de l' | ||
| + | <code python> | ||
| + | print(H_code(" | ||
| + | </ | ||
| + | '' | ||
| + | <code python> | ||
| + | print(H_code(" | ||
| + | </ | ||
| + | '' | ||
| + | |||
| + | <note tip> **QUESTION ** | ||
| + | |||
| + | Sans rien changer aux fonctions '' | ||
| + | |||
| + | Exemple : | ||
| + | * Votre adresse mail : '' | ||
| + | * Réponse attendue : '' | ||
| + | |||
| + | < | ||
| + | * Pour répondre, vous devez remplir le formulaire à l' | ||
| + | {{https:// | ||
| + | --> </ | ||
| + | |||
| + | </ | ||