Bonjour.
Voici un programme que j'ai codé. Je vous le poste pour 2 choses:
=> Pour le partager (normal j'ai envie de dire et sa va dans l'idée/optique de la communauté)
=> Une quelconque optimisation.
En aucun celui-ci fais office de tutoriel ou autre. Mais il peu être pris en exemple pour l'implémentation d'option, savoir comment vérifier qu'un char appartient a un ensemble ou autre.
Le but du programme est simple. En passant les paramètres qui vont bien, on ne fait que hasher une chaine de caratères (
char *crypt (const char *clef, const char *salt)) dans le format choisi:
md5
blowfish
sha256
sha512
Comme certains le verront surement , je me suis appuyé sur le format /etc/shadow.
Le salt est par défault généré aléatoirement, mais il est possible de pouvoir mettre son propre salt (option -s). Il ne vous sera demandé que les 8 caractères. Les
$n$ et le
$ de fin du salt seront rajoutés automatiquement. le
n entre les
$ aura une valeur en fonction du type de hashage choisi:
1 - md5
2 - blowfish
5 - sha256
6 - sha512
Voici le code:
Code :
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 255
#define MD5 "md5"
#define BLOWFISH "blowfish"
#define SHA256 "sha256"
#define SHA512 "sha512"
#define SIZE_SALT 13
#define SIZE_S 8
#define TYPE_CHAR "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/."
char *crypt (const char *clef, const char *salt);
char *strtok( char *str1, const char *str2 );
/********************************************************************
void salt_gene(char [], char );
Fonction génération du salt:
Arguments:
buf[]: buffer vide afin de stocker le salt
type: Numero du type de hashage
- 1: md5
- 2: blowfish
- 5: SHA256
- 6: SHA512
Action:
Cette fonction génère aleatoirement une chaine de caractères
dans l'ensemble suivant:
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/."
********************************************************************/
void salt_gene(char buf[SIZE_SALT], char type)
{
int i;
srand(time(NULL));
buf[0]='$';
buf[1]=type;
buf[2]='$';
for (i=3; i < 11;i++){
buf[i]=(TYPE_CHAR)[rand() % 64];
}
buf[11]='$';
buf[12]='\0';
}
/************************************************************************
void usage();
Fonction d'affichage du menu.
Arguments:
Aucun!
Action:
Affiche le menu d'aide et quit le programme avec un statut de 1
************************************************************************/
void usage() {
printf("Usage:\nhash -c [CHAINE A HASHER] -t [md5|blowfish|sha256|sha512] -s [SALT] -v -h\n\nOptions:\n");
printf("\t-c:\tchaine de caractère a hasher. (Option Obligatoire)\n");
printf("\t-t:\tType de hashage (md5:blowfish:sha256:sha512). (Option Obligatoire)\n");
printf("\t-s:\tDéfini le salt désiré. [SIZE => 8 char]\n");
printf("\t \tCaractères autorisés:\n");
printf("\t \t[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/.]\n");
printf("\t-v:\tMode verbose.\n");
printf("\t-h:\tAffiche ce menu.\n");
exit(1);
}
/************************************************************************
void check_arg(int , char **);
Fonction de gestion de paramètres obligatoire
Arguments:
nb: est tout simplement argc. Cad le nombre de paramètres
passé
chaine: est tout simplement argv[].
Action:
Check tout les paramètres passé et verifie si les options -c -t
sont bien présentes. Si oui on continue le programme, Si non on
affiche le menu d'aide et cloture le programme.
************************************************************************/
void check_arg(int nb, char **chaine) {
int opt_c = 0, opt_t = 0, i;
for ( i = 0; i < nb; i++) {
if (strcmp(chaine[i], "-c") == 0)
opt_c = 1;
if (strcmp(chaine[i], "-t") == 0)
opt_t = 1;
}
if (!opt_c)
usage();
else if (!opt_t)
usage();
}
/************************************************************************
void check_salt(char [], char );
Fonction de check de l'arg de l'option -s
Argument:
salt[]: cahine de caractères choisi par l'$USER
type: Numero du type de hashage
- 1: md5
- 2: blowfish
- 5: SHA256
- 6: SHA512
Action: cette fonction a pour but de parser la chaine de caractères
saisie par l'$USER et de checker si celui-ci n'a pas saisie
de mauvais caractères.
Les caractères autorisés sont:
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/.
************************************************************************/
void check_salt(char salt[SIZE_S], char type){
char carac[]=TYPE_CHAR, tab[SIZE_S];
int i, j, check;
memset(tab, 0, SIZE_S);
strncpy(tab, salt, SIZE_S);
salt[0]='$';
salt[1]=type;
salt[2]='$';
for (i = 0; i < SIZE_S ; i++){
check = 0;
j = 0;
while(j<strlen(carac)) {
if (tab[i] == carac[j]) {
check = 1;
}
j++;
}
if (check == 0)
usage();
else
salt[i+3] = tab[i];
}
salt[11]='$';
salt[12]='\0';
}
int main (int argc, char* argv[])
{
//Avant de tout initialiser, on check le nombre d'arguments
if (argc < 2)
usage();
else {
//On va déjà check les arguments OBLIGATOIRES comme le -t et -c
check_arg(argc, argv);
//Le salt fait 8 caratères de long + $n$ au début et $\0 a la fin donc 13
char type = {0}, salt[SIZE_SALT], buffer[256], option[]="hc:t:s:v", type_Name[10];
int verbose = 0, opt = 0, opt_s = 0;
//Initialisation des tab
memset(buffer, 0, 255);
memset(salt, 0, SIZE_SALT);
memset(type_Name, 0,10);
//Check des arg
while((opt=getopt(argc, argv, option)) != -1) {
switch(opt) {
case 'c':
strncpy(buffer, optarg, MAX);
break;
case 't':
if (strcmp(optarg, MD5) == 0) {
strcpy(type_Name, MD5);
type = '1';
}
else if (strcmp(optarg, BLOWFISH) == 0){
strcpy(type_Name, BLOWFISH);
type = '2';
}
else if (strcmp(optarg, SHA256) == 0) {
strcpy(type_Name, SHA256);
type = '5';
}
else if (strcmp(optarg, SHA512) == 0) {
strcpy(type_Name, SHA512);
type = '6';
}
break;
case 'v':
verbose = 1;
break;
case 's':
if ((strlen(optarg) > SIZE_S) || (strlen(optarg) < SIZE_S)) {
usage();
}
else {
strncpy(salt, optarg, SIZE_SALT);
check_salt(salt, type);
opt_s = 1;
}
break;
case 'h':
usage();
break;
}
}
//Génération du salt
if (!opt_s)
salt_gene(salt, type);
//Si mode verbose on affiche ttes les infos
if (verbose)
printf("Salt: %s\nChaine à hasher: %s\nType de hash: %s\n\nRésultat: %s\n", salt, buffer, type_Name,crypt(buffer,salt));
//Sinon juste le résultat
else
printf("Résultat: %s\n", crypt(buffer,salt));
}
return 0;
}
voici un lien pour une meilleur vision:
http://silentd.root-me.org/scripts/hash1.c.html
Pour les personnes qui le téléchargerons, il vous faudrat rajouter
-lcrypt comme option a gcc.
Code :
gcc -o hash1 hash1.c -lcrypt
L'option -h vous donnera les différentes options.
J'ai essayé de commenter les fonctions un maximum. Comme vous pourrez le voir, je pose trés peu de commentaire l'intérieur de celle-ci mais préfère expliquer leur fonctionnement dans un bloc de commentaire situé juste au dessus de celle-ci.
Je suis ouvert à toutes "réflextions" sur le code car celles-ci ne peuvent qu'être bénéfiques. Aussi bien pour moi (faut savoir être égoîste un peu des fois :p) mais aussi pour ceux qui liront la discussion et qui désirent approfondir leur connaissances.
Il doit certainement y avoir des exploitations diverses a ce code. Donc certainement des choses à en dire alors comme dirais un ami (qui se reconnaitra)
"bah go!"
On est loin du programme de fou qui va faire tourner la planète a l'envers hein

. Je suis juste dans une démarche de partage et de "perfectionnement" aussi bien personelle que communautaire.
Junky
PS: vous avez la source ici:
http://silentd.root-me.org/scripts/sourc...es/hash1.c