SHA - Output of program is different from sha512sum command - c

In summary, I program for first time with openssl/sha.h and everything goes right in compilation. here is my code:
#include <stdlib.h>
#include <stdio.h>
#include <openssl/sha.h>
int main()
{
int j;
FILE *hash_file = fopen("hash.txt", "wb");
for(j = 0; j < 256; j++)
{
unsigned char md[SHA512_DIGEST_LENGTH];
char* fileName = malloc(sizeof(int));
sprintf(fileName, "%X%s", j, ".txt");
int i;
FILE *file = fopen(fileName, "rb");
SHA512_CTX mdcontext;
int bytes;
unsigned char data[2048];
if(file == NULL)
{
printf("%s can not be opened\n", fileName);
return;
}
SHA512_Init(&mdcontext);
while((bytes = fread(data, 1, 2048, file) != 0))
SHA512_Update(&mdcontext, data, bytes);
SHA512_Final(md, &mdcontext);
for(i = 0; i < SHA512_DIGEST_LENGTH; i++)
{
printf("%x", md[i]);
fprintf(hash_file, "%x", md[i]);
}
// fprintf(hash_file, "\n");
printf("\n");
free(fileName);
fclose(file);
}
fclose(hash_file);
return 0;
}
and I have this output :
711c22448e721e5491d8245b49425aa861f1fc4a15287f735e23799b65cffec5b5abdfddd91cd643aeb3b530d48f5e258e7e230a94ed525c1387bb4e1b
But when I hash same file with sha512sum command in Linux i got this output:
6e3ea4bec3cd738f06f011c2f4ee4f6cd6d12205cafe41c083d52f94d9de4ab8b9e702664a367b633be14024a96e88a140a2e7fee4dc2c6e2f0bd436e281e35b make.sh
what is the problem?

Oh boi!
A tiny little parantheses can make you pull your hair out.
The problem is in this statement while((bytes = fread(data, 1, 2048, file) != 0)). You see, in this statement the != condition will be evaluated first. So, when fread reads (and returns), let's say n number of characters, it checks if n!=0. If it evaluates to true then it sets bytes to 1 (true is casted to 1).
And now, the function SHA512_Update(&mdcontext, data, bytes); becomes SHA512_Update(&mdcontext, data, 1); while it should have been SHA512_Update(&mdcontext, data, n); (where n is the number of characters successfully read).
Solution
Change while((bytes = fread(data, 1, 2048, file) != 0)) to while((bytes = fread(data, 1, 2048, file)) != 0).
Update [Saving the hash in a char array]:
The output of SHA512 is of 128 characters. So, we need a char array of size twice that of SHA512_DIGEST_LENGTH (64). Then, we can just store it in the char array using sprintf.
char hash[SHA512_DIGEST_LENGTH*2];
for(i = 0; i < SHA512_DIGEST_LENGTH; i++)
sprintf(&hash[i*2], "%02x", md[i]);
Why i*2? Because output has a width of 2 bytes. So, result will be stored at hash[i] and hash[i+1].
Now, to print it:
for(i = 0; i < SHA512_DIGEST_LENGTH*2; i++)
printf("%c", hash[i]);
PS:
Read about precedence.
And don't forget to follow the advices in comments to your post, especially the one about using %02x by Steve.

Related

How to convert a binary array into one single variable?

