Présentation du hash:
Un hash, c’est une empreinte digitale numérique unique et de taille fixe créée à partir de n’importe quelle donnée, qui permet de l’identifier et de vérifier qu’elle n’a pas été modifiée.
Exemple de fonctions de hashage sous linux
# 1. md5sum - Donne un "code" de 32 caractères
echo "hello" | md5sum
# Résultat : 5d41402abc4b2a76b9719d911017c592
# 2. sha256sum - Code plus long (64 caractères)
echo "hello" | sha256sum
# Résultat : 2cf24dba5fb0a30e...
# 3. Vérifier qu'un fichier n'a pas été modifié
sha256sum mon_fichier.txt > checksum.txt
# Plus tard...
sha256sum -c checksum.txt # Vérifie si le fichier a changé
Code en C simple pour la pédagogie , hash.c
usage:
etudiant@ordi:~/Works/hash$ ./hash -h
Usage: ./hash [options] "chaine a hasher"
Options:
-s Utiliser l'algorithme simple (defaut)
-d Utiliser l'algorithme djb2
-m Utiliser l'algorithme sdbm
-a Afficher tous les algorithmes
-h Afficher cette aide
etudiant@ordi:~/Works/hash$
code: hash.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*
* Fonction de hachage simple inspirée de djb2
* Retourne une valeur de hash non-signée
*/
unsigned long int hash_djb2(const char *str)
{
unsigned long int hash = 5381;
int c;
if (str == NULL)
{
return 0;
}
while ((c = *str++) != '\0')
{
/* hash * 33 + c */
hash = ((hash << 5) + hash) + c;
}
return hash;
}
/*
* Fonction de hachage alternative type sdbm
*/
unsigned long int hash_sdbm(const char *str)
{
unsigned long int hash = 0;
int c;
if (str == NULL)
{
return 0;
}
while ((c = *str++) != '\0')
{
hash = c + (hash << 6) + (hash << 16) - hash;
}
return hash;
}
/*
* Fonction de hachage très simple pour débutants
* (plus facile à comprendre)
*/
unsigned long int hash_simple(const char *str)
{
unsigned long int hash = 0;
const unsigned long int prime = 31;
const char *p;
if (str == NULL)
{
return 0;
}
p = str;
while (*p != '\0')
{
hash = (hash * prime) + (unsigned long int)(*p);
p++;
}
return hash;
}
/*
* Convertit un hash en chaîne hexadécimale
* Le buffer doit avoir au moins 17 octets (16 hex + null)
*/
void hash_to_hex(unsigned long int hash, char *hex_buffer, size_t buf_size)
{
/*
* ANSI C n'a pas de snprintf, on utilise sprintf avec vérification
* On suppose que buf_size >= 17 pour un long int (8 octets = 16 hex)
*/
if (buf_size >= 17)
{
(void)sprintf(hex_buffer, "%08lX", hash);
}
else if (buf_size > 0)
{
hex_buffer[0] = '\0'; /* Buffer trop petit */
}
}
/*
* Affiche l'utilisation du programme
*/
static void print_usage(const char *prog_name)
{
fprintf(stderr, "Usage: %s [options] \"chaine a hasher\"\n", prog_name);
fprintf(stderr, "Options:\n");
fprintf(stderr, " -s Utiliser l'algorithme simple (defaut)\n");
fprintf(stderr, " -d Utiliser l'algorithme djb2\n");
fprintf(stderr, " -m Utiliser l'algorithme sdbm\n");
fprintf(stderr, " -a Afficher tous les algorithmes\n");
fprintf(stderr, " -h Afficher cette aide\n");
}
/*
* Programme principal
*/
int main(int argc, char *argv[])
{
const char *input_string = NULL;
int algorithm = 0; /* 0=simple, 1=djb2, 2=sdbm */
int show_all = 0;
int i;
/* Analyse des arguments */
for (i = 1; i < argc; i++)
{
if (argv[i][0] == '-')
{
switch (argv[i][1])
{
case 's':
algorithm = 0;
break;
case 'd':
algorithm = 1;
break;
case 'm':
algorithm = 2;
break;
case 'a':
show_all = 1;
break;
case 'h':
print_usage(argv[0]);
return 0;
default:
fprintf(stderr, "Option inconnue: %s\n", argv[i]);
print_usage(argv[0]);
return 1;
}
}
else
{
input_string = argv[i];
}
}
/* Si aucune chaîne fournie, on utilise un exemple */
if (input_string == NULL)
{
fprintf(stderr, "Aucune chaine fournie.\n");
print_usage(argv[0]);
printf("\nExemple d'utilisation:\n");
input_string = "Hello, World!";
printf("Chaine par defaut: \"%s\"\n\n", input_string);
}
/* Calcul et affichage des hashs */
if (show_all)
{
unsigned long int hash1, hash2, hash3;
char hex_buffer[17]; /* 16 caractères hexa + null terminator */
hash1 = hash_simple(input_string);
hash2 = hash_djb2(input_string);
hash3 = hash_sdbm(input_string);
printf("Resultats pour: \"%s\"\n", input_string);
printf("Longueur: %lu caracteres\n",
(unsigned long)strlen(input_string));
printf("\n");
printf("Algorithme Hash (decimal) Hash (hex)\n");
printf("------------- --------------- ----------\n");
hash_to_hex(hash1, hex_buffer, sizeof(hex_buffer));
printf("Simple %-19lu 0x%s\n", hash1, hex_buffer);
hash_to_hex(hash2, hex_buffer, sizeof(hex_buffer));
printf("DJB2 %-19lu 0x%s\n", hash2, hex_buffer);
hash_to_hex(hash3, hex_buffer, sizeof(hex_buffer));
printf("SDBM %-19lu 0x%s\n", hash3, hex_buffer);
}
else
{
unsigned long int hash;
char hex_buffer[17];
const char *algo_name;
switch (algorithm)
{
case 0:
hash = hash_simple(input_string);
algo_name = "simple";
break;
case 1:
hash = hash_djb2(input_string);
algo_name = "djb2";
break;
case 2:
hash = hash_sdbm(input_string);
algo_name = "sdbm";
break;
default:
hash = hash_simple(input_string);
algo_name = "simple";
break;
}
hash_to_hex(hash, hex_buffer, sizeof(hex_buffer));
printf("Algorithme: %s\n", algo_name);
printf("Chaine: \"%s\"\n", input_string);
printf("Hash (decimal): %lu\n", hash);
printf("Hash (hexadecimal): 0x%s\n", hex_buffer);
printf("Taille du hash: %lu bits\n",
(unsigned long)sizeof(hash) * 8);
}
return EXIT_SUCCESS;
}
Dans notre programme nous proposons 3 type d’algorithmes
hash_simple
avec monia donner l’organigramme de cet algorithme et PL
djb2
avec monia donner l’organigramme de cet algorithme et PL
sdbm
avec monia donner l’organigramme de cet algorithme et PL
