md5sum of file in Linux C - c

I want to find md5sum of a file in Linux C, Is there any API where I can send file name to get md5sum of that file.

There's code here.
Also, the openssl libs have md5 functions (from here):
#include <openssl/md5.h>
#include <unistd.h>
int main()
{
int n;
MD5_CTX c;
char buf[512];
ssize_t bytes;
unsigned char out[MD5_DIGEST_LENGTH];
MD5_Init(&c);
bytes=read(STDIN_FILENO, buf, 512);
while(bytes > 0)
{
MD5_Update(&c, buf, bytes);
bytes=read(STDIN_FILENO, buf, 512);
}
MD5_Final(out, &c);
for(n=0; n<MD5_DIGEST_LENGTH; n++)
printf("%02x", out[n]);
printf("\n");
return(0);
}

You can use popen to run md5sum and read the output:
#include <stdio.h>
#include <ctype.h>
#define STR_VALUE(val) #val
#define STR(name) STR_VALUE(name)
#define PATH_LEN 256
#define MD5_LEN 32
int CalcFileMD5(char *file_name, char *md5_sum)
{
#define MD5SUM_CMD_FMT "md5sum %." STR(PATH_LEN) "s 2>/dev/null"
char cmd[PATH_LEN + sizeof (MD5SUM_CMD_FMT)];
sprintf(cmd, MD5SUM_CMD_FMT, file_name);
#undef MD5SUM_CMD_FMT
FILE *p = popen(cmd, "r");
if (p == NULL) return 0;
int i, ch;
for (i = 0; i < MD5_LEN && isxdigit(ch = fgetc(p)); i++) {
*md5_sum++ = ch;
}
*md5_sum = '\0';
pclose(p);
return i == MD5_LEN;
}
int main(int argc, char *argv[])
{
char md5[MD5_LEN + 1];
if (!CalcFileMD5("~/testfile", md5)) {
puts("Error occured!");
} else {
printf("Success! MD5 sum is: %s\n", md5);
}
}

You can use the mhash library (license is LGPL). On Debian systems:
sudo apt-get install libmhash-dev
See the man page man 3 mhash
But I don't think you can just give it the name of a file. You have to open the file yourself, read the data, and feed the data to this library's functions.

An easy answer to the question asked by Raja and using answer from sje397, the md5sum of a file can be calculated within the C program as below. Also notice that there is no need of writing the read command twice when you can use the do while loop.
int calculate_md5sum(char *filename)
{
//open file for calculating md5sum
FILE *file_ptr;
file_ptr = fopen(filename, "r");
if (file_ptr==NULL)
{
perror("Error opening file");
fflush(stdout);
return 1;
}
int n;
MD5_CTX c;
char buf[512];
ssize_t bytes;
unsigned char out[MD5_DIGEST_LENGTH];
MD5_Init(&c);
do
{
bytes=fread(buf, 1, 512, file_ptr);
MD5_Update(&c, buf, bytes);
}while(bytes > 0);
MD5_Final(out, &c);
for(n=0; n<MD5_DIGEST_LENGTH; n++)
printf("%02x", out[n]);
printf("\n");
return 0;
}

