How to store SHA1 output to a file using C - c

I have computed the SHA1 for a piece of data and I need to store it into a file to be read by another person later. The SHA1 gives the output as 190 bit's, but I can't store as bits into a file, fputc() function does it characters which means bytes.
So I want to either store it as bytes into the file or as its hexadecimal representation (preferably). In C, so far I can only get it to print the hash to the terminal as the hexadecimal representation (using a way I found in another question posted in this site), but I can't figure out how to store it to a file properly.
Please help!

If you want to write the SHA1 digest as binary digest in the file, you can use:
fwrite ( &sha1_digest, sizeof(sha1_digest), 1, stream );
Where stream is a FILE* opened in binary mode.
If you want to save it as hexadecimal string, you can do a loop :
char *p=(void*)&sha1_digest;
int i=sizeof(sha1_digest);
while (i--)
fprintf (stream, "%02x",*p++);
where tream is a FILE* opened in text or binary mode
I assumed that sha1_digest was a structure. If it's an array, you don't need the & and if the array is not fixed size, then you must provide the size of the digest (because in this case, sizeof() would return the sizeof a pointer isntead of the array.)
You are certainly aware, but SHA1 is no longer considered as a safe hash, if your use is somewhat related to security.

i used the following code for generating sha1 hash of text stored in message.txt file(text is: hello how are you).
#include <stdio.h>
#include <stdlib.h>
#include <openssl/sha.h>
#define BUFSIZE 1024*16
void do_fp(FILE *f);
void pt(unsigned char *md);
#ifndef _OSD_POSIX
int read(int, void *, unsigned int);
#endif
int main(int argc, char **argv)
{
int i, err = 0;
FILE *IN,*fp;
if (argc == 1) {
do_fp(stdin);
}
else {
printf("hi");
for (i = 1; i < argc; i++) {
IN = fopen(argv[i], "r");
if (IN == NULL) {
perror(argv[i]);
err++;
continue;
}
printf("SHA1(%s)= ", argv[i]);
do_fp(IN);
fclose(IN);
}
}
exit(err);
}
void do_fp(FILE *f)
{
SHA_CTX c;
unsigned char md[SHA_DIGEST_LENGTH];
int fd;
int i;
unsigned char buf[BUFSIZE];
FILE *fp;
fd = fileno(f);
SHA1_Init(&c);
for (;;) {
i = read(fd, buf, BUFSIZE);
if (i <= 0)
break;
SHA1_Update(&c, buf, (unsigned long)i);
}
SHA1_Final(&(md[0]), &c);
fp = fopen("file.txt","wb");
char *p=(void*)md;
i=SHA_DIGEST_LENGTH;
while (i--)
fprintf (fp, "%02x",*p++);
pt(md);
}
void pt(unsigned char *md)
{
int i;
for (i = 0; i < SHA_DIGEST_LENGTH; i++)
printf("%02x", md[i]);
printf("\n");
}
i got followng as output. SHA1(message.txt)= 46e7b8310aa4d03b57e11022166d37beedf36537 however hash stored in file.txt is as follows. 46ffffffe7ffffffb8310affffffa4ffffffd03b57ffffffe11022166d37ffffffbeffffffedfffffff36537 please provide necessary guidance to achieve correct hash in file.txt. thank you in advance.

Related

wzip.c OS three easy steps

