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/06 12: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 2h 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=232=4294967296 : | ||
+ | * H_code('' | ||
+ | * H_code('' | ||
+ | * deux données proches ou très similaires auront un index proche ou similaire : si '' | ||
+ | * Exemple : n=232=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(s1)=H(s2) avec s1≠s2 | ||
+ | |||
+ | 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:// | ||
+ | --> </ | ||
+ | |||
+ | </ | ||