I have an binary array and i am trying to convert this into a single variable so that i can read the binary bitwise consecutively. I have tried looping over the array and adding each of them into a variable but this has not work. Can anyone give me some pointers into how to do this?
This is what i have tried:
char* filename = vargs[1];
BYTE buffer[BUFFER_SIZE];
FILE *file_ptr = fopen(filename,"rb");
fseek(file_ptr, 0, SEEK_END);
size_t file_length = ftell(file_ptr);
rewind(file_ptr);
fread(buffer, sizeof(BYTE), BUFFER_SIZE, file_ptr);
char binaryLine = '\0';
for (int i = 0; i > file_length; i++)
{
binaryLine += buffer[i];
printf("%d ", (int)buffer[i]);
}
Maybe there is some miss understanding, but when you read a file in a char* or char[], that is one variable.
Maybe try below code, and see what your missing.
Pay attention to, just to name a few:
for instruction, need to be true to continue
fread you need to get the amount of bytes read to loop it
main, it's a function or it's main, show it
fopen etc, would also neeed you to check for errors, which might help you to figure out why something does not work
regarding your question, It's important to ask a question and provide info, as stated in other comment, what do you want....
#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char * argv[]) {
const char* filename = argv[1];
char * buffer=NULL;
FILE *file_ptr = fopen(filename,"rb");
if (! file_ptr) return 1;
fseek(file_ptr, 0, SEEK_END);
size_t file_length = ftell(file_ptr);
rewind(file_ptr);
if (file_length!=0)
buffer=calloc(1,file_length);
if (buffer)
{
size_t bytes_read=fread(buffer, 1, file_length, file_ptr);
for (int i = 0; i < bytes_read; i++)
{
printf("%d ", (int)buffer[i]);
}
free(buffer);
buffer=NULL;
return 0;
}
return 1;
}

C programming in Linux: not getting correct output for program that finds number of occurrences of substring in file

I am writing a program that finds the number of occurrences of input substrings from the command line inside a text file (also read from the command line) which is written into a buffer.
When I run the code in bash, I get the error: Segmentation fault (core dumped).
I am still learning how to code with C in this environment and have some sort of idea as to why the segmentation fault occurred (misuse of dynamic memory allocation?), but I could not find the problem with it. All I could conclude was that the problem is coming from within the for loop (I labeled where the potential error is being caused in the code).
EDIT: I managed to fix the segmentation fault error by changing argv[j] to argv[i], however when I run the code now, count1 always returns 0 even if the substring occurs multiple times in the text file and I am not sure what is wrong even though I have gone through the code multiple times.
$ more foo.txt
aabbccc
$ ./main foo.txt a
0
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
int main(int argc, char *argv[]) {
FILE *fp;
long lsize;
char *buf;
int count = 0, count1 = 0;
int i, j, k, l1, l2;
if (argc < 3) { printf("Error: insufficient arguments.\n"); return(1); };
fp = fopen(argv[1], "r");
if (!fp) {
perror(argv[1]);
exit(1);
}
//get size of file
fseek(fp, 0L, SEEK_END);
lsize = ftell(fp);
rewind(fp);
//allocate memory for entire content
buf = calloc(1, lsize+1);
if (!buf) {
fclose(fp);
fputs("Memory alloc fails.\n", stderr);
exit(1);
}
//copy the file into the buffer
if (1 != fread(buf, lsize, 1, fp)) {
fclose(fp);
free(buf);
fputs("Entire read fails.\n", stderr);
exit(1);
}
l1 = strlen(buf);
//error is somewhere here
for (i = 2; i < argc; i++) {
for (j = 0; j < l1;) {
k = 0;
count = 0;
while ((&buf[j] == argv[k])) {
count++;
j++;
k++;
}
if (count == strlen(argv[j])) {
count1++;
count = 0;
}
else
j++;
}
printf("%d\n", count1);
}
fclose(fp);
return 0;
}
fread(buf, lsize, 1, fp) will read 1 block of lsize bytes, however fread
doesn't care about the contents and won't add a '\0'-terminating byte for the
string, so l1 = strlen(buf); yields undefined behaviour, the rest of the
result can be ignored as a result of this (and your counting has errors as well).
Note that files usually don't have a 0-terminating byte at the end,
that applies even for files containing text, they usually end with a
newline.
You have to set the 0-terminating byte yourself:
if (1 != fread(buf, lsize, 1, fp)) {
fclose(fp);
free(buf);
fputs("Entire read fails.\n", stderr);
exit(1);
}
buf[lsize] = '0';
And you can use strstr to get the location of the substring, like this:
for(i = 2; i < argc; ++i)
{
char *content = buf;
int count = 0;
while((content = strstr(content, argv[i])))
{
count++;
content++; // point to the next char in the substring
}
printf("The substring '%s' appears %d time(s)\n", argv[i], count);
}
Your counting is wrong, there are some errors. This comparison
&buf[j] == argv[k]
is wrong, you are comparing pointers, not the contents. You have to use strcmp
to compare strings. In this case you would have to use strncmp because you
only want to match the substring:
while(strncmp(&buf[j], argv[k], strlen(argv[k])) == 0)
{
// substring matched
}
but this is also wrong, because you are incrementing k as well, which will
give you the next argument, at the end you might read beyond the limits of
argv if the substring is longer than the number of arguments. Based on your
code, you would have to compare characters:
while(buf[j] == argv[i][k])
{
j++;
k++;
}
You would have to increment the counter only when a substring is matched, like
this:
l1 = strlen(buf);
for (i = 2; i < argc; i++) {
int count = 0;
int k = 0; // running index for inspecting argv[i]
for (j = 0; j < l1; ++j) {
while(buf[j + k] == argv[i][k])
k++;
// if all characters of argv[i]
// matched, argv[i][k] will be the
// 0-terminating byte
if(argv[i][k] == 0)
count++;
// reset running index for argv[i]
// go to next char if buf
k = 0;
}
printf("The substring '%s' appears %d time(s)\n", argv[i], count);
}