I am newbie in OS. Im currently learning OS three easy steps.
I found this code for the the first project of the course.
(wzip) is a file compression tool, and the other (wunzip) is a file decompression tool.
input:
aaaaaaaaaabbbb
correct output:
10a4b
instructions: write out a 4-byte integer in binary format followed by the single character in ASCII.
current output:
ab
I type in the shell:
prompt> gcc -o wzip wzip.c -Wall -Werror
prompt> ./wzip file1.txt > file1.z
This is the link for the project:
https://github.com/remzi-arpacidusseau/ostep-projects/tree/master/initial-utilities
This is the code I found for this specific part of the project:
wzip:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
/*
wzip: is a file compresion tool.
*/
void writeFile(int , char *);
int main(int argc, char *argv[]){
FILE *fp;
char newbuff[2], oldbuff[2];
int count;
if (argc < 2){
printf("wzip: file1 [file2 ...]\n");
exit(EXIT_FAILURE);
}
// open files
for (size_t i = 1; i < argc; i++){
if ((fp = fopen(argv[i], "r")) == NULL){
printf("wzip: cannot open file\n");
exit(EXIT_FAILURE);
}
while (fread(newbuff, 1, 1, fp)){
if (strcmp(newbuff, oldbuff) == 0){
count++;
} else {
if (oldbuff[0] != '\0'){
writeFile(count, oldbuff);
}
count = 1;
strcpy(oldbuff, newbuff);
}
}
fclose(fp);
}
writeFile(count, oldbuff);
return 0;
}
void writeFile(int count, char *oldbuff){
// write as network byte order
count = htonl(count);
fwrite(&count, 4, 1, stdout);
fwrite(oldbuff, 1, 1, stdout);
}
wunzip:
#include <stdio.h>
#include <stdlib.h> // exit
#include <string.h> // memset
#include <arpa/inet.h> // ntohl
int
main(int argc, char *argv[])
{
FILE *fp;
char buff[5];
if (argc <= 1) {
printf("wunzip: file1 [file2 ...]\n");
exit(EXIT_FAILURE);
}
for (size_t i = 1; i < argc; i++) {
if ((fp = fopen(argv[i], "r")) == NULL) {
printf("wunzip: cannot open file\n");
exit(EXIT_FAILURE);
}
int count = 0;
while (fread(&count, 4, 1, fp)) {
count = ntohl(count); // read from network byte order
memset(buff, 0, strlen(buff));
fread(buff, 1, 1, fp);
for (size_t i = 0; i < count; i++) {
printf("%s", buff);
}
}
fclose(fp);
}
return 0;
}
Cant please some one can give a hand to understand better.
Thanks in advance.
How is your solution coming along?
The first that jumps out about the code posted here is that your write the wrong number of bytes. In other words, you don't follow the compression guidelines of the exercise. The instructions for the OSTEP project was to write a 32 bit int (4 bytes) followed by a single ascii character (1 byte).
It helps to set up a test before writing the compressed output. Make sure that what is being written does indeed equal 5 bytes.
#include <stdio.h>
struct token {
u_int32_t count;
u_int8_t ch;
};
size_t numbytes (struct token t) {
/* calculates the number of bytes in a single token */
/* assumes a token has two attributes */
/* should return a value of 5 */
size_t mybytes = sizeof(t.count) + sizeof(t.ch)
return mybytes;
}
I personally found it easier to think about the read procedure in terms of a parser. This is due to the fact that some of the test cases get slightly more complex. You need to effectively manage state between line reads and also between files.
It's a little bit late, but I just did this program for my course's assignment and I want to share my solution. It passes all the available test cases but it's not official from any party (neither from my course nor the project owner).
The code:
#include <stdio.h> // FILE, stdout, fprintf, fwrite, fgetc, EOF, fclose
#include <stdlib.h> // EXIT_*, exit
struct rle_t
{
int l;
char c;
};
void
writerle(struct rle_t rleobj)
{
fwrite((int *)(&(rleobj.l)), sizeof(int), 1, stdout);
fwrite((char *)(&(rleobj.c)), sizeof(char), 1, stdout);
}
struct rle_t
process(FILE *stream, struct rle_t prev)
{
int curr;
struct rle_t rle;
while ((curr = fgetc(stream)) != EOF)
{
if (prev.c != '\0' && curr != prev.c)
{
rle.c = prev.c;
rle.l = prev.l;
prev.l = 0;
writerle(rle);
}
prev.l++;
prev.c = curr;
}
rle.c = prev.c;
rle.l = prev.l;
return rle;
}
int
main(int argc, const char *argv[])
{
if (argc < 2)
{
fprintf(stdout, "wzip: file1 [file2 ...]\n");
exit(EXIT_FAILURE);
}
struct rle_t prev;
prev.c = '\0';
prev.l = 0;
for (int i = 1; i < argc; ++i)
{
FILE *fp = fopen(argv[i], "r");
if (fp == NULL)
{
fprintf(stdout, "wzip: cannot open files\n");
exit(EXIT_FAILURE);
}
struct rle_t rle = process(fp, prev);
prev.c = rle.c;
prev.l = rle.l;
fclose(fp);
}
writerle(prev);
return 0;
}
From the post, I think there is no need to use any function like htonl(3) for this problem. The tricky part is in the writerle() function, which you already got it. But let me explain what I understand:
Use fwrite(3) to write binary format to the stream, in this case, stdout.
First parameter is a pointer, that's why I need &(rleobj.l) and &(rleobj.c).
This line
fwrite((int *)(&(rleobj.l)), sizeof(int), 1, stdout);
tells that I want to write 4 bytes (sizeof(int)) of the first parameter (&(rleobj.l)) to the standard output (stdout) one time (1). The typecast is optional (depending on your compiler and how you want to read your code).
The reason why they require you to do so is because it will separate between the run-length part and the character part.
Let's say you have a simple input file like this:
333333333333333333333333333333333aaaaaaaaaaaa
After encoding without the binary format:
33312a
This is wrong. Because now, it looks like the run-length of the character a is 33312, instead of 33 of 3 and 12 of a.
However, with binary format, those parts are separated:
❯ xxd -b output.z
00000000: 00100001 00000000 00000000 00000000 00110011 00001100 !...3.
00000006: 00000000 00000000 00000000 01100001 ...a
Here, the first four bytes represent the run-length and the next one byte represents the character.
I hope this will help.