If you're looking to generate MD5 hash for a file and compare it with a string, you can use this.
Here, I have used D'Nabre's code from another SO answer and Michael Foukarakis's hex string to byte array code from this SO answer.
It needs to be linked against the OpenSSL library (gcc md5.c -o md5 -lssl) to work.
Sample usage:
unsigned char *file_hash = md5_for_file("~/testfile");
if (md5_is_match_str(file_hash, "b7be4ec867f9b0286b91dd40178774d6")) {
printf("Match\n");
} else {
printf("Mismatch\n");
}
free(file_hash);
md5.h:
#ifndef MD5_H
#define MD5_H
/** Caller to free result */
unsigned char *md5_for_file(char *filename);
/** md5_1 & md5_2 maybe NULL */
int md5_is_match(unsigned char *md5_1, unsigned char *md5_2);
/** md5 maybe NULL */
int md5_is_match_str(unsigned char *md5, const char *md5_str);
#endif //MD5_H
md5.c:
#include "md5.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/md5.h>
// Print the MD5 sum as hex-digits.
void print_md5_sum(unsigned char *md) {
int i;
for (i = 0; i < MD5_DIGEST_LENGTH; i++) {
printf("%02x", md[i]);
}
printf("\n");
}
// Get the size of the file by its file descriptor
unsigned long get_size_by_fd(int fd) {
struct stat statbuf;
if (fstat(fd, &statbuf) < 0) exit(-1);
return statbuf.st_size;
}
unsigned char *md5_for_file(char *filename) {
int file_descript;
unsigned long file_size;
char *file_buffer;
unsigned char *result = malloc(sizeof(*result) * MD5_DIGEST_LENGTH);
if (NULL == result) {
printf("malloc failed\n");
goto END;
}
printf("using file:\t%s\n", filename);
file_descript = open(filename, O_RDONLY);
if (file_descript < 0) exit(-1);
file_size = get_size_by_fd(file_descript);
printf("file size:\t%lu\n", file_size);
file_buffer = mmap(0, file_size, PROT_READ, MAP_SHARED, file_descript, 0);
MD5((unsigned char *) file_buffer, file_size, result);
munmap(file_buffer, file_size);
print_md5_sum(result);
END:
return result;
}
int md5_is_match(unsigned char *md5_1, unsigned char *md5_2) {
if (!md5_1 || !md5_2) {
return 0;
}
int i;
for (i = 0; i < MD5_DIGEST_LENGTH; i++) {
if (md5_1[i] != md5_2[i]) {
return 0;
}
}
return 1;
}
int md5_is_match_str(unsigned char *md5, char *md5_str) {
if (!md5 || !md5_str) { return 0; }
/** Make byte arrary from md5_str */
unsigned char md5_arr[MD5_DIGEST_LENGTH] = {0};
const char *pos = md5_str;
size_t count = 0;
/* WARNING: no sanitization or error-checking whatsoever */
for (count = 0; count < sizeof(md5_arr) / sizeof(md5_arr[0]); count++) {
sscanf(pos, "%2hhx", &md5_arr[count]);
pos += 2;
}
for (count = 0; count < sizeof(md5_arr) / sizeof(md5_arr[0]); count++) {
printf("%02x", md5_arr[count]);
}
printf("\n");
/** actual comparison */
if (memcmp(md5, md5_arr, MD5_DIGEST_LENGTH)) {
return 0;
}
return 1;
}

Related

How to use read() function to read data from a file in C?

I would like to read data from a file, I need to open file in binary form and read blocks of data at a time?
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc,char* argv[])
{
int n;
FILE * fp;
size_t nbyte;
unsigned char * buffer[1024];
fp=open("file_test.txt",O_RDONLY);
read(fp,buffer,1);
printf("%s\n",buffer[0]);
close(fp);
return 0;
}
open/read is the POSIX version of fopen/fread, open does not return FILE* pointer.
unsigned char * buffer[1024]; is for array of character strings. You just need a buffer unsigned char buffer[1024];
printf("%s\n",...); is for printing c-string, it cannot print binary data in general.
int main(void)
{
int fin = open("file_test.txt", O_BINARY | O_RDONLY);
if (!fin)
return 0;
unsigned char buffer[1024];
while (1)
{
size_t size = read(fin, buffer, sizeof(buffer));
if (size == 0)
break;
for (size_t i = 0; i < size; i++)
printf("%02X ", buffer[i]);
//break; print the whole file!
}
close(fin);
return 0;
}

