1 /* Copyright (C) 2014 Jason Self <j@jxself.org>
3 This file is part of skeinsum.
5 skeinsum is free software: you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 skeinsum is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with skeinsum. If not, see <http://www.gnu.org/licenses/>.
29 #include "SHA3api_ref.h"
31 #define hashbitlen 512
32 #define MaxNmberFiles 10
33 #define skeinVersion "1.3"
36 char invalidOption = 0;
47 static struct option const long_options[] =
49 { "binary", no_argument, NULL, 'b' },
50 { "check", no_argument, NULL, 'c' },
51 { "quiet", no_argument, NULL, QUIET_OPTION },
52 { "status", no_argument, NULL, STATUS_OPTION },
53 { "text", no_argument, NULL, 't' },
54 { "warn", no_argument, NULL, 'w' },
55 { "tag", no_argument, NULL, TAG_OPTION },
56 { "help", no_argument, NULL, HELP_OPTION },
57 { "version", no_argument, NULL, VERSION_OPTION },
61 void printHexMsg(unsigned char *ptr, int size, char result[])
66 for (i = 0 ; i < size ; i ++)
71 if (High >= 0xA && High <= 0xF)
73 else if(High >= 0x0 && High <= 0x9)
76 if (Low >= 0xA && Low <= 0xF)
78 else if(Low >= 0x0 && Low <= 0x9)
87 int HashTextMode(char file_name[], char MsgDigest[])
89 FILE *fp_in = fopen(file_name,"r");
92 long size_fp_in = st.st_size;
96 printf("skein%dsum: %s: No such file or directory\n",hashbitlen,file_name);
97 printf(" %s FAILED open or read\n",file_name);
102 hello = (char*) malloc (size_fp_in);
103 fgets(hello,size_fp_in,fp_in);
105 unsigned char output[hashbitlen/4];
106 Hash(hashbitlen,(unsigned char*) hello,size_fp_in,output);
108 printHexMsg(output,hashbitlen/4,MsgDigest);
114 int HashBinaryMode(char file_name[],char MsgDigest[])
116 FILE *fp_in = fopen(file_name,"rb");
118 stat(file_name, &st);
119 long size_fp_in = st.st_size;
123 printf("skein%dsum: %s: No such file or directory\n",hashbitlen,file_name);
124 printf(" %s FAILED open or read\n",file_name);
128 unsigned char *hello;
129 hello = (unsigned char*) malloc (size_fp_in);
130 fread(hello,size_fp_in,1,fp_in);
132 unsigned char output[hashbitlen/4];
133 Hash(hashbitlen,hello,size_fp_in,output);
135 printHexMsg(output,hashbitlen/4,MsgDigest);
141 int HashStringMode(char Msg[],char MsgDigest[])
143 unsigned char output[hashbitlen/4];
144 Hash(hashbitlen,(unsigned char*) Msg,sizeof(Msg),output);
145 printHexMsg(output,hashbitlen/4,MsgDigest);
151 * return 2 : is Directory
152 * return -1 : Something else.
154 int isFile(char argument[])
157 if( stat(argument,&s) == 0 )
159 if( s.st_mode & S_IFDIR )
163 else if( s.st_mode & S_IFREG )
173 int isProper(char MsgDigest[])
175 if ((strlen(MsgDigest) - hashbitlen/4) != 0)
179 for(index = 0; index < strlen(MsgDigest);index++)
181 c = MsgDigest[index];
182 if(!(( c >= '0' && c <= '9' ) || ( c >= 'A' && c <= 'F')))
190 int decomposeHashLine(char hash[], char MsgDigest_tmp[], char file_tmp[])
197 while(((c = hash[i])!=' ')&&((c = hash[i])!='_'))
204 sprintf(alg,"skein%d",hashbitlen);
212 strcpy(MsgDigest_tmp,tmp);
214 while((c = hash[i])!= '\n')
216 file_tmp[j] = hash[i];
222 else if((hash[i]=='_')&&(hash[i+1]=='v'))
227 while((c = hash[i])!=' ')
229 version[j] = hash[i];
234 float vers = 0, skeinVers = 0;
235 sscanf(version,"%f",&vers);
236 sscanf(skeinVersion,"%f",&skeinVers);
240 while((c = hash[i])!=')')
242 file_tmp[j] = hash[i];
250 while((c = hash[i])!='\n')
252 MsgDigest_tmp[j] = hash[i];
256 MsgDigest_tmp[j] = 0;
259 {//version newer than mine
262 else if (skeinVers > vers)
263 {//going to use older version than mine
277 int main(int argc, char** argv)
279 char MsgDigest[hashbitlen/2];
280 char **list_files = (char**) malloc(MaxNmberFiles* sizeof(char*));
281 int number_files = 0;
295 /*****************************************************************************************
296 ************************************* GETTING DATA ***********************************
297 *****************************************************************************************/
298 while ((opt = getopt_long (argc, argv, "bctw", long_options, NULL)) != -1)
337 case VERSION_OPTION :
362 printf("Try `skein%dsum --help' for more information.\n",hashbitlen);
366 for (; optind < argc; ++optind)
371 {// no options found, test if there is a file and hash it
372 if(isFile(argv[optind]) == 1)
374 char *file_name = malloc(sizeof(argv[optind]));
375 file_name = argv[optind];
376 list_files[number_files] = (char*) malloc (sizeof(file_name));
377 list_files[number_files] = file_name;
380 else if (isFile(argv[optind]) == 2)
382 printf("skein%dsum: %s Is a directory\n",hashbitlen,argv[optind]);
387 printf("skein%dsum: %s: No such file or directory\n",hashbitlen,argv[optind]);
394 /*****************************************************************************************
395 ************************************* PROCESSING DATA ***********************************
396 *****************************************************************************************/
397 if(argc > 1 && version == 1)
399 printf("skein512sum 1.0\n");
400 printf("License GPLv3+: GNU GPL version 3 or later\n");
401 printf("<http://gnu.org/licenses/gpl.html>\n");
402 printf("This is free software: you are free to change and redistribute it.\n");
403 printf("There is NO WARRANTY, to the extent permitted by law.\n");
406 if(argc > 1 && help == 1)
409 printf("Usage: skein%dsum [OPTION]... [FILE]...\n",hashbitlen);
410 printf("Print or check skein (%d-bit) checksums.\n",hashbitlen);
411 printf("With no FILE, or when FILE is -, read standard input.\n");
413 printf("-b, --binary read in binary mode\n");
414 printf("-c, --check read skein sums from the FILEs and check them\n");
415 printf("--tag create a BSD-style checksum\n");
416 printf("-t, --text read in text mode (default)\n");
418 printf("The following three options are useful only when verifying checksums:\n");
419 printf("--quiet don't print OK for each successfully verified file\n");
420 printf("--status don't output anything, status code shows success\n");
421 printf("-w, --warn warn about improperly formatted checksum lines\n");
423 printf("--strict with --check, exit non-zero for any invalid input\n");
424 printf("--help display this help and exit\n");
425 printf("--version output version information and exit\n");
427 printf("The sums are computed as described in version 1.3 of the Skein\n");
428 printf("specification. When checking, the input should be a former output of\n");
429 printf("this program. The default mode is to print a line with checksum, a\n");
430 printf("character indicating input mode ('*' for binary, space for text), and\n");
431 printf("name for each FILE.\n");
435 if(argc > 1 && binary == 1)
437 if (check == 1 || quiet == 1 || warn == 1 || status == 1)
439 printf("skein%dsum: the --binary and --text options are meaningless when verifying checksums\n",hashbitlen);
440 printf("Try 'skein%dsum --help' for more information.\n",hashbitlen);
446 while(index_files < number_files)
450 printf("skein%dsum: %s: No such file or directory\n",hashbitlen,list_files[index_files]);
454 if(HashBinaryMode(list_files[index_files],MsgDigest)!=-1)
458 printf("skein%d_v%s (%s) = %s\n",hashbitlen,skeinVersion,list_files[index_files],MsgDigest);
462 printf("%s ",MsgDigest);
463 printf("*%s\n",list_files[index_files]);
469 else if(errorFound != 1)
470 { // read stdin for strings
472 char longstring[1000];
474 while((fgets(stri,100,stdin))!=NULL)
476 strcat(longstring,stri);
478 HashStringMode(longstring,MsgDigest);
481 printf("skein%d_v%s (-) = %s\n",hashbitlen,skeinVersion,MsgDigest);
485 printf("%s *-\n",MsgDigest);
490 else if (argc > 1 && binary == 0) // Text Mode
492 if (check == 1 || quiet == 1 || warn == 1 || status == 1)
494 printf("skein%dsum: the --binary and --text options are meaningless when verifying checksums\n",hashbitlen);
495 printf("Try 'skein%dsum --help' for more information.\n",hashbitlen);
501 while(index_files < number_files)
503 if(HashTextMode(list_files[index_files],MsgDigest)!=-1)
507 printf("skein%d_v%s (%s) = %s\n",hashbitlen,skeinVersion,list_files[index_files],MsgDigest);
511 printf("%s ",MsgDigest);
512 printf("%s\n",list_files[index_files]);
518 else if(errorFound != 1)
519 { // read stdin for strings
521 char longstring[1000];
523 while((fgets(stri,100,stdin))!=NULL)
525 strcat(longstring,stri);
527 HashStringMode(longstring,MsgDigest);
530 printf("skein%d_v%s (-) = %s\n",hashbitlen,skeinVersion,MsgDigest);
534 printf("%s -\n",MsgDigest);
539 else if (argc > 1 && binary == -1)
542 {// hashing stdin entries
543 if(quiet == 1 || status == 1 || warn == 1)
546 printf("skein%dsum: the --quiet option is meaningful only when verifying checksums\n",hashbitlen);
548 printf("skein%dsum: the --status option is meaningful only when verifying checksums\n",hashbitlen);
550 printf("skein%dsum: the --warn option is meaningful only when verifying checksums\n",hashbitlen);
552 printf("Try 'skein%dsum --help' for more information.\n",hashbitlen);
558 while(index_files < number_files)
560 if(HashTextMode(list_files[index_files],MsgDigest)!=-1)
564 printf("skein%d_v%s (%s) = %s\n",hashbitlen,skeinVersion,list_files[index_files],MsgDigest);
568 printf("%s ",MsgDigest);
569 printf("%s\n",list_files[index_files]);
575 else if(errorFound != 1)
576 { // hasing strings read from stdin
578 char longstring[1000];
580 while((fgets(stri,100,stdin))!=NULL)
582 strcat(longstring,stri);
584 HashStringMode(longstring,MsgDigest);
587 printf("skein%d_v%s (-) = %s\n",hashbitlen,skeinVersion,MsgDigest);
591 printf("%s -\n",MsgDigest);
599 printf("skein%dsum: the --tag option is meaningless when verifying checksums\n",hashbitlen);
600 printf("Try 'skein%dsum --help' for more information\n",hashbitlen);
604 while(index_files < number_files)
607 char hash[500], file_name[100], file_tmp[100], MsgDigest_tmp[hashbitlen/2];
608 int NoMatch = 0, NotProper = 0, Computed = 0;
609 strcpy(file_name,list_files[index_files]);
612 fp = fopen(file_name,"r");
615 while(fgets(hash,500,fp)!=NULL)
619 unsigned int hashVersion = decomposeHashLine(hash,MsgDigest_tmp,file_tmp);
620 if(hashVersion == -1)
622 printf("skein%d: %s is using newer version of skein%d algorithm\n",hashbitlen,file_tmp,hashbitlen);
623 printf("You should update your algorithm\n");
626 else if( hashVersion == 0)
628 printf("skein%d: %s is using an older version of skein%d algorithm\n",hashbitlen,file_tmp,hashbitlen);
629 printf("You should use the older algorithm\n");
634 if(!isProper(MsgDigest_tmp))
636 if(status != 1 && warn == 1)
638 printf("skein%dsum: %s: %d: improperly formatted skein%d checksum line\n",hashbitlen,file_tmp,line,hashbitlen);
644 if(file_tmp[0] == '*')
646 int index_file_tmp = 0;
647 for( ; file_tmp[index_file_tmp+1]!=0 ; index_file_tmp++)
649 file_tmp[index_file_tmp] = file_tmp[index_file_tmp + 1];
651 file_tmp[index_file_tmp] = 0;
652 HashBinaryMode(file_tmp,MsgDigest);
656 HashTextMode(file_tmp,MsgDigest);
659 if(!strcmp(MsgDigest,MsgDigest_tmp))
663 printf("%s: OK\n",file_tmp);
668 printf("%s: FAILED\n",file_tmp);
675 printf("skein%dsum: WARNING: %d of %d computed checksums did NOT match\n",
676 hashbitlen,NoMatch,Computed);
680 printf("skein%dsum: WARNING: %d line is improperly formatted\n",hashbitlen,NotProper);
685 printf("skein%dsum: %s: No such file or directory\n",hashbitlen,file_name);
691 if(number_files == 0)
693 char longstring[1000];
695 char MsgDigest_tmp[hashbitlen/2];
696 int Computed = 0, NotProper = 0, NoMatch = 0 , line = 0;
697 while((fgets(longstring,1000,stdin))!=NULL)
701 decomposeHashLine(longstring,MsgDigest_tmp,file_name);
702 if(!isProper(MsgDigest_tmp))
704 if(status != 1 && warn == 1)
706 printf("skein%dsum: %s: %d: improperly formatted skein%d checksum line\n",hashbitlen,file_name,line,hashbitlen);
712 if(file_name[0] == '*')
714 int index_file_tmp = 0;
715 for( ; file_name[index_file_tmp+1]!=0 ; index_file_tmp++)
717 file_name[index_file_tmp] = file_name[index_file_tmp + 1];
719 file_name[index_file_tmp] = 0;
720 HashBinaryMode(file_name,MsgDigest);
724 HashTextMode(file_name,MsgDigest);
727 if(!strcmp(MsgDigest,MsgDigest_tmp))
731 printf("%s: OK\n",file_name);
736 printf("%s: FAILED\n",file_name);
742 printf("skein%dsum: WARNING: %d of %d computed checksums did NOT match\n",
743 hashbitlen,NoMatch,Computed);
747 printf("skein%dsum: WARNING: %d line is improperly formatted\n",hashbitlen,NotProper);
756 if ((errorFound != 1) && (argc == 1 || (hashString == 1 && number_files == 0)))
759 char longstring[1000];
761 while((fgets(stri,100,stdin))!=NULL)
763 strcat(longstring,stri);
765 HashStringMode(longstring,MsgDigest);
766 printf("%s -\n",MsgDigest);