Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Paste
P50
GPT test
Active
Public
Actions
Authored by
•
aheinecke
on Jul 15 2024, 1:32 PM.
Edit Paste
Archive Paste
View Raw File
Subscribe
Mute Notifications
Award Token
Tags
None
Subscribers
None
/*This program was created by the prompt:
Write a c program that uses libgcrypt to print or check checksums.
The invocation should be: @NAME_OF_THE_PROGRAM@ [OPTION]... [FILE]...
Print or check checksums of the file or files FILE.
With no FILE, or when FILE is -, read standard input.
Options are:
-z, --zero end each output line with NUL, not newline, and disable file name escaping
-c, --check read checksums from the FILEs and check them
-a, --algo the algorithm to use for calculating the hashsum
-l, --list list all available algorithms
The default output is to print a line with: checksum, two spaces,
and name for each FILE.
The program should be called hash, but if its filename is not
hash or hash.exe and the filename matches a known hash algorithm
it should use the filename of the executable as the --algo parameter.
The program should provide all the hash algorithms available in
libgcrypt 1.10
The list option should list all the algrithms which can be used
as for the --algo parameter.
Check should read in a file that matches the output and for
each line should calculate the hash sum of the filenme and
compare it to the checksum in the same line. If the checksum
differs an error should be printed containing the filename
and the program should exit with a nonzero return code.
*/
#include
<stdio.h>
#include
<stdlib.h>
#include
<string.h>
#include
<libgen.h>
#include
<gcrypt.h>
#include
<getopt.h>
#include
<unistd.h>
#include
<fcntl.h>
#define BUF_SIZE 4096
void
print_usage
()
{
printf
(
"Usage: hash [OPTION]... [FILE]...
\n
"
);
printf
(
"Print or check checksums of the file or files FILE.
\n\n
"
);
printf
(
"With no FILE, or when FILE is -, read standard input.
\n\n
"
);
printf
(
"Options are:
\n
"
);
printf
(
" -z, --zero end each output line with NUL, not newline, and disable file name escaping
\n
"
);
printf
(
" -c, --check read checksums from the FILEs and check them
\n
"
);
printf
(
" -a, --algo the algorithm to use for calculating the hashsum
\n
"
);
printf
(
" -l, --list list all available algorithms
\n
"
);
}
void
list_algorithms
()
{
printf
(
"Available algorithms:
\n
"
);
for
(
int
i
=
1
;
i
<
400
;
i
++
)
{
const
char
*
algo_name
=
gcry_md_algo_name
(
i
);
if
(
!
algo_name
)
{
break
;
}
if
(
!
strcmp
(
algo_name
,
"?"
))
{
continue
;
}
printf
(
" %s
\n
"
,
algo_name
);
}
}
void
calculate_checksum
(
const
char
*
filename
,
int
algo
,
int
zero_end
)
{
FILE
*
file
=
stdin
;
if
(
filename
&&
strcmp
(
filename
,
"-"
)
!=
0
)
{
file
=
fopen
(
filename
,
"rb"
);
if
(
!
file
)
{
perror
(
"Error opening file"
);
return
;
}
}
gcry_md_hd_t
hd
;
gcry_md_open
(
&
hd
,
algo
,
0
);
char
buf
[
BUF_SIZE
];
size_t
n
;
while
((
n
=
fread
(
buf
,
1
,
BUF_SIZE
,
file
))
>
0
)
{
gcry_md_write
(
hd
,
buf
,
n
);
}
if
(
file
!=
stdin
)
{
fclose
(
file
);
}
unsigned
char
*
hash
=
gcry_md_read
(
hd
,
algo
);
size_t
hash_len
=
gcry_md_get_algo_dlen
(
algo
);
for
(
size_t
i
=
0
;
i
<
hash_len
;
i
++
)
{
printf
(
"%02x"
,
hash
[
i
]);
}
if
(
filename
&&
strcmp
(
filename
,
"-"
)
!=
0
)
{
printf
(
" %s%c"
,
filename
,
zero_end
?
'\0'
:
'\n'
);
}
else
{
printf
(
"%c"
,
zero_end
?
'\0'
:
'\n'
);
}
gcry_md_close
(
hd
);
}
int
check_checksums
(
const
char
*
filename
,
int
algo
)
{
FILE
*
file
=
fopen
(
filename
,
"r"
);
if
(
!
file
)
{
perror
(
"Error opening file"
);
return
1
;
}
char
line
[
BUF_SIZE
];
while
(
fgets
(
line
,
sizeof
(
line
),
file
))
{
char
*
hash_str
=
strtok
(
line
,
" "
);
strtok
(
NULL
,
" "
);
char
*
file_name
=
strtok
(
NULL
,
"
\n
"
);
if
(
!
hash_str
||
!
file_name
)
{
fprintf
(
stderr
,
"Malformed line in checksum file: %s
\n
"
,
line
);
fclose
(
file
);
return
1
;
}
FILE
*
check_file
=
fopen
(
file_name
,
"rb"
);
if
(
!
check_file
)
{
perror
(
"Error opening file to check"
);
fclose
(
file
);
return
1
;
}
gcry_md_hd_t
hd
;
gcry_md_open
(
&
hd
,
algo
,
0
);
char
buf
[
BUF_SIZE
];
size_t
n
;
while
((
n
=
fread
(
buf
,
1
,
BUF_SIZE
,
check_file
))
>
0
)
{
gcry_md_write
(
hd
,
buf
,
n
);
}
fclose
(
check_file
);
unsigned
char
*
hash
=
gcry_md_read
(
hd
,
algo
);
size_t
hash_len
=
gcry_md_get_algo_dlen
(
algo
);
char
computed_hash
[
hash_len
*
2
+
1
];
for
(
size_t
i
=
0
;
i
<
hash_len
;
i
++
)
{
sprintf
(
&
computed_hash
[
i
*
2
],
"%02x"
,
hash
[
i
]);
}
if
(
strcmp
(
hash_str
,
computed_hash
)
!=
0
)
{
fprintf
(
stderr
,
"Checksum mismatch for file %s
\n
"
,
file_name
);
gcry_md_close
(
hd
);
fclose
(
file
);
return
1
;
}
gcry_md_close
(
hd
);
}
fclose
(
file
);
return
0
;
}
int
main
(
int
argc
,
char
*
argv
[])
{
int
zero_end
=
0
;
int
check
=
0
;
int
list
=
0
;
const
char
*
algo_str
=
NULL
;
int
algo
=
GCRY_MD_SHA256
;
// Default algorithm
static
struct
option
long_options
[]
=
{
{
"zero"
,
no_argument
,
0
,
'z'
},
{
"check"
,
no_argument
,
0
,
'c'
},
{
"algo"
,
required_argument
,
0
,
'a'
},
{
"list"
,
no_argument
,
0
,
'l'
},
{
0
,
0
,
0
,
0
}
};
int
c
;
while
((
c
=
getopt_long
(
argc
,
argv
,
"zca:l"
,
long_options
,
NULL
))
!=
-1
)
{
switch
(
c
)
{
case
'z'
:
zero_end
=
1
;
break
;
case
'c'
:
check
=
1
;
break
;
case
'a'
:
algo_str
=
optarg
;
break
;
case
'l'
:
list
=
1
;
break
;
default
:
print_usage
();
return
1
;
}
}
if
(
list
)
{
list_algorithms
();
return
0
;
}
if
(
algo_str
)
{
algo
=
gcry_md_map_name
(
algo_str
);
if
(
algo
==
0
)
{
fprintf
(
stderr
,
"Unknown algorithm: %s
\n
"
,
algo_str
);
return
1
;
}
}
else
{
char
*
base_name
=
basename
(
argv
[
0
]);
if
(
base_name
&&
strcmp
(
base_name
,
"hash"
)
!=
0
&&
strcmp
(
base_name
,
"hash.exe"
)
!=
0
)
{
algo
=
gcry_md_map_name
(
base_name
);
if
(
algo
==
0
)
{
fprintf
(
stderr
,
"Unknown algorithm: %s
\n
"
,
base_name
);
return
1
;
}
}
}
if
(
check
)
{
if
(
optind
==
argc
)
{
fprintf
(
stderr
,
"No checksum file specified for checking
\n
"
);
return
1
;
}
return
check_checksums
(
argv
[
optind
],
algo
);
}
if
(
optind
==
argc
)
{
calculate_checksum
(
"-"
,
algo
,
zero_end
);
}
else
{
for
(
int
i
=
optind
;
i
<
argc
;
i
++
)
{
calculate_checksum
(
argv
[
i
],
algo
,
zero_end
);
}
}
return
0
;
}
Event Timeline
•
aheinecke
created this paste.
Jul 15 2024, 1:32 PM
2024-07-15 13:32:15 (UTC+2)
Log In to Comment