1 /* Copyright (C) 2014, 2015 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/>.
31 #include "SHA3api_ref.h"
33 #define hashbitlen 1024
34 #define MaxNmberFiles 10
35 #define skeinVersion "1.3"
38 char invalidOption = 0;
49 static struct option const long_options[] =
51 { "binary", no_argument, NULL, 'b' },
52 { "check", no_argument, NULL, 'c' },
53 { "quiet", no_argument, NULL, QUIET_OPTION },
54 { "status", no_argument, NULL, STATUS_OPTION },
55 { "text", no_argument, NULL, 't' },
56 { "warn", no_argument, NULL, 'w' },
57 { "tag", no_argument, NULL, TAG_OPTION },
58 { "help", no_argument, NULL, HELP_OPTION },
59 { "version", no_argument, NULL, VERSION_OPTION },
63 void printHexMsg(unsigned char *ptr, int size, char result[])
68 for (i = 0 ; i < size ; i ++)
73 if (High >= 0xA && High <= 0xF)
75 else if(High >= 0x0 && High <= 0x9)
78 if (Low >= 0xA && Low <= 0xF)
80 else if(Low >= 0x0 && Low <= 0x9)
89 int HashTextMode(char file_name[], char MsgDigest[])
91 FILE *fp_in = fopen(file_name,"r");
94 long size_fp_in = st.st_size;
98 printf("skein%dsum: %s: No such file or directory\n",hashbitlen,file_name);
99 printf(" %s FAILED open or read\n",file_name);
104 hello = (char*) malloc (size_fp_in);
105 fgets(hello,size_fp_in,fp_in);
107 unsigned char output[hashbitlen/4];
108 Hash(hashbitlen,(unsigned char*) hello,size_fp_in,output);
110 printHexMsg(output,hashbitlen/4,MsgDigest);
116 int HashBinaryMode(char file_name[],char MsgDigest[])
118 FILE *fp_in = fopen(file_name,"rb");
120 stat(file_name, &st);
121 long size_fp_in = st.st_size;
125 printf("skein%dsum: %s: No such file or directory\n",hashbitlen,file_name);
126 printf(" %s FAILED open or read\n",file_name);
130 unsigned char *hello;
131 hello = (unsigned char*) malloc (size_fp_in);
132 fread(hello,size_fp_in,1,fp_in);
134 unsigned char output[hashbitlen/4];
135 Hash(hashbitlen,hello,size_fp_in,output);
137 printHexMsg(output,hashbitlen/4,MsgDigest);
143 int HashStringMode(char Msg[],char MsgDigest[])
145 unsigned char output[hashbitlen/4];
146 Hash(hashbitlen,(unsigned char*) Msg,sizeof(Msg),output);
147 printHexMsg(output,hashbitlen/4,MsgDigest);
153 * return 2 : is Directory
154 * return -1 : Something else.
156 int isFile(char argument[])
159 if( stat(argument,&s) == 0 )
161 if( s.st_mode & S_IFDIR )
165 else if( s.st_mode & S_IFREG )
175 int isProper(char MsgDigest[])
177 if ((strlen(MsgDigest) - hashbitlen/4) != 0)
181 for(index = 0; index < strlen(MsgDigest);index++)
183 c = MsgDigest[index];
184 if(!(( c >= '0' && c <= '9' ) || ( c >= 'A' && c <= 'F')))
192 int decomposeHashLine(char hash[], char MsgDigest_tmp[], char file_tmp[])
199 while(((c = hash[i])!=' ')&&((c = hash[i])!='_'))
206 sprintf(alg,"skein%d",hashbitlen);
214 strcpy(MsgDigest_tmp,tmp);
216 while((c = hash[i])!= '\n')
218 file_tmp[j] = hash[i];
224 else if((hash[i]=='_')&&(hash[i+1]=='v'))
229 while((c = hash[i])!=' ')
231 version[j] = hash[i];
236 float vers = 0, skeinVers = 0;
237 sscanf(version,"%f",&vers);
238 sscanf(skeinVersion,"%f",&skeinVers);
242 while((c = hash[i])!=')')
244 file_tmp[j] = hash[i];
252 while((c = hash[i])!='\n')
254 MsgDigest_tmp[j] = hash[i];
258 MsgDigest_tmp[j] = 0;
261 {//version newer than mine
264 else if (skeinVers > vers)
265 {//going to use older version than mine
279 int main(int argc, char** argv)
281 char MsgDigest[hashbitlen/2];
282 char **list_files = (char**) malloc(MaxNmberFiles* sizeof(char*));
283 int number_files = 0;
297 /*****************************************************************************************
298 ************************************* GETTING DATA ***********************************
299 *****************************************************************************************/
300 while ((opt = getopt_long (argc, argv, "bctw", long_options, NULL)) != -1)
339 case VERSION_OPTION :
364 printf("Try `skein%dsum --help' for more information.\n",hashbitlen);
368 for (; optind < argc; ++optind)
373 {// no options found, test if there is a file and hash it
374 if(isFile(argv[optind]) == 1)
376 char *file_name = malloc(sizeof(argv[optind]));
377 file_name = argv[optind];
378 list_files[number_files] = (char*) malloc (sizeof(file_name));
379 list_files[number_files] = file_name;
382 else if (isFile(argv[optind]) == 2)
384 printf("skein%dsum: %s Is a directory\n",hashbitlen,argv[optind]);
389 printf("skein%dsum: %s: No such file or directory\n",hashbitlen,argv[optind]);
396 /*****************************************************************************************
397 ************************************* PROCESSING DATA ***********************************
398 *****************************************************************************************/
399 if(argc > 1 && version == 1)
401 printf("skein1024sum 1.0\n");
402 printf("License GPLv3+: GNU GPL version 3 or later\n");
403 printf("<http://gnu.org/licenses/gpl.html>\n");
404 printf("This is free software: you are free to change and redistribute it.\n");
405 printf("There is NO WARRANTY, to the extent permitted by law.\n");
408 if(argc > 1 && help == 1)
411 printf("Usage: skein%dsum [OPTION]... [FILE]...\n",hashbitlen);
412 printf("Print or check skein (%d-bit) checksums.\n",hashbitlen);
413 printf("With no FILE, or when FILE is -, read standard input.\n");
415 printf("-b, --binary read in binary mode\n");
416 printf("-c, --check read skein sums from the FILEs and check them\n");
417 printf("--tag create a BSD-style checksum\n");
418 printf("-t, --text read in text mode (default)\n");
420 printf("The following three options are useful only when verifying checksums:\n");
421 printf("--quiet don't print OK for each successfully verified file\n");
422 printf("--status don't output anything, status code shows success\n");
423 printf("-w, --warn warn about improperly formatted checksum lines\n");
425 printf("--strict with --check, exit non-zero for any invalid input\n");
426 printf("--help display this help and exit\n");
427 printf("--version output version information and exit\n");
429 printf("The sums are computed as described in version 1.3 of the Skein\n");
430 printf("specification. When checking, the input should be a former output of\n");
431 printf("this program. The default mode is to print a line with checksum, a\n");
432 printf("character indicating input mode ('*' for binary, space for text), and\n");
433 printf("name for each FILE.\n");
437 if(argc > 1 && binary == 1)
439 if (check == 1 || quiet == 1 || warn == 1 || status == 1)
441 printf("skein%dsum: the --binary and --text options are meaningless when verifying checksums\n",hashbitlen);
442 printf("Try 'skein%dsum --help' for more information.\n",hashbitlen);
448 while(index_files < number_files)
452 printf("skein%dsum: %s: No such file or directory\n",hashbitlen,list_files[index_files]);
456 if(HashBinaryMode(list_files[index_files],MsgDigest)!=-1)
460 printf("skein%d_v%s (%s) = %s\n",hashbitlen,skeinVersion,list_files[index_files],MsgDigest);
464 printf("%s ",MsgDigest);
465 printf("*%s\n",list_files[index_files]);
471 else if(errorFound != 1)
472 { // read stdin for strings
474 char longstring[1000];
476 while((fgets(stri,100,stdin))!=NULL)
478 strcat(longstring,stri);
480 HashStringMode(longstring,MsgDigest);
483 printf("skein%d_v%s (-) = %s\n",hashbitlen,skeinVersion,MsgDigest);
487 printf("%s *-\n",MsgDigest);
492 else if (argc > 1 && binary == 0) // Text Mode
494 if (check == 1 || quiet == 1 || warn == 1 || status == 1)
496 printf("skein%dsum: the --binary and --text options are meaningless when verifying checksums\n",hashbitlen);
497 printf("Try 'skein%dsum --help' for more information.\n",hashbitlen);
503 while(index_files < number_files)
505 if(HashTextMode(list_files[index_files],MsgDigest)!=-1)
509 printf("skein%d_v%s (%s) = %s\n",hashbitlen,skeinVersion,list_files[index_files],MsgDigest);
513 printf("%s ",MsgDigest);
514 printf("%s\n",list_files[index_files]);
520 else if(errorFound != 1)
521 { // read stdin for strings
523 char longstring[1000];
525 while((fgets(stri,100,stdin))!=NULL)
527 strcat(longstring,stri);
529 HashStringMode(longstring,MsgDigest);
532 printf("skein%d_v%s (-) = %s\n",hashbitlen,skeinVersion,MsgDigest);
536 printf("%s -\n",MsgDigest);
541 else if (argc > 1 && binary == -1)
544 {// hashing stdin entries
545 if(quiet == 1 || status == 1 || warn == 1)
548 printf("skein%dsum: the --quiet option is meaningful only when verifying checksums\n",hashbitlen);
550 printf("skein%dsum: the --status option is meaningful only when verifying checksums\n",hashbitlen);
552 printf("skein%dsum: the --warn option is meaningful only when verifying checksums\n",hashbitlen);
554 printf("Try 'skein%dsum --help' for more information.\n",hashbitlen);
560 while(index_files < number_files)
562 if(HashTextMode(list_files[index_files],MsgDigest)!=-1)
566 printf("skein%d_v%s (%s) = %s\n",hashbitlen,skeinVersion,list_files[index_files],MsgDigest);
570 printf("%s ",MsgDigest);
571 printf("%s\n",list_files[index_files]);
577 else if(errorFound != 1)
578 { // hasing strings read from stdin
580 char longstring[1000];
582 while((fgets(stri,100,stdin))!=NULL)
584 strcat(longstring,stri);
586 HashStringMode(longstring,MsgDigest);
589 printf("skein%d_v%s (-) = %s\n",hashbitlen,skeinVersion,MsgDigest);
593 printf("%s -\n",MsgDigest);
601 printf("skein%dsum: the --tag option is meaningless when verifying checksums\n",hashbitlen);
602 printf("Try 'skein%dsum --help' for more information\n",hashbitlen);
606 while(index_files < number_files)
609 char hash[500], file_name[100], file_tmp[100], MsgDigest_tmp[hashbitlen/2];
610 int NoMatch = 0, NotProper = 0, Computed = 0;
611 strcpy(file_name,list_files[index_files]);
614 fp = fopen(file_name,"r");
617 while(fgets(hash,500,fp)!=NULL)
621 unsigned int hashVersion = decomposeHashLine(hash,MsgDigest_tmp,file_tmp);
622 if(hashVersion == -1)
624 printf("skein%d: %s is using newer version of skein%d algorithm\n",hashbitlen,file_tmp,hashbitlen);
625 printf("You should update your algorithm\n");
628 else if( hashVersion == 0)
630 printf("skein%d: %s is using an older version of skein%d algorithm\n",hashbitlen,file_tmp,hashbitlen);
631 printf("You should use the older algorithm\n");
636 if(!isProper(MsgDigest_tmp))
638 if(status != 1 && warn == 1)
640 printf("skein%dsum: %s: %d: improperly formatted skein%d checksum line\n",hashbitlen,file_tmp,line,hashbitlen);
646 if(file_tmp[0] == '*')
648 int index_file_tmp = 0;
649 for( ; file_tmp[index_file_tmp+1]!=0 ; index_file_tmp++)
651 file_tmp[index_file_tmp] = file_tmp[index_file_tmp + 1];
653 file_tmp[index_file_tmp] = 0;
654 HashBinaryMode(file_tmp,MsgDigest);
658 HashTextMode(file_tmp,MsgDigest);
661 if(!strcmp(MsgDigest,MsgDigest_tmp))
665 printf("%s: OK\n",file_tmp);
670 printf("%s: FAILED\n",file_tmp);
677 printf("skein%dsum: WARNING: %d of %d computed checksums did NOT match\n",
678 hashbitlen,NoMatch,Computed);
682 printf("skein%dsum: WARNING: %d line is improperly formatted\n",hashbitlen,NotProper);
687 printf("skein%dsum: %s: No such file or directory\n",hashbitlen,file_name);
693 if(number_files == 0)
695 char longstring[1000];
697 char MsgDigest_tmp[hashbitlen/2];
698 int Computed = 0, NotProper = 0, NoMatch = 0 , line = 0;
699 while((fgets(longstring,1000,stdin))!=NULL)
703 decomposeHashLine(longstring,MsgDigest_tmp,file_name);
704 if(!isProper(MsgDigest_tmp))
706 if(status != 1 && warn == 1)
708 printf("skein%dsum: %s: %d: improperly formatted skein%d checksum line\n",hashbitlen,file_name,line,hashbitlen);
714 if(file_name[0] == '*')
716 int index_file_tmp = 0;
717 for( ; file_name[index_file_tmp+1]!=0 ; index_file_tmp++)
719 file_name[index_file_tmp] = file_name[index_file_tmp + 1];
721 file_name[index_file_tmp] = 0;
722 HashBinaryMode(file_name,MsgDigest);
726 HashTextMode(file_name,MsgDigest);
729 if(!strcmp(MsgDigest,MsgDigest_tmp))
733 printf("%s: OK\n",file_name);
738 printf("%s: FAILED\n",file_name);
744 printf("skein%dsum: WARNING: %d of %d computed checksums did NOT match\n",
745 hashbitlen,NoMatch,Computed);
749 printf("skein%dsum: WARNING: %d line is improperly formatted\n",hashbitlen,NotProper);
758 if ((errorFound != 1) && (argc == 1 || (hashString == 1 && number_files == 0)))
761 char longstring[1000];
763 while((fgets(stri,100,stdin))!=NULL)
765 strcat(longstring,stri);
767 HashStringMode(longstring,MsgDigest);
768 printf("%s -\n",MsgDigest);