|
//
********************************************
// Nom : EnableSecret.cpp
// Auteur : sebastien.fontaine@authsecu.com.pas.de.spam
// Date de création : 11 Janvier 2007
// version : 1.0.3.12
// Licence : Cette executable est libre de toute utilisation.
// La seule condition existante est de faire référence
// au site http://www.authsecu.com afin de respecter le
travail d'autrui.
// ********************************************
// ********************************************************
// Les includes
// ********************************************************
// Il faut ajouter dans les proprités du projet => C++ => Command Line :
// /I "C:\RepPerso\Personnel\Developpement\Projets\LibrairieSocket"
#include "LibrairieSocket.h"
#include "conio.h" // Nécessaire pour le getch()
#include "md5.version.crypt.h"
// ********************************************************
// Les Librairies
// ********************************************************
// ********************************************************
// Les procédures
// ********************************************************
void initiation_des_variables(void);
void gestion_des_arguments(int argc, char* argv[]);
void hash_brute_force(void);
void hash_dictionnaire(void);
DWORD WINAPI interception_des_touches(LPVOID lpParameter);
void affichage_des_statistiques(void);
void sauvegarde(void);
void chargement(char *);
void variation_majuscule(char *);
void cryptage(char *);
char * md5_crypt(const char *, const char *);
// ********************************************************
// Les constantes
// ********************************************************
#define TAILLE_MAX_MOT
20 // Définit la tallie maximal du mot en
claire
#define NB_DE_FICHIER 4096 //
Définir le nombre de fichier qui recevront les hash
#define PROFONDEUR_DU_TABLEAU 80000 // Définit le la
taille de chaque char* du tableau
// ********************************************************
// Les variables
// ********************************************************
char enable_secret[1000];
// Chaine complète de l'enable secret
char salt[7];
// Première partie de enable_secret
char password_crypte[22];
// Chaine MD5 de enable_secret
char * mot_hasher;
// Chaine de caractere hashé
char *tableau_des_caracteres; //
Tableau possédant les caractères à tester
char *tableau_des_caracteres_variant; // Tableau possédant
les caractères à varier
bool sortie_boucles;
// Booléan permettant de synchroniser les deux thread (touche et hash)
int
compteur;
// Compte le nombre de hash effectué
// *2 sinon plantage sur des mot de 12 caracteres en mode
dico+variation. Pas trouvé la solution
char mot_brut_force[TAILLE_MAX_MOT*2]; // Mot en
claire dans la fonction brute force
char mot_dictionnaire[TAILLE_MAX_MOT]; // Mot en
claire dans la fonction dicotionnaire
char chaine_de_demarrage[TAILLE_MAX_MOT]; // Chaine contenant le mot à
démarrer en cas de reprise
int heure_de_depart;
// Définit l'heure de départ du traitement
unsigned short longueur_maxi; //
Longueur maximal de la chaine en brut force
bool dicionnaire_active;
// Active le brut force à partir d'un dictionnaire
char *fichier_du_dico;
// Nom du fichier pour lire le dictionnaire
char *fichier_a_sauvegarder; //
Nom du fichier pour sauvegarder la position
unsigned short nombre_de_variation_avant; // Définit le nombre de
caractere a varié avant les mots
unsigned short nombre_de_variation_apres; // Définit le nombre de
caractere a varié après les mots
bool view;
// Active l'affichage
bool
minuscule;
// Active la variation du disctionnaire majuscule minuscule
bool la_chaine_est_trouvee;
// Indique si le mot de passe à été décrypté
FILE *pointeur_vidage_dico;
// Déclare le pointeur de fichier pour lire le dictionnaire
int main (int argc, char* argv[])
{
DWORD id_du_thread_touche;
// Id du thread touche
initiation_des_variables();
gestion_des_arguments(argc,argv);
printf ("\nPassword crypté : %s",enable_secret);
// ********************************************************
// Vérifie le format du password
// ********************************************************
if ( (strlen(enable_secret)!=30) || (strncmp(enable_secret,"$1$",3))
|| (enable_secret[7]!='$') )
{
printf ("\nFormat du password incorrect");
exit(0);
}
// ********************************************************
// Séparation du password
// ********************************************************
strncpy(salt,enable_secret,8);
salt[8]='\0';
strncpy(password_crypte,enable_secret+8,22);
password_crypte[22]='\0';
// ********************************************************
// Appel de la fonction interception_des_touches dans un
process différent
// ********************************************************
CreateThread(NULL,0,interception_des_touches,NULL,0,&id_du_thread_touche);
Sleep(1); // Permet d'être sur que l'affichage suivant aura
lieu (l'autre process pourrais terminer en moin d'une seconde)
// ********************************************************
// Prend les chaine à haser soit du mode brut force ou du
dico
// ********************************************************
if (dicionnaire_active==true)
hash_dictionnaire();
else
hash_brute_force();
// ********************************************************
// Affiche le resultat de sortie
// ********************************************************
if (la_chaine_est_trouvee==true)
printf("\nYes, the password was found. It's :
%s",mot_brut_force);
else
printf("\nSorry, but the password was not found");
printf("\n");
}
void initiation_des_variables(void)
{
// ********************************************************
// Affichage de la banniere
// ********************************************************
printf("\nCisco5 - Brut Force all Cisco Password 5 (enable
secret) - Version 1.0.3.12");
printf("\nCreate on January 11, 2007, Last compilation on
January 16, 2007");
printf("\nCreated by sebastien.fontaine@authsecu.com");
printf("\n");
// ********************************************************
// Initialisation des options générales
// ********************************************************
view=false;
// ********************************************************
// Initialisation du Password
// ********************************************************
strcpy(enable_secret,"$1$8.K7$PjHq5g/20wsd05yj5EAwl/");
// ********************************************************
// Initiation brut force
// ********************************************************
longueur_maxi=20;
tableau_des_caracteres="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789*$%!";
fichier_a_sauvegarder="save.txt";
// ********************************************************
// Initiation des statistiques
// ********************************************************
heure_de_depart=GetTickCount();
compteur=0;
// ********************************************************
// Initiation du dico
// ********************************************************
dicionnaire_active=false;
fichier_du_dico="dictionnary.txt";
nombre_de_variation_avant=0;
nombre_de_variation_apres=0;
tableau_des_caracteres_variant="0123456789";
minuscule=false;
sortie_boucles=false;
la_chaine_est_trouvee=false;
}
void gestion_des_arguments(int argc,char* argv[])
{
char *caractere_non_convertit;
int i;
// ********************************************************
// Affichage de l'aide
// ********************************************************
if ( (argc>1) && (strcmp(argv[1],"-?")==0) || (argc==1) )
{
printf("\n");
printf("\nGENERAL OPTIONS");
printf("\n-? This help");
printf("\n-view View the
results Default: %d (1 => Activate)",view);
printf("\n\nPASSWORD");
printf("\n-password Enable
Secret Defaut: None");
printf("\n");
printf("\nBRUT FORCE");
printf("\n-maximum_length Maximum
caracters Default: %d",longueur_maxi);
printf("\n-characters Separate with
\"\" Default: %s",tableau_des_caracteres);
printf("\n-save_name Name of save
file Default: %s",fichier_a_sauvegarder);
printf("\n-load_name Name of load
file Default: (specify one name for activate the load)");
printf("\n");
printf("\nDICTIONNARY");
printf("\n-dictionnary Test
dictionnary Default: %d (1 => Activate)",dicionnaire_active);
printf("\n-file_name_dico Name of the
file Default: %s",fichier_du_dico);
printf("\n-variable_before Lenght of
variant Default: %d",nombre_de_variation_avant);
printf("\n-variable_after Lenght of
variant Default: %d",nombre_de_variation_apres);
printf("\n-variable_characters Separate with
\"\" Default: %s",tableau_des_caracteres_variant);
printf("\n-capital_letter Maj/min
variation Default: %d",minuscule);
printf("\n\nSAMPLE");
printf("\nEnableSecret -password $1$/oqx$.3HyeKPEryag7w3u4H0n0/
");
printf("\n\n");
exit(0);
}
// ********************************************************
// Récupération des arguments
// ********************************************************
for (i=1;i<argc;i=i+1)
{
//
********************************************************
// Choix généraux
//
********************************************************
if ( (stricmp(argv[i],"-view")==0) || (stricmp(argv[i],"/view")==0)
)
if (strtod(argv[i+1],&caractere_non_convertit)==0)
view=false;
else
view=true;
//
********************************************************
// Options PASSWORD
//
********************************************************
if ( (stricmp(argv[i],"-password")==0) || (stricmp(argv[i],"/password")==0)
)
strcpy(enable_secret,argv[i+1]);
//
********************************************************
// Choix brut force
//
********************************************************
if ( (stricmp(argv[i],"-maximum_length")==0) ||
(stricmp(argv[i],"/maximum_length")==0) )
longueur_maxi=(unsigned short)strtod(argv[i+1],&caractere_non_convertit);
if ( (stricmp(argv[i],"-characters")==0) || (stricmp(argv[i],"/characters")==0)
)
tableau_des_caracteres=argv[i+1];
if ( (stricmp(argv[i],"-save_name")==0) || (stricmp(argv[i],"/save_name")==0)
)
fichier_a_sauvegarder=argv[i+1];
if ( (stricmp(argv[i],"-load_name")==0) || (stricmp(argv[i],"/load_name")==0)
)
chargement(argv[i+1]);
//
********************************************************
// Choix Dictionnaire
//
********************************************************
if ( (stricmp(argv[i],"-dictionnary")==0) || (stricmp(argv[i],"/dictionnary")==0)
)
if (strtod(argv[i+1],&caractere_non_convertit)==0)
dicionnaire_active=false;
else
dicionnaire_active=true;
if ( (stricmp(argv[i],"-file_name_dico")==0) ||
(stricmp(argv[i],"/file_name_dico")==0) )
fichier_du_dico=argv[i+1];
if ( (stricmp(argv[i],"-variable_before")==0) ||
(stricmp(argv[i],"/variable_before")==0) )
nombre_de_variation_avant=(unsigned
short)strtod(argv[i+1],&caractere_non_convertit);
if ( (stricmp(argv[i],"-variable_after")==0) ||
(stricmp(argv[i],"/variable_after")==0) )
nombre_de_variation_apres=(unsigned
short)strtod(argv[i+1],&caractere_non_convertit);
if ( (stricmp(argv[i],"-variable_characters")==0)
|| (stricmp(argv[i],"/variable_characters")==0) )
tableau_des_caracteres_variant=argv[i+1];
if ( (stricmp(argv[i],"-capital_letter")==0) ||
(stricmp(argv[i],"/capital_letter")==0) )
if (strtod(argv[i+1],&caractere_non_convertit)==0)
minuscule=false;
else
minuscule=true;
}
}
void hash_brute_force(void)
{
int tableau_compteur[256]; // Permet de suivre
l'incrémentation des caractères du mot
unsigned int compteur_de_sortie;
unsigned int i,j;
unsigned nombre_de_caractere;
// ********************************************************
// Initialisation du tableau
// ********************************************************
if (chaine_de_demarrage[0]=='\0')
{
for (i=0;i<256;i++)
tableau_compteur[i]=-1;
tableau_compteur[0]=0;
}
else
{
//
********************************************************
// Reprend les positions du mot de démarrage
//
********************************************************
for (i=0;i<strlen(chaine_de_demarrage);i++)
for (j=0;j<strlen(tableau_des_caracteres);j++)
if (chaine_de_demarrage[i]==tableau_des_caracteres[j])
tableau_compteur[strlen(chaine_de_demarrage)-1-i]=j;
//
********************************************************
// Fini le tableau des position par -1
//
********************************************************
for (i=(int)strlen(chaine_de_demarrage);i<256;i++)
tableau_compteur[i]=-1;
//
********************************************************
// Copy le mot de démarrage dans le
mot_brut_force qui sera traité
//
********************************************************
memcpy(mot_brut_force,chaine_de_demarrage,strlen(chaine_de_demarrage));
}
// ********************************************************
// Boucle
// ********************************************************
while (!sortie_boucles&&!la_chaine_est_trouvee)
{
//
********************************************************
// Initialisation des compteurs de suivi
//
********************************************************
compteur_de_sortie=0;
nombre_de_caractere=0;
//
********************************************************
// Compte le nombre de caractere à afficher
//
********************************************************
for (i=0;i<longueur_maxi;i++)
if (tableau_compteur[i]!=-1)
nombre_de_caractere++;
//
********************************************************
// Recupération du mot en inverse
//
********************************************************
for (i=0;i<nombre_de_caractere;i++)
if (tableau_compteur[i]!=-1)
mot_brut_force[nombre_de_caractere-1-i]=tableau_des_caracteres[tableau_compteur[i]];
mot_brut_force[nombre_de_caractere]='\0';
if ( (nombre_de_variation_avant!=0) && (nombre_de_variation_apres!=0)
)
//
********************************************************
// Ajoute le mot du dictionnaire au début et à
la fin
//
********************************************************
{
size_t len_brut=strlen(mot_brut_force);
size_t len_dico=strlen(mot_dictionnaire);
char brut[100];
strcpy(brut,mot_brut_force);
if (len_brut<=nombre_de_variation_avant)
{
memcpy(mot_brut_force+len_brut,mot_dictionnaire,len_dico);
mot_brut_force[len_brut+len_dico]='\0';
}
else
{
memcpy(mot_brut_force+nombre_de_variation_avant,mot_dictionnaire,len_dico);
memcpy( mot_brut_force+ nombre_de_variation_avant+ len_dico,brut+nombre_de_variation_avant, len_brut-nombre_de_variation_avant);
mot_brut_force[len_dico+len_brut]='\0';
}
}
else if (nombre_de_variation_avant!=0)
//
********************************************************
// Ajoute le mot du dictionnaire à la fin
//
********************************************************
{
memcpy(mot_brut_force+ strlen(mot_brut_force), mot_dictionnaire,strlen(mot_dictionnaire));
mot_brut_force[strlen(mot_brut_force)+strlen(mot_dictionnaire)]='\0';
}
else if (nombre_de_variation_apres!=0)
//
********************************************************
// Ajoute le mot du dictionnaire au début
//
********************************************************
{
memcpy(mot_brut_force+ strlen(mot_dictionnaire), mot_brut_force,strlen(mot_brut_force)+1);
memcpy(mot_brut_force,mot_dictionnaire,strlen(mot_dictionnaire));
mot_brut_force[strlen(mot_dictionnaire)+strlen(mot_brut_force)]='\0';
}
//
********************************************************
// Incrémentation du tableau
//
********************************************************
for (i=0;i<longueur_maxi;i++)
{
if (compteur_de_sortie==i)
tableau_compteur[i]++;
if (tableau_compteur[i]==(int)strlen(tableau_des_caracteres))
{
tableau_compteur[i]=0;
compteur_de_sortie++;
}
}
//
********************************************************
// Condition de sortie
//
********************************************************
if (compteur_de_sortie==longueur_maxi)
sortie_boucles=true;
//
********************************************************
// Cryptage du mot
//
********************************************************
cryptage(mot_brut_force);
//
********************************************************
// Comparaison
//
********************************************************
if (strcmp(mot_hasher,enable_secret)==0)
la_chaine_est_trouvee=true;
}
// ********************************************************
// Initialise la condition de boucle pour la prochaine
utilisation (cas du disco variant)
// ********************************************************
sortie_boucles=false;
}
void hash_dictionnaire(void)
{
size_t positionnement_du_retour_charriot;
bool est_ce_une_lettre=false;
// ********************************************************
// Ouverture du dictionnaire en mode lecture et mode texte
// ********************************************************
pointeur_vidage_dico=fopen(fichier_du_dico,"rt");
// ********************************************************
// Boucle parcourrant le dicotionnaire
// ********************************************************
while(!feof(pointeur_vidage_dico)&&!la_chaine_est_trouvee)
{
//
********************************************************
// Récupération de la ligne en cours
//
********************************************************
fgets(mot_dictionnaire,400,pointeur_vidage_dico);
//
********************************************************
// Supprime le retour charriot à la fin des
lignes
//
********************************************************
positionnement_du_retour_charriot=strlen(mot_dictionnaire)-1;
// Permet d'éviter d'utiliser deux fois strlen
if (mot_dictionnaire[positionnement_du_retour_charriot]==10)
mot_dictionnaire[positionnement_du_retour_charriot]='\0';
//
********************************************************
// Définit si le premier caractère est une
lettre
//
********************************************************
if ( (mot_dictionnaire[0]>=65)&&(mot_dictionnaire[0]<=90)
|| (mot_dictionnaire[0]>=97)&&(mot_dictionnaire[0]<=122) )
est_ce_une_lettre=true;
else
est_ce_une_lettre=false;
if ( (nombre_de_variation_avant!=0) || (nombre_de_variation_apres!=0)
)
//
********************************************************
// Varation du mot en ajoutant des caracteres à
la fin
//
********************************************************
{
tableau_des_caracteres=tableau_des_caracteres_variant;
longueur_maxi=nombre_de_variation_avant+nombre_de_variation_apres;
strcpy(mot_brut_force,mot_dictionnaire);
// La sauvegarde se base sur mot_brut_force
//
********************************************************
// Test le mot du dictionnaire avant
de passer à sa variation
//
********************************************************
cryptage(mot_dictionnaire);
//
********************************************************
// Passe à sa variation si c'est pas
trouvé
//
********************************************************
if (strcmp(mot_hasher,enable_secret)!=0)
//
********************************************************
// Variation du mot
//
********************************************************
hash_brute_force();
}
else if (minuscule==true)
//
********************************************************
// Varation du mot en modifiant toutes les
lettres Minuscule et Majuscule
//
********************************************************
{
strcpy(mot_brut_force,mot_dictionnaire); // La sauvegarde se base sur
mot_brut_force
variation_majuscule(mot_dictionnaire);
}
else
{
//
********************************************************
// Pas de varation. Traitement normal du mot
//
********************************************************
strcpy(mot_brut_force,mot_dictionnaire); // La sauvegarde se base sur
mot_brut_force
cryptage(mot_dictionnaire);
}
//
********************************************************
// Comparaison
//
********************************************************
if (strcmp(mot_hasher,enable_secret)==0)
la_chaine_est_trouvee=true;
}
}
DWORD WINAPI interception_des_touches(LPVOID lpParameter)
{
int i;
int depart_de_la_mesure;
int compteur_courrant;
// ********************************************************
// Affichage des possibilités
// ********************************************************
printf ("\n(s)-Statistiques (b)backup
(q)-Quit\n\n");
// ********************************************************
// Boucle d'interception des touches
// ********************************************************
while (sortie_boucles==false)
{
switch (getch())
{
case 's':
affichage_des_statistiques();
printf("\nWord per second
: .");
depart_de_la_mesure=GetTickCount();
compteur_courrant=compteur;
for (i=0;i<10;i++)
{
Sleep(300);
printf(".");
}
printf("
%d/s\n", ((1000*(compteur-compteur_courrant))/ (GetTickCount()-depart_de_la_mesure)));
break;
case 'q':
printf("\n");
sauvegarde();
sortie_boucles=true;
break;
case 'b':
sauvegarde();
break;
}
}
return 0;
}
void affichage_des_statistiques(void)
{
int jour,heure,minute,seconde;
int tempo;
// ********************************************************
// Calcul des variables
// ********************************************************
tempo=(GetTickCount()-heure_de_depart);
jour=tempo/(1000*60*60*24);
heure=(tempo%(1000*60*60*24))/(1000*60*60); // % signifie
modulo. c'est à dire le reste de la division entière
minute=(tempo%(1000*60*60))/(1000*60);
seconde=(tempo%(1000*60))/(1000);
// ********************************************************
// Affichage des statistiques
// ********************************************************
printf("\nTest number : %d",compteur);
printf("\nLast word : %s",mot_brut_force);
printf("\nTime from begin : %d day and
%.2d:%.2d:%.2d",jour,heure,minute,seconde);
}
void sauvegarde(void)
{
FILE *pointeur_du_fichier_sauvegarde; // Déclare
le pointeur de fichier pour enregistrer la position
// ********************************************************
// Ouverture du fichier
// ********************************************************
pointeur_du_fichier_sauvegarde=fopen(fichier_a_sauvegarder,"w");
// ********************************************************
// Ecris les poisitions
// ********************************************************
fprintf(pointeur_du_fichier_sauvegarde,"%d\n",longueur_maxi);
fprintf(pointeur_du_fichier_sauvegarde,"%s\n",mot_brut_force);
fprintf(pointeur_du_fichier_sauvegarde,"%d\n",compteur);
fprintf(pointeur_du_fichier_sauvegarde,"%d",GetTickCount()-heure_de_depart);
// ********************************************************
// Ferme le fichier
// ********************************************************
fclose(pointeur_du_fichier_sauvegarde);
// ********************************************************
// Message d'information
// ********************************************************
printf ("Sauvegarde du mot %s effectuee dans le fichier :
%s\n", mot_brut_force,fichier_a_sauvegarder);
}
void chargement(char * fichier_a_charger)
{
char *caractere_non_convertit;
FILE *pointeur_du_fichier_chargement; // Déclare le
pointeur de fichier pour enregistrer la position
char contenu_de_la_ligne[400]="";
// ********************************************************
// Ouverture du dictionnaire en mode lecture et mode texte
// ********************************************************
pointeur_du_fichier_chargement=fopen(fichier_a_charger,"rt");
// ********************************************************
// Récupération de la ligne 1 : La longueur Maxi
// ********************************************************
fgets(contenu_de_la_ligne,400,pointeur_du_fichier_chargement);
longueur_maxi=(unsigned
short)strtod(contenu_de_la_ligne,&caractere_non_convertit);
// ********************************************************
// Récupération de la ligne 2 : Le mot de démarrage
// ********************************************************
fgets(chaine_de_demarrage,400,pointeur_du_fichier_chargement);
chaine_de_demarrage[strlen(chaine_de_demarrage)-1]='\0'; //
Supprime le retour charriot
// ********************************************************
// Récupération de la ligne 3 : Le compteur
// ********************************************************
fgets(contenu_de_la_ligne,400,pointeur_du_fichier_chargement);
compteur=(int)strtod(contenu_de_la_ligne,&caractere_non_convertit);
// ********************************************************
// Récupération de la ligne 4 : Le temps
// ********************************************************
fgets(contenu_de_la_ligne,400,pointeur_du_fichier_chargement);
heure_de_depart=(int)strtod(contenu_de_la_ligne,&caractere_non_convertit);
printf("\nMot : %s",chaine_de_demarrage);
printf("\ncompteur : %d",compteur);
printf("\nTemps : %d",heure_de_depart);
// ********************************************************
// Ferme le fichier
// ********************************************************
fclose(pointeur_du_fichier_chargement);
}
void variation_majuscule(char * mot_a_varier)
{
size_t longueur;
unsigned compteur_tampon;
unsigned int i,j;
unsigned int tampon;
char * mot_en_cours_de_variation;
mot_en_cours_de_variation=(char *)malloc(100);
longueur=strlen(mot_a_varier);
compteur_tampon=2<<(longueur-1); // Equivalent à
(int)pow(2,longueur); (2 exposant longueur)
// ********************************************************
// Passe la chaine en minuscule
// ********************************************************
strcpy(mot_a_varier,strlwr(mot_a_varier));
// ********************************************************
// Boucle parcourrant toutes les combinaisons
// ********************************************************
for (i=0;i<compteur_tampon;i++)
{
strcpy(mot_en_cours_de_variation,mot_a_varier);
for (j=0;j<longueur;j++)
{
tampon=i;
tampon=tampon>>j;
tampon=tampon&1;
if ( (tampon==1) &&
(mot_en_cours_de_variation[j]>=97) &&
(mot_en_cours_de_variation[j]<=122) )
mot_en_cours_de_variation[j]=mot_en_cours_de_variation[j]-32;
}
//
********************************************************
// Cryptage du mot varié
//
********************************************************
cryptage(mot_en_cours_de_variation);
//
********************************************************
// Comparaison
//
********************************************************
if (strcmp(mot_hasher,enable_secret)==0)
{
//
********************************************************
// Permet que ce soit le mot en cour
de variation qui sera affiché comme trouvé
//
********************************************************
strcpy(mot_brut_force,mot_en_cours_de_variation);
//
********************************************************
// Quitte la boucle FOR
//
********************************************************
break;
}
}
}
void cryptage(char * tampon_mot_de_passe)
{
// ********************************************************
// Cryptage MD5 avec le Salt
// ********************************************************
mot_hasher=md5_crypt(tampon_mot_de_passe,salt);
// ********************************************************
// Affichage du Hash
// ********************************************************
if (view==true)
printf("%s-%s\n",tampon_mot_de_passe,mot_hasher);
// ********************************************************
// Incrémente le compteur pour connaitre le nombre de hash
effectué
// ********************************************************
compteur++;
}
char * md5_crypt(const char * pw, const char * salt)
{
static char base64[]=
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
struct MD5_CONTEXT outer_context, inner_context;
MD5_DIGEST digest;
unsigned pwl=strlen(pw);
unsigned l;
unsigned i, j;
char *p;
static char buffer[100];
if (*salt == '$' && salt[1] == '1' && salt[2] == '$')
salt += 3;
for (l=0; l<8 && salt[l] && salt[l] != '$'; l++);
md5_context_init(&inner_context);
md5_context_hashstream(&inner_context, pw, pwl);
md5_context_hashstream(&inner_context, salt, l);
md5_context_hashstream(&inner_context, pw, pwl);
md5_context_endstream(&inner_context, pwl*2+l);
md5_context_digest(&inner_context, digest);
md5_context_init(&outer_context);
md5_context_hashstream(&outer_context, pw, pwl);
md5_context_hashstream(&outer_context, "$1$", 3);
md5_context_hashstream(&outer_context, salt, l);
for (i=pwl; i; )
{
j=i;
if (j > 16) j=16;
md5_context_hashstream(&outer_context, digest,
j);
i -= j;
}
j=pwl*2+l+3;
for (i=pwl; i; i >>= 1)
{
md5_context_hashstream(&outer_context, (i & 1) ?
"": pw, 1);
++j;
}
md5_context_endstream(&outer_context, j);
md5_context_digest(&outer_context, digest);< |