Reading integers from txt file in C

I`m making a file reader that reads integers numbers line by line from a file. The problem is that is not working. I think I am using fscanf in a wrong way. Can someone help me?
I had already look for answers in others questions but I can`t find anything that explain why I my code is not working.
int read_from_txt(){
FILE *file;
file = fopen("random_numbers.txt", "r");
//Counting line numbers to allocate exact memory
int i;
unsigned int lines = 0;
unsigned int *num;
char ch;
while(!feof(file)){
ch = fgetc(file);
if (ch == '\n'){
lines++;
}
}
//array size will be lines+1
num = malloc(sizeof(int)*(lines+1));
//storing random_numbers in num vector
for(i=0;i<=lines;i++){
fscanf(file, "%d", &num[i]);
printf("%d", num[i]);
}
fclose(file);
}
The txt file is like:
12
15
32
68
46
...
But the output of this code keeps giving "0000000000000000000..."
You forgot to "rewind" the file:
fseek(file, 0, SEEK_SET);
Your process of reading goes through the file twice - once to count lines, and once more to read the data. You need to go back to the beginning of the file before the second pass.
Note that you can do this in a single pass by using realloc as you go: read numbers in a loop into a temporary int, and for each successful read expand the num array by one by calling realloc. This will expand the buffer as needed, and you would not need to rewind.
Be careful to check the results of realloc before re-assigning to num to avoid memory leaks.
You could try to use the getline function from standard IO and add the parsed numbers into the array using only one loop. See the code below. Please check https://linux.die.net/man/3/getline
Also, you can use the atoi or strtoul functions to convert the read line to an integer. Feel free to check https://linux.die.net/man/3/atoi or https://linux.die.net/man/3/strtoul
The code below evaluate a file with a list of numbers and add those numbers to a C integer pointer
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char ** argv) {
FILE * file;
file = fopen("./file.txt", "r");
size_t read;
char * line = NULL;
size_t line_len = 0;
size_t buffer_size = 10;
int * buffer = (int *)malloc(sizeof(int) * buffer_size);
int seek = 0;
while((read = getline(&line, &line_len, file)) != -1) {
buffer[seek++] = atoi(line);
if (seek % 10 == 0) {
buffer_size += 10;
buffer = (int *)realloc(buffer, sizeof(int) * buffer_size);
}
}
for (int i = 0; i < seek; i++) {
printf("%d\n", buffer[i]);
}
free(buffer);
fclose(file);
}
If you aren't sure which conversion function should you use. You can check the difference between atoi and sscanf at What is the difference between sscanf or atoi to convert a string to an integer?

Trying to make program that counts number of bytes in a specified file (in C)

