#include <stdio.h>
#include <string.h>

#include <openssl/evp.h>

#ifdef DEBUG
#define DBG 1
#else
#define DBG 0
#endif

#define MAX_SIZE_BUFF 200

unsigned char *simple_digest(char *algth, char *buffer, unsigned int len, int *olen){

	EVP_MD *m;
	EVP_MD_CTX ctx;
	unsigned char *ret;
	
	OpenSSL_add_all_digests ();
	if (!(m = (EVP_MD*) EVP_get_digestbyname(algth)))
		return NULL;
	
	if (!(ret = (unsigned char *) malloc(EVP_MAX_MD_SIZE)))
		return NULL;
	
	EVP_DigestInit(&ctx, m);
	EVP_DigestUpdate(&ctx, buffer, len);
	EVP_DigestFinal(&ctx, ret, olen);
	
	return ret;
}

void hex_print(unsigned char *buff,int len){
	int i;
	for(i=0;i<len;i++)
		printf("%02x",(unsigned char)(buff[i]&0xFF));	
}

void strtohex(unsigned char *in, unsigned char *out,int len){
	int i;
	char tmp[3];
	tmp[2]=0;
	for(i=0;i<len/2;i++){
		tmp[0]=in[2*i];
		tmp[1]=in[2*i+1];
		out[i]=strtol(tmp,NULL,16);
	}
}

int main(int argc, char **argv){

	int tries=0;
	unsigned char buff_words[MAX_SIZE_BUFF];
	unsigned char hash[16];
	unsigned char *line=NULL;
	int len=100,read;
	int olen;
	char *out;
	
	if(argc<3) {
	        printf("Usage: mymd5crack /path/to/hashfile /path/to/dictfile\n");
        	exit(1);
	}
	
	FILE *hashfile;
	hashfile = fopen(argv[1],"r");
	if(!hashfile){
		perror(argv[1]);
	return -1;
	}

	
	FILE *dictfile;
	dictfile = fopen(argv[2],"r");
	if(!dictfile){
		perror(argv[2]);
	return -1;
	}
	
	read = getline(&line, &len, hashfile);
	if(strlen(line)!=33){
		fprintf(stderr,"ERROR: Invalid hash length %d\n",strlen(line));
		return -1;
	}	
	
	strtohex(line,hash,32);
		
	if(DBG){
			printf("Input hash: %s\n", line);
			printf("Input buffer from hash: ");
			hex_print(hash,16);
			printf("\n\n");
	}
	
	//Read words in a loop
	while((read = getline(&line, &len, dictfile)) != -1){
		if( strlen(line) < 200){
			tries++;	
				
			//Copy word into buffer
			strcpy(buff_words,line);
			
			if(DBG)
				printf("Input buffer from dict: %s \n",buff_words);
			// compute md5
			out = simple_digest("md5",buff_words,strlen(line)-1,&olen);
			
			if(DBG){	
				printf("For password %s MD5 is: ",line);
				hex_print(out,olen);
				printf("\n\n");	
			}
				
			//Compare computed md5 with hash
			if(memcmp(out,hash,16) == 0){
			
				printf("PASSWORD FOUND!! in %d tries: %s\n",tries,line);
					
				fclose(hashfile);
				fclose(dictfile);
				free(out);
				if(line)
					free(line);
				
				return 0;	
			}
			free(out);
		}else{
			printf("\nWords from dict too long... cough*, cough*...\n");
		}
	}
	
	printf("Password not found in %d tries!\n",tries);
	
	if(line)
		free(line);
		
	fclose(hashfile);
	fclose(dictfile);
	
	return 0;
}