reading file`s lines char by char into char** array

I wrote the next function that tries to read and enter each line from text file into a string array in c :
int main(int argc,char* argv[])
{
char ** lines;
readFile(argv[1],lines);
}
int readFile(char* filePath,char** lines)
{
char file_char;
int letter_in_line=0;
int line=1;
char* line_string=malloc(1024);
int j=1;
int fd=open(filePath,O_RDONLY);
if (fd < 0)
{
return 0;
}
while (read(fd,&file_char,1) >0)
{
if(file_char != '\n' && file_char != '0x0')
{
line_string[letter_in_line] = file_char;
letter_in_line++;
}
else
{
if(lines != NULL)
{
lines=(char**)realloc(lines,sizeof(char*)*line);
}
else
{
lines=(char**)malloc(sizeof(char*));
}
char* line_s_copy=strdup(line_string);
lines[line-1]=line_s_copy;
line++;
letter_in_line=0;
memset(line_string,0,strlen(line_string));
}
j++;
}
printf("cell 0 : %s",lines[0]);
return 1;
}
I have 2 questions :
1)Whenever the code reaches the print of cell 0, I'm getting
Segmentation fault (core dumped) error. What is wrong ?
2)In case I
want to see the changes in the lines array in my main, I should pass
&lines to the func and get char*** lines as an argument ? In
addition, I will need to replace every 'line' keyword with '*line' ?
*I know that I can use fopen,fget, etc... I decided to implement it in this way for a reason.
There is many issues that make your code core dump.
Here a version very similar to your code. I hope it will help you to understand this.
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
int read_file(const char *filename, char ***result)
{
/* open the file */
const int fd = open(filename, O_RDONLY);
if (fd < 0) {
*result = NULL;
return -1;
}
/* read the file characters by characters */
char *buffer = (char *)malloc(sizeof(char) * 1024);
char c;
int column = 0;
int line = 0;
*result = NULL;
/* for each characters in the file */
while (read(fd, &c, 1) > 0) {
/* check for end of line */
if (c != '\n' && c != 0 && column < 1024 - 1)
buffer[column++] = c;
else {
/* string are null terminated in C */
buffer[column] = 0;
column = 0;
/* alloc memory for this line in result */
*result = (char **)realloc(*result, sizeof(char *) *
(line + 1));
/* duplicate buffer and store it in result */
(*result)[line++] = strdup(buffer);
}
}
free(buffer);
return line;
}
int main(int argc, char *argv[])
{
if (argc != 2) {
fprintf(stderr, "usage: %s [filename]", argv[0]);
return 1;
}
char **lines;
int line_count = read_file(argv[1], &lines);
if (line_count < 0) {
fprintf(stderr, "cannot open file %s\n", argv[1]);
return 1;
}
for(int i=0; i < line_count; i++)
printf("%s\n", lines[i]);
return 0;
}
Here an other version:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int read_file(const char *filename, char ***result)
{
/* init result */
*result = NULL;
/* open the file */
FILE *file = fopen(filename, "r");
if (file == NULL)
return -1;
/* read the file line by line */
char *buffer = (char *)malloc(sizeof(char) * 1024);
int line = 0;
while (fgets(buffer, 1024, file)) {
*result = (char **)realloc(*result, sizeof(char *) *
(line + 1));
(*result)[line++] = strdup(buffer);
}
free(buffer);
return line;
}
int main(int argc, char *argv[])
{
if (argc != 2) {
fprintf(stderr, "usage: %s [filename]", argv[0]);
return 1;
}
char **lines;
int line_count = read_file(argv[1], &lines);
if (line_count < 0) {
fprintf(stderr, "cannot open file %s\n", argv[1]);
return 1;
}
for(int i=0; i < line_count; i++)
printf("%s\n", lines[i]);
return 0;
}

Low Level File I/O Compare Strings

I'm writing a program that takes a file with the 3 lines of encrypted passwords and compares them to all 4 lower case letters from aaaa - zzzz. The only issue I am having is that I can't figure out how to go line by line of the file I input and how to compare it to the 4 letter words individually. It should then print the 3 decrypted 4 letter words that correlate to the passwords from the file. Also if there are any types on how to improve my code, please let me know. I'm a beginner at this so I need clear explanations and examples if possible. Thank you.
EDIT*****
The main problem is in the all function and main. I'm not wanting to print the aaaa, aaab, aaac, etc to the screen but I want to put it in an char array so that i can compare each individually to each line from the file using crypt. So I need advice on how to put all 456976 combinations into an array, compare it to each line of code, and print the solutions to the screen.
file looks like this:
$1$6gMKIopE$I.zkP2EvrXHDmApzYoV.B.
$1$pkMKIcvE$WQfqzTNmcQr7fqsNq7K2p0
$1$0lMKIuvE$7mOnlu6RZ/cUFRBidK7PK.
My code looks like this:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define BUFFER_SIZE 1024
int my_fgets(char* buf, int len, int f)
{
for (int i = 0; i < len; i++,buf++)
{
int count = read(f, buf, 1);
if (!count || (buf[0] == '\n'))
{
buf[0] = 0;
return i;
}
}
return 0;
}
int inc(char *c,char begin, char end){
if(c[0]==0)
return 0;
if(c[0] == end){ // This make the algorithm to stop at char 'f'
c[0]=begin; // but you can put any other char
return inc(c+sizeof(char), begin, end);
}
c[0]++;
return 1;
}
char all(int a, int n,char begin, char end){
int i, j;
char *c = malloc((n+1)*sizeof(char));
char result[] = "";
for(i = a; i <= n; i++)
{
for(j=0;j<i;j++) c[j]=begin;
c[i]=0;
do {
int k = sizeof(result);
for (int g = 0; g < k -1; g++)
{
result[g] = c;
}
} while(inc(c,begin,end));
}
free(c);
}
int main(int argc, char* argv[])
{
char *result;
char let[456976];
int f = open("pass.txt", O_RDONLY);
if (f < 0)
return 0;
char buf[1024];
while (my_fgets(buf, sizeof(buf), f))
{
let = all(4,4,'a','z');
int i = 0;
result = crypt((let[i+1]), buf);
int ok = strcmp (result, pass) == 0;
return ok ? 0 : 1;
all(4, 4, 'a', 'z');
}
close(f);
}
I think you need to reword the question. Maybe the code below is what you want. Let's say you have a password, and you have a file which contains a list of encrypted passwords (or hash usually), you want to see if password is right or wrong. You compare the hash of the password with hashes in the file. I haven't tested this code.
ps, let me know if I am way off, I'll delete the answer.
void crypt(char* hash, const char* password_test) {
//create hash from password, or encrypt it or something?
}
int test_password(const char *filename, const char *password){
FILE *f;
f = fopen(filename, "r");
if (!f) return 0;
char password_hash[256];
crypt(password_hash, password);
char hash[256];
char buf[1024];
while (fgets(buf, sizeof(buf), f) != NULL)
{
crypt(hash, buf);
if (strcmp(password_hash, hash) == 0)
return 1;
}
fclose(f);
return 0;
}
void main() {
int result = test_password("test.txt", "password");
if (result == 1)
printf("password is good\n");
}
Reading line by line using open/read/close
int my_fgets(char* buf, int len, int f)
{
for (int i = 0; i < len; i++,buf++)
{
int count = read(f, buf, 1);
if (!count || (buf[0] == '\n'))
{
buf[0] = 0;
return i;
}
}
return 0;
}
int main(){
int f = open("test.txt", O_RDONLY);
if (f < 0) return 0;
char buf[1024];
while (my_fgets(buf, sizeof(buf), f))
printf("%s\n", buf);
close(f);
}

Printing from a buffer using the read(2) function in C

I'm trying to read in bits using the read function and I'm not sure how I'm supposed to printf the results using the buffer.
currently the code fragment is as follows
char *infile = argv[1];
char *ptr = buff;
int fd = open(infile, O_RDONLY); /* read only */
assert(fd > -1);
char n;
while((n = read(fd, ptr, SIZE)) > 0){ /*loops that reads the file until it returns empty */
printf(ptr);
}
The data read into ptr may contain \0 bytes, format specifiers and is not necessarily \0 terminated. All good reasons not to use printf(ptr). Instead:
// char n;
ssize_t n;
while((n = read(fd, ptr, SIZE)) > 0) {
ssize_t i;
for (i = 0; i < n; i++) {
printf(" %02hhX", ptr[i]);
// On older compilers use --> printf(" %02X", (unsigned) ptr[i]);
}
}
Here is the code that does the job for you:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <string.h>
#define SIZE 1024
int main(int argc, char* argv[])
{
char *infile = "Text.txt";
char ptrBuffer[SIZE];
int fd = open(infile, O_RDONLY); /* read only */
assert(fd > -1);
int n;
while((n = read(fd, ptrBuffer, SIZE)) > 0){ /*loops that reads the file until it returns empty */
printf("%s", ptrBuffer);
memset(ptrBuffer, 0, SIZE);
}
return 0;
}
You can read file name as parameter.
Even if ptr is a string, you need to use printf("%s", ptr);, not printf(ptr);
However, after you call
read(fd, ptr, SIZE)
ptr is rarely a string (strings need to be null-terminated). You need to use a loop and choose the format you need. For example:
for (int i = 0; i < n; i++)
printf("%02X ", *ptr);

Obtain data from a file dynamically

I have text file emails.txt..this is how the entry in the text file..
Emails.txt
abc#gmail.com
sfs#yahoo.com
i have to obtain the data from file and select 2 entries from the data randomly..
could anyone suggest me the technique to do this.
Thanks
You can read the file twice, first time to count the number of lines, then generate two random numbers in the range of 0 to number_of_lines found and then read the file again while looking for the lines you are interested in or you can do it like this:
Filename: emails.c
#include
int main (int argc, char **argv)
{
// open a handler to your file (read)
FILE *fp = fopen("emails.txt", "r");
// check if we have successfully opened the file for reading
if (fp != NULL)
{
// in your case 256 characters is enough for line size
// since emails are not that long but if longer buffer overflow
// is very possible and its not helpful as stackoverflow.com is :p
char line_buffer[256];
// count the number of lines read
unsigned int lines_read = 0;
// read up to line size or until EOL (End of Line) or EOF (End of File)
// will return NULL on error or eof
while (fgets(line_buffer, sizeof(line_buffer), fp) != NULL) {
// use rand() and seed it with the number of lines read
if ((rand() % ++lines_read) == 0) {
// do something with this line, it was randomly picked
// for the example, will print it on the screen
printf("%s \n", line_buffer);
}
}
// close file handler as we don't need it anymore
fclose(fp);
}
// return to the OS
return 0;
}
NOTE: This is C implementation, so save as .c file.
If you are using c++, and not just c -- you can use something like the following code:
#include <iostream>
#include <fstream>
#include <time.h>
#include <vector>
using namespace std;
int getrand(int num, int notnum)
{
int result = 0;
while (true)
{
result = abs(rand()) % num + 1;
if (result != notnum)
{
return result;
}
}
}
int main()
{
ifstream emails;
srand(time(NULL));
emails.open("emails.txt");
string email;
vector<string> emailVector;
while (emails >> email)
{
emailVector.push_back(email);
}
int index1 = getrand(emailVector.size(), 0);
int index2 = getrand(emailVector.size(), index1);
cout << "email 1: " << emailVector[index1 - 1] << endl;
cout << "email 2: " << emailVector[index2 - 1] << endl;
}
This will work:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define BUF_SIZE 4096
#define RAND_COUNT 2
int count_lines(FILE *fp) {
char buf[BUF_SIZE];
int line_count=0;
fseek(fp, 0L, SEEK_SET);
while(fgets(buf, BUF_SIZE, fp) != NULL) {
line_count++;
}
fseek(fp, 0L, SEEK_SET);
return line_count;
}
int line_num(FILE *fp, char *buf, int line_num){
fseek(fp, 0L, SEEK_SET);
int i=0;
while(fgets(buf, BUF_SIZE, fp) != NULL) {
if (++i == line_num) {
return i;
}
}
return -1;
}
int main (int argc, const char * argv[]) {
FILE *fp=NULL;
char buf[BUF_SIZE];
char name[]="email.txt";
if((fp=fopen(name, "r"))==NULL){
printf("can't open: %s\n\n",name);
return -1;
}
int line_count=count_lines(fp);
printf("line count=%i\n",line_count);
srand ((unsigned int)time(NULL));
for (int i=1; i<=line_count; i++) {
line_num(fp,buf,i);
printf("%i = %s",i,buf);
}
for (int i=0; i<RAND_COUNT; i++) {
int a=(rand() % line_count);
line_num(fp,buf,a);
printf("line %i = %s\n",a,buf);
}
fclose(fp);
return 0;
}

Resources