I am currently attempting to write a program that will tell it's user how many times the specified 8-bit byte appears in the specified file.
I have some ground work laid out, but when it comes to making sure that the file makes it in to an array or buffer or whatever format I should put the file data into to check for the bytes, I feel I'm probably very far off from using the correct methods.
After that, I need to check whatever the file data gets put in to for the byte specified, but I am also unsure how to do this.
I think I may be over-complicating this quite a bit, so explaining anything that needs to be changed or that can just be scrapped completely is greatly appreciated.
Hopefully didn't leave out any important details.
Everything seems to be running (this code compiles), but when I try to printf the final statement at the bottom, it does not spit out the statement.
I have a feeling I just did not set up the final for loop correctly at all..
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
//#define BUFFER_SIZE (4096)
main(int argc, char *argv[]){ //argc = arg count, argv = array of arguements
char buffer[4096];
int readBuffer;
int b;
int byteCount = 0;
b = atoi(argv[2]);
FILE *f = fopen(argv[1], "rb");
unsigned long count = 0;
int ch;
if(argc!=3){ /* required number of args = 3 */
fprintf(stderr,"Too few/many arguements given.\n");
fprintf(stderr, "Proper usage: ./bcount path byte\n");
exit(0);
}
else{ /*open and read file*/
if(f == 0){
fprintf(stderr, "File could not be opened.\n");
exit(0);
}
}
if((b <= -1) || (b >= 256)){ /*checks to see if the byte provided is between 0 & 255*/
fprintf(stderr, "Byte provided must be between 0 and 255.\n");
exit(0);
}
else{
printf("Byte provided fits in range.\n");
}
int i = 0;
int k;
int newFile[i];
fseek(f, 0, SEEK_END);
int lengthOfFile = ftell(f);
for(k = 0; k < sizeof(buffer); k++){
while(fgets(buffer, lengthOfFile, f) != NULL){
newFile[i] = buffer[k];
i++;
}
}
if(newFile[i] = buffer[k]){
printf("same size\n");
}
for(i = 0; i < sizeof(newFile); i++){
if(b == newFile[i]){
byteCount++;
}
printf("Final for loop is working???"\n");
}
}
OP is mixing fgets() with binary reads of a file.
fgets() reads a file up to the buffer size provided or reaching a \n byte. It is intended for text processing. The typical way to determine how much data was read via fgets() is to look for a final \n - which may or may not be there. The data read could have embedded NUL bytes in it so it becomes problematic to know when to stop scanning the buffer. on a NUL byte or a \n.
Fortunately this can all be dispensed with, including the file seek and buffers.
// "rb" should be used when looking at a file in binary. C11 7.21.5.3 3
FILE *f = fopen(argv[1], "rb");
b = atoi(argv[2]);
unsigned long byteCount = 0;
int ch;
while ((ch = fgetc(f)) != EOF) {
if (ch == b) {
byteCount++;
}
}
The OP error checking is good. But the for(k = 0; k < sizeof(buffer); k++){ loop and its contents had various issues. OP had if(b = newFile[i]){ which should have been if(b == newFile[i]){
Not really an ANSWER --
Chux corrected the code, this is just more than fits in a comment.
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
struct stat st;
int rc=0;
if(argv[1])
{
rc=stat(argv[1], &st);
if(rc==0)
printf("bytes in file %s: %ld\n", argv[1], st.st_size);
else
{
perror("Cannot stat file");
exit(EXIT_FAILURE);
}
return EXIT_SUCCESS;
}
return EXIT_FAILURE;
}
The stat() call is handy for getting file size and for determining file existence at the same time.
Applications use stat instead of reading the whole file, which is great for gigantic files.

Binary Translation

#include <stdio.h>
int main() {
unsigned char data[1];
FILE *f = fopen("bill.jpg", "rb");
while (!feof(f)) {
if (fread(data, 1, 1, f) > 0) {
printf("0x%02x\n", data[0]);
}
}
fclose(f);
}
Is this the right? I am worried because if I view the file using hexdump, I get completely different output.
That should correctly print the first byte of the file in hex.
Check the documentation for the Hexdump utility used, or tell us which platform is being used. Some dump utilities display the bytes in reverse order on each line to make little-endian reading somewhat more intuitive—once you understand what it is doing.
I'm sorry, but no -- while (!feof(f)) is essentially always wrong -- it'll typically appear to read the last item in the file twice. Here's a reasonably usable hex dumper I wrote a few years ago:
/* public domain by Jerry Coffin, tested with MS C 10.0 and BC 4.5
*/
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
unsigned long offset = 0;
FILE *input;
int bytes, i, j;
unsigned char buffer[16];
char outbuffer[60];
if ( argc < 2 ) {
fprintf(stderr, "\nUsage: dump filename [filename...]");
return EXIT_FAILURE;
}
for (j=1;j<argc; ++j) {
if ( NULL ==(input=fopen(argv[j], "rb")))
continue;
printf("\n%s:\n", argv[j]);
while (0 < (bytes=fread(buffer, 1, 16, input))) {
sprintf(outbuffer, "%8.8lx: ", offset+=16);
for (i=0;i<bytes;i++) {
sprintf(outbuffer+10+3*i, "%2.2X ",buffer[i]);
if (!isprint(buffer[i]))
buffer[i] = '.';
}
printf("%-60s %*.*s\n", outbuffer, bytes, bytes, buffer);
}
fclose(input);
}
return 0;
}

To generate hexadecimal numbers for 1000 bytes in C

I want to generate hexadecimal numbers in C starting with seed value(initial value) 0706050403020100.My next numbers should be 0f0e0d0c0b0a0908 and so on for next iteration.
In that way i want to generate numbers for say 1000 bytes.
1)how can i generate these hexadecimal numbers.
2)How to store these numbers if i want to compare the generated/produced hexadecimal numbers character by character with the data available in a buffer(dynamic) which has contents of a read file.
Any suggestions/answers are most welcome as i am still learning C language.
EDIT:Here's the code i have tried.
#include<stdio.h>
#include<stdlib.h>
int main(){
FILE *fp;
char *buffer, c;
size_t filesize, result;
int i, expected_data[];
fp = fopen("hex_data", "r");
if (fp == NULL) {
fputs("Error\n", stderr);
exit(1);
}
fseek(fp, 0L, SEEK_END);
filesize = ftell(fp);
printf("Size of hex_data file is:%u \n", filesize);
fseek(fp,0L,SEEK_SET);
buffer = (char*) malloc(sizeof(char)*filesize);
if(buffer == NULL){
fputs("\nMemory error ", stderr);
}
buffer_size = fread(buffer, sizeof(char), size, fp);
for(i=0; i < result; i++) {
printf("%c",*(buffer +i));
}
printf("No of elements read from file are:%u \n", buffer_size);
fseek(fp,0L,SEEK_SET);
int current_pos = 0;
while(current_pos < buffer_size) {
if (buffer[current_pos] != expected_data) {
fputs("Error\n",stderr);
}
else {
current_pos++;
expected_data = next_exp_data(data); //function is call hexadecimal numbers produced
}
}
Here i want to write a function to generate hex numbers for 1000 bytes starting from 0706050403020100.If this is the initial data everytime if i add 08 to each byte i should get the next number(til 1000 bytes).But i don't know how to do it.Can anyone help me out.
Any corrections in the code are most welcome.
This will generate 1000 bytes of random hexadecimal numbers. (Or rather, the ASCII representation of 1000 hexadecimal digits.)
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
int i;
for (i=0; i<1000; i++) {
printf("%x", rand()%16);
}
printf("\n");
return EXIT_SUCCESS;
}
If you wanted to store them in a buffer to compare with something else later, you might want to look at sprintf instead of printf. For that, you really need to understand how strings are allocated and used in C first.
EDIT: This might be more what you're after. It reads hexadecimal digits from standard input (which can be redirected from a file if desired) and checks to see if they follow the pattern that you described.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
int expected_number = 7;
unsigned int read_number;
while (1 == scanf("%2x", &read_number)) {
if (expected_number != read_number) {
fprintf(stderr, "Expected %02x but got %02x.\n", expected_number, read_number);
}
expected_number--;
if (expected_number == -1) expected_number = 15;
}
return EXIT_SUCCESS;
}
Your numbers are large, so use a 64-bit unsigned integer data type, such as unsigned long long. You won't be able to deal with numbers greater than 2**64 without adopting a new scheme. Print hex values using printf("%x", value).
You can look at GNU GMP library for arbitrarily large integers.

Resources