Fast double file read in C

I have a large file containing floating point numbers and I want to read them.
52.881 49.779 21.641 37.230 23.417 7.506 120.190 1.240 79.167 82.397 126.502 47.377 112.583 124.590 103.339 5.821 24.566 38.916 42.576
This is just the beggining of the file. It has 10000000 numbers.
I got this code but I don't know how to print the numbers.
#include <stdio.h>
#include <stdlib.h>
#include <err.h>
#include <fcntl.h>
#include <sysexits.h>
#include <unistd.h>
int main()
{
int fd;
size_t bytes_read, bytes_expected = 1000000*sizeof(double);
double *data;
char *infile = "file.dat";
if ((fd = open(infile,O_RDONLY)) < 0)
err(EX_NOINPUT, "%s", infile);
if ((data = malloc(bytes_expected)) == NULL)
err(EX_OSERR, "data malloc");
bytes_read = read(fd, data, bytes_expected);
if (bytes_read != bytes_expected)
err(EX_DATAERR, "Read only %d of %d bytes",
bytes_read, bytes_expected);
/* print all */
free(data);
exit(EX_OK);
}
You are attempting to read a text file as if the data was binary, so you will read some bytes but the double values stored in the array will not be the values that you wanted to read from the file, you can probably do this
FILE *file;
double *array;
size_t count;
const char *infile = "file.dat";
file = fopen(infile, "r");
if (file == NULL)
return -1;
count = 0;
while (fscanf(file, "%*lf") == 1)
count += 1;
rewind(file);
array = malloc(count * sizeof(*array));
if (array == NULL) {
fprintf(stderr, "cannot allocate %zu bytes!\n", count * sizeof(*array));
fclose(file);
return -1;
}
// Read the values into the array
for (size_t i = 0; i < count; ++i) {
fscanf(file, "%lf", &array[i]);
}
// Print the array
for (size_t i = 0; i < count; ++i) {
fprintf(stdout, "%f\n", array[i]);
}
// Release memory
free(array);
Since you want a fast solution, maybe you have to sacrifice memory.
The faster manner of reading a file is in binary form.
Thus, I would obtain the file size with an efficient method,
then I would allocate memory accordingly,
with the idea of uploading the entire file to memory.
There, since memory reading is faster than file reading,
the data can be quickly read by using sscanf(...).
We can also observe that each floating point number
needs at least 3 characters to be stored in a text file:
1 char for the dot ('.'),
1 char for some digit,
and 1 char for
a space (' ') used to separating a value from its succesor in the
file.
Thus, the file size divided by 3 will be the upper bound for the size of the array of doubles.
#include <stdio.h>
int main(void) {
char *filename = "file.dat";
FILE *F = fopen(filename, "rb");
fseek(F, 0L, SEEK_END);
long int filesize = ftell(F);
rewind(F);
char *data = malloc(filesize+1);
fread(data, filesize, 1, F);
data[filesize] = '\0'; // End of string, just in case
fclose(F);
// The desired data will be stored in array:
double *array = malloc(sizeof(double) * filesize/3);
int ret;
int n; // represents the no chars in a sscanf(...) reading
double *a = array;
while (1) { // Infinite loop...
ret = sscanf(data, " %lg%n", a, &n);
if (ret == EOF) break; // <<---- EXIT POINT of the loop
a++;
data += n;
}
long int array_size = a - array + 1;
}

