Présentation:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
/*
* Fonction de hachage simple avec sel
* Retourne une valeur de hash non-signée
*/
unsigned long int hash_djb2_salt(const char *str, const char *salt)
{
unsigned long int hash = 5381;
const char *s;
if (str == NULL)
{
return 0;
}
/* Appliquer d'abord le sel */
if (salt != NULL)
{
s = salt;
while (*s != '\0') {
hash = ((hash << 5) + hash) + (unsigned char)*s;
s++;
}
}
/* Puis la chaîne principale */
s = str;
while (*s != '\0')
{
hash = ((hash << 5) + hash) + (unsigned char)*s;
s++;
}
return hash;
}
/*
* Fonction de hachage alternative type sdbm avec sel
*/
unsigned long int hash_sdbm_salt(const char *str, const char *salt)
{
unsigned long int hash = 0;
const char *s;
if (str == NULL)
{
return 0;
}
/* Appliquer d'abord le sel */
if (salt != NULL)
{
s = salt;
while (*s != '\0')
{
hash = (unsigned char)*s + (hash << 6) + (hash << 16) - hash;
s++;
}
}
/* Puis la chaîne principale */
s = str;
while (*s != '\0')
{
hash = (unsigned char)*s + (hash << 6) + (hash << 16) - hash;
s++;
}
return hash;
}
/*
* Fonction de hachage très simple pour débutants avec sel
*/
unsigned long int hash_simple_salt(const char *str, const char *salt)
{
unsigned long int hash = 0;
const unsigned long int prime = 31;
const char *s;
if (str == NULL)
{
return 0;
}
/* Appliquer d'abord le sel */
if (salt != NULL)
{
s = salt;
while (*s != '\0')
{
hash = (hash * prime) + (unsigned char)*s;
s++;
}
}
/* Puis la chaîne principale */
s = str;
while (*s != '\0')
{
hash = (hash * prime) + (unsigned char)*s;
s++;
}
return hash;
}
/*
* Version originale sans sel (pour compatibilité)
*/
unsigned long int hash_djb2(const char *str)
{
return hash_djb2_salt(str, NULL);
}
unsigned long int hash_sdbm(const char *str)
{
return hash_sdbm_salt(str, NULL);
}
unsigned long int hash_simple(const char *str)
{
return hash_simple_salt(str, NULL);
}
/*
* Convertit un hash en chaîne hexadécimale
*/
static void hash_to_hex(unsigned long int hash, char *hex_buffer, size_t buf_size)
{
if (buf_size >= 17)
{
(void)sprintf(hex_buffer, "%08lX", hash);
}
else if (buf_size > 0)
{
hex_buffer[0] = '\0';
}
}
/*
* Génère un sel aléatoire simple
*/
static void generate_salt(char *salt_buffer, size_t length)
{
static const char charset[] =
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789"
"./";
size_t i;
static int seeded = 0;
if (length < 1)
{
return;
}
/* Initialisation simple du générateur aléatoire */
if (!seeded)
{
srand((unsigned int)time(NULL));
seeded = 1;
}
/* Génération du sel */
for (i = 0; i < length - 1; i++)
{
int key = rand() % (int)(sizeof(charset) - 1);
salt_buffer[i] = charset[key];
}
salt_buffer[length - 1] = '\0';
}
/*
* 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, " --salt \"SEL\" Utiliser un sel specifique\n");
fprintf(stderr, " --random-salt Genere un sel aleatoire\n");
fprintf(stderr, " -h Afficher cette aide\n");
}
/*
* Programme principal
*/
int main(int argc, char *argv[])
{
const char *input_string = NULL;
const char *salt = NULL;
int algorithm = 0; /* 0=simple, 1=djb2, 2=sdbm */
int show_all = 0;
char random_salt[17]; /* 16 caractères + null */
int i;
/* Analyse des arguments */
for (i = 1; i < argc; i++)
{
if (argv[i][0] == '-')
{
if (strcmp(argv[i], "--salt") == 0 && i + 1 < argc)
{
salt = argv[++i];
}
else
if (strcmp(argv[i], "--random-salt") == 0)
{
generate_salt(random_salt, sizeof(random_salt));
salt = random_salt;
}
else
{
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];
printf("Resultats pour: \"%s\"\n", input_string);
if (salt != NULL) {
printf("Sel utilise: \"%s\"\n", salt);
}
printf("Longueur: %lu caracteres\n",
(unsigned long)strlen(input_string));
printf("\n");
printf("Algorithme Hash (decimal) Hash (hex)\n");
printf("------------- --------------- ----------\n");
hash1 = hash_simple_salt(input_string, salt);
hash_to_hex(hash1, hex_buffer, sizeof(hex_buffer));
printf("Simple %-19lu 0x%s\n", hash1, hex_buffer);
hash2 = hash_djb2_salt(input_string, salt);
hash_to_hex(hash2, hex_buffer, sizeof(hex_buffer));
printf("DJB2 %-19lu 0x%s\n", hash2, hex_buffer);
hash3 = hash_sdbm_salt(input_string, salt);
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_salt(input_string, salt);
algo_name = "simple";
break;
case 1:
hash = hash_djb2_salt(input_string, salt);
algo_name = "djb2";
break;
case 2:
hash = hash_sdbm_salt(input_string, salt);
algo_name = "sdbm";
break;
default:
hash = hash_simple_salt(input_string, salt);
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);
if (salt != NULL) {
printf("Sel: \"%s\"\n", salt);
}
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;
}
