1 /**********************************************************************
3 * Copyright (c) 2005-2006 Cryptocom LTD *
4 * This file is distributed under the same license as OpenSSL *
6 * Almost drop-in replacement for md5sum and sha1sum *
7 * which computes GOST R 34.11-94 hashsum instead *
9 **********************************************************************/
17 #define BUF_SIZE 262144
18 int hash_file(gost_hash_ctx *ctx,char *filename,char *sum,int mode);
19 int hash_stream(gost_hash_ctx *ctx,int fd, char *sum);
20 int get_line(FILE *f,char *hash,char *filename);
23 fprintf(stderr,"gostsum [-bvt] [-c [file]]| [files]\n"
24 "\t-c check message digests (default is generate)\n"
25 "\t-v verbose, print file names when checking\n"
26 "\t-b read files in binary mode\n"
27 "\t-t use test GOST paramset (default is CryptoPro paramset)\n"
28 "The input for -c should be the list of message digests and file names\n"
29 "that is printed on stdout by this program when it generates digests.\n");
37 int main(int argc,char **argv)
42 int open_mode = O_RDONLY;
43 gost_subst_block *b= &GostR3411_94_CryptoProParamSet;
44 FILE *check_file = NULL;
47 while( (c=getopt(argc,argv,"bc::tv"))!=-1)
51 case 'v': verbose=1; break;
52 case 't': b= &GostR3411_94_TestParamSet; break;
53 case 'b': open_mode |= O_BINARY; break;
54 case 'c': if (optarg) {
55 check_file = fopen(optarg,"r");
65 fprintf(stderr,"invalid option %c",optopt);
69 init_gost_hash_ctx(&ctx,b);
72 char inhash[65],calcsum[65],filename[PATH_MAX];
73 int failcount=0,count=0;;
74 if (check_file==stdin && optind<argc)
76 check_file=fopen(argv[optind],"r");
83 while (get_line(check_file,inhash,filename))
85 if (!hash_file(&ctx,filename,calcsum,open_mode)) {
89 if (!strncmp(calcsum,inhash,65))
92 fprintf(stderr,"%s\tOK\n",filename);
96 fprintf(stderr,"%s\tFAILED\n",filename);
98 fprintf(stderr,"%s: GOST hash sum check failed for '%s'\n",
104 if (verbose && failcount) {
105 fprintf(stderr,"%s: %d of %d file(f) failed GOST hash sum check\n",
106 argv[0],failcount,count);
108 exit (failcount?1:0);
112 if (!hash_stream(&ctx,fileno(stdin),sum)) {
116 printf("%s -\n",sum);
119 for (i=optind;i<argc;i++) {
121 if (!hash_file(&ctx,argv[i],sum,open_mode)) {
124 printf("%s %s\n",sum,argv[i]);
130 int hash_file(gost_hash_ctx *ctx,char *filename,char *sum,int mode)
133 if ((fd=open(filename,mode))<0) {
137 if (!hash_stream(ctx,fd,sum)) {
145 int hash_stream(gost_hash_ctx *ctx,int fd, char *sum)
147 unsigned char buffer[BUF_SIZE];
151 while ((bytes=read(fd,buffer,BUF_SIZE))>0) {
152 hash_block(ctx,buffer,bytes);
157 finish_hash(ctx,buffer);
159 sprintf(sum+2*i,"%02x",buffer[31-i]);
164 int get_line(FILE *f,char *hash,char *filename) {
166 if (fread(hash,1,64,f)<64) return 0;
170 if (hash[i]<'0' || (hash[i]>'9' && hash[i]<'A') || (hash[i]>'F'
171 && hash[i]<'a')||hash[i]>'f')
173 fprintf(stderr,"Not a hash value '%s'\n",hash);
178 fprintf(stderr,"Malformed input line\n");
181 i=strlen(fgets(filename,PATH_MAX,f));
182 while (filename[--i]=='\n'||filename[i]=='\r') filename[i]=0;