C project with files

I need some help with my C project:
I need to write a c program who receives 2 parameters:
1) The name of a text file(infile) which is in the same catalog
2) A number k>0
And creates 2 new files,outfile1 & outfile 2 as:
Outfile 1: k,2*k,3*k…. character of infile
Outfile 2: k,2*k,3*k…..line of infile
Example:
INFILE
Abcdefg
123456
XXXXXX
01010101
OUTFILE 1:
Cf25XX101
OUTFILE 2:
XXXXXX
I wrote some code ,but its not working. Any ideas?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char** read_lines(FILE* txt, int* count) {
char** array = NULL;
int i;
char line[100];
int line_count;
int line_length;
*count = 0;
line_count = 0;
while (fgets(line, sizeof(line), txt) != NULL) {
line_count++;
}
rewind(txt);
array = malloc(line_count * sizeof(char *));
if (array == NULL) {
return NULL;
}
for (i = 0; i < line_count; i++) {
fgets(line, sizeof(line), txt);
line_length = strlen(line);
line[line_length - 1] = '\0';
line_length--;
array[i] = malloc(line_length + 1);
strcpy(array[i], line);
}
*count = line_count;
return array;
}
int main(int argc, char * argv[]) {
char** array = NULL;
FILE* file = NULL;
const char* filename = NULL;
int i;
int line_count;
int k;
char c;
printf("ENTER ONE PHYSICAL NUMBER\n");
do{
if(k>0)
scanf("%d",&k);
else{
printf("ENTER ONE PHYSICAL NUMBER\n");
scanf("%d",&k);
}
}while(k<=0);
file = fopen("LEIT.txt", "rt");
if (file == NULL) {
printf("CANT OPEN FILE %s.\n", filename);
return 1;
}
array = read_lines(file, &line_count);
printf("ARRAY:\n");
for (i = 0; i < line_count; i++) {
printf("[%d]: %s\n", (i+1), array[i]);
}
printf("CALCULATING OUTFILE1 AND OUTFILE2\n");
printf("OUTFILE1:\n");
for(i=0;i<line_count;i++){
c=i*k;
printf("%c\n",array[c]);
}
printf("WRITING OUTFILE1 COMPLETE!\n");
printf("OUTFILE2:\n");
for(i=0;i<line_count;i++){
c=i*k;
printf("%c\n",array[c]);
}
printf("WRITING OUTFILE2 COMPLETE!\n");
return 0;
}
My actual problem is calculate and write into files (outfile1 and outfile2) the result...
You need to close file after finishing reading/writing it with fclose.
You can create and write strings to a file using fopen with correct mode.
You can output formatted string to a file by using fprintf.
It seems that you don't want to print the 0th character/line, so in the last for loop, i should start from 1 (or start from 0 but add 1 later).
array[c] is a string, not a character. So when printing it, you should use %s specifier instead of %c.
It is not a good idea using char as count in later for loops unless you know input file will be very short. signed char can only count to 127 before overflow (unsigned char can count to 255). But if you have a very long file, for example thousands of lines, this program would not work properly.
array is malloced in function char** read_lines(FILE* txt, int* count). After finish using it, you need to dealloc, or free it by calling
for (i = 0; i < line_count; i++) {
free(array[i]);
}
and followed by free(array). This avoids memory leakage.
Modified code is here. In the following code, char c is not used. This is the part where you process output files, and before return 0; in main function.
printf("CALCULATING OUTFILE1 AND OUTFILE2\n");
printf("OUTFILE1:\n");
// Since we finished using LEIT.txt, close it here.
fclose(file);
// Mode: "w" - Write file. "+" - Create if not exist.
// You can lso use "a+" (append file) here if previous record need to be preserved.
FILE *out1 = fopen("OUTFILE1.txt", "w+");
FILE *out2 = fopen("OUTFILE2.txt", "w+");
if ((out1 == NULL) || (out2 == NULL)) {
printf("CANT CREATE OUTPUT FILES.\n");
return 1;
}
// Out file 1.
unsigned int count = k;
for (i = 0; i < line_count; i++){
while (count < strlen(array[i])) {
// This just prints to stdout, but is good for debug.
printf("%c", array[i][count]);
// Write to the file.
fprintf(out1, "%c", array[i][count]);
// Calculate c for next char.
count += k + 1;
}
// Before go to next line, minus string length of current line.
count -= strlen(array[i]);
}
printf("\n");
printf("WRITING OUTFILE1 COMPLETE!\n");
// Close file.
fclose(out1);
// Out file 2.
printf("OUTFILE2:\n");
for (i = 1;i < line_count / k; i++){
count = i * k;
// This just prints to stdout, but is good for debug.
printf("%s\n", array[count]);
// Write to the file.
fprintf(out2, "%s\n", array[count]);
}
printf("WRITING OUTFILE2 COMPLETE!\n");
//Close file.
fclose(out2);
// dealloc malloced memory.
for (i = 0; i < line_count; i++) {
free(array[i]);
}
free(array);

C memory allocation with File input

Hello i have a problem with memory allocation,
1. open file
2. take lenght of text inside
3. make buffer in size of lenght (array[] ? malloc ?)
4. make operations on text in buffer.
5. close
it terminates when text any longer than 1xx characters i have no idea whats going on.
ps.attention! im learning and quality of this code can be bad
#include <stdio.h>
#include <stdlib.h>
void copy_to_buffer(FILE *fp, int length, char *buffer){
for(int i = 0; i < length; i++){
char c = fgetc(fp);
buffer[i] = c;
}
}
int length_of_text(FILE *fp) {
fseek(fp, 0L, SEEK_END);
int size = ftell(fp);
rewind(fp);
return size;
}
void char_counter(int length, char *buffer, int *charBuffer) {
int counts[128] = { 0 };
for (int i = 0; i < length; i++) {
counts[(int)(buffer[i])]++;
charBuffer[i] = counts[i];
}
for (int i = 0; i < 128; i++) {
charBuffer[i] = counts[i];
if(counts[i] != 0)
printf("%d.(%c) counted: %d times.\n", i,i, counts[i]);
}
}
/***********************************MAIN***********************************/
int main(int argc, char** argv) {
FILE *fp = fopen("tekst.txt" , "r");
int length = length_of_text(fp); //lenght of text
char *buffer = malloc(sizeof(char)*length); //buffer for text from file
if(buffer == NULL)
printf("error");
else
printf("alocated at = %p\n", &buffer);
int charBuffer[128] = {0}; // charcount buffer
buffer[length] = '\0'; // '\0' after last sign
copy_to_buffer(fp, length, buffer);
char_counter(length, buffer, charBuffer);
free(buffer);
fclose(fp);
return 0;
}
In this line
charBuffer[i] = counts[i];
you will overflow charBuffer[128] when the file size is >= 128, since i is indexing by up to the length of the file.
In your char_counter function you do
charBuffer[i] = counts[i];
in the first for loop but buffer is only defined to be 128 ints. If the text is longer than 128 characters this will cause a buffer overflow and a segmentation fault.
Remove that line and let the 2nd for loop do it.

Resources