hashsum.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /*
  2. * Written by Daniel Richards <[email protected]> 6/7/2002
  3. * hash.c: This app uses libtomcrypt to hash either stdin or a file
  4. * This file is Public Domain. No rights are reserved.
  5. * Compile with 'gcc hashsum.c -o hashsum -ltomcrypt'
  6. * This example isn't really big enough to warrent splitting into
  7. * more functions ;)
  8. */
  9. #include <tomcrypt.h>
  10. #if _POSIX_C_SOURCE >= 200112L
  11. #include <libgen.h>
  12. #else
  13. #define basename(x) x
  14. #endif
  15. #include "common.h"
  16. #if !defined(PATH_MAX) && defined(_MSC_VER)
  17. #include <windows.h>
  18. #define PATH_MAX MAX_PATH
  19. #endif
  20. /* thanks http://stackoverflow.com/a/8198009 */
  21. #define _base(x) ((x >= '0' && x <= '9') ? '0' : \
  22. (x >= 'a' && x <= 'f') ? 'a' - 10 : \
  23. (x >= 'A' && x <= 'F') ? 'A' - 10 : \
  24. '\255')
  25. #define HEXOF(x) (x - _base(x))
  26. static char* hashsum;
  27. static void die(int status)
  28. {
  29. unsigned long w, x;
  30. FILE* o = status == EXIT_SUCCESS ? stdout : stderr;
  31. fprintf(o, "usage: %s -a algorithm [-c] [file...]\n", hashsum);
  32. fprintf(o, "Algorithms:\n");
  33. w = 0;
  34. for (x = 0; hash_descriptor[x].name != NULL; x++) {
  35. w += fprintf(o, "%-14s", hash_descriptor[x].name);
  36. if (w >= 70) {
  37. fprintf(o, "\n");
  38. w = 0;
  39. }
  40. }
  41. if (w != 0) fprintf(o, "\n");
  42. free(hashsum);
  43. exit(status);
  44. }
  45. static void printf_hex(unsigned char* hash_buffer, unsigned long w)
  46. {
  47. unsigned long x;
  48. for (x = 0; x < w; x++) {
  49. printf("%02x",hash_buffer[x]);
  50. }
  51. }
  52. static void check_file(int argn, int argc, char **argv)
  53. {
  54. int err, failed, invalid;
  55. unsigned char is_buffer[MAXBLOCKSIZE], should_buffer[MAXBLOCKSIZE];
  56. char buf[PATH_MAX + (MAXBLOCKSIZE * 3)];
  57. /* iterate through all files */
  58. while(argn < argc) {
  59. char* s;
  60. FILE* f = fopen(argv[argn], "rb");
  61. if(f == NULL) {
  62. int n = snprintf(buf, sizeof(buf), "%s: %s", hashsum, argv[argn]);
  63. if (n > 0 && n < (int)sizeof(buf))
  64. perror(buf);
  65. else
  66. perror(argv[argn]);
  67. exit(EXIT_FAILURE);
  68. }
  69. failed = 0;
  70. invalid = 0;
  71. /* read the file line by line */
  72. while((s = fgets(buf, sizeof(buf), f)) != NULL)
  73. {
  74. int tries, n;
  75. unsigned long hash_len, w, x;
  76. char* space = strstr(s, " ");
  77. if (space == NULL) {
  78. fprintf(stderr, "%s: no properly formatted checksum lines found\n", hashsum);
  79. goto ERR;
  80. }
  81. hash_len = space - s;
  82. hash_len /= 2;
  83. /* convert the hex-string back to binary */
  84. for (x = 0; x < hash_len; ++x) {
  85. should_buffer[x] = HEXOF(s[x*2]) << 4 | HEXOF(s[x*2 + 1]);
  86. }
  87. space++;
  88. if (*space != '*') {
  89. fprintf(stderr, "%s: unsupported input mode '%c'\n", hashsum, *space);
  90. goto ERR;
  91. }
  92. space++;
  93. for (n = 0; n < (buf + sizeof(buf)) - space; ++n) {
  94. if(iscntrl((int)space[n])) {
  95. space[n] = '\0';
  96. break;
  97. }
  98. }
  99. /* try all hash algorithms that have the appropriate hash size */
  100. tries = 0;
  101. for (x = 0; hash_descriptor[x].name != NULL; ++x) {
  102. if (hash_descriptor[x].hashsize == hash_len) {
  103. tries++;
  104. w = sizeof(is_buffer);
  105. if ((err = hash_file(x, space, is_buffer, &w)) != CRYPT_OK) {
  106. fprintf(stderr, "%s: File hash error: %s: %s\n", hashsum, space, error_to_string(err));
  107. ERR:
  108. fclose(f);
  109. exit(EXIT_FAILURE);
  110. }
  111. if(XMEMCMP(should_buffer, is_buffer, w) == 0) {
  112. printf("%s: OK\n", space);
  113. break;
  114. }
  115. }
  116. } /* for */
  117. if (hash_descriptor[x].name == NULL) {
  118. if(tries > 0) {
  119. printf("%s: FAILED\n", space);
  120. failed++;
  121. }
  122. else {
  123. invalid++;
  124. }
  125. }
  126. } /* while */
  127. fclose(f);
  128. if(invalid) {
  129. fprintf(stderr, "%s: WARNING: %d %s is improperly formatted\n", hashsum, invalid, invalid > 1?"lines":"line");
  130. }
  131. if(failed) {
  132. fprintf(stderr, "%s: WARNING: %d computed %s did NOT match\n", hashsum, failed, failed > 1?"checksums":"checksum");
  133. }
  134. argn++;
  135. }
  136. exit(EXIT_SUCCESS);
  137. }
  138. int main(int argc, char **argv)
  139. {
  140. int idx, check, z, err, argn;
  141. unsigned long w, x;
  142. unsigned char hash_buffer[MAXBLOCKSIZE];
  143. hashsum = strdup(basename(argv[0]));
  144. /* You need to register algorithms before using them */
  145. register_algs();
  146. if (argc > 1 && (strcmp("-h", argv[1]) == 0 || strcmp("--help", argv[1]) == 0)) {
  147. die(EXIT_SUCCESS);
  148. }
  149. if (argc < 3) {
  150. die(EXIT_FAILURE);
  151. }
  152. argn = 1;
  153. check = 0;
  154. idx = -2;
  155. while(argn < argc){
  156. if(strcmp("-a", argv[argn]) == 0) {
  157. argn++;
  158. if(argn < argc) {
  159. idx = find_hash(argv[argn]);
  160. if (idx == -1) {
  161. struct {
  162. const char* is;
  163. const char* should;
  164. } shasum_compat[] =
  165. {
  166. #ifdef LTC_SHA1
  167. { "1", sha1_desc.name },
  168. #endif
  169. #ifdef LTC_SHA224
  170. { "224", sha224_desc.name },
  171. #endif
  172. #ifdef LTC_SHA256
  173. { "256", sha256_desc.name },
  174. #endif
  175. #ifdef LTC_SHA384
  176. { "384", sha384_desc.name },
  177. #endif
  178. #ifdef LTC_SHA512
  179. { "512", sha512_desc.name },
  180. #endif
  181. #ifdef LTC_SHA512_224
  182. { "512224", sha512_224_desc.name },
  183. #endif
  184. #ifdef LTC_SHA512_256
  185. { "512256", sha512_256_desc.name },
  186. #endif
  187. { NULL, NULL }
  188. };
  189. for (x = 0; shasum_compat[x].is != NULL; ++x) {
  190. if(XSTRCMP(shasum_compat[x].is, argv[argn]) == 0) {
  191. idx = find_hash(shasum_compat[x].should);
  192. break;
  193. }
  194. }
  195. }
  196. if (idx == -1) {
  197. fprintf(stderr, "%s: Unrecognized algorithm\n", hashsum);
  198. die(EXIT_FAILURE);
  199. }
  200. argn++;
  201. continue;
  202. }
  203. else {
  204. die(EXIT_FAILURE);
  205. }
  206. }
  207. if(strcmp("-c", argv[argn]) == 0) {
  208. check = 1;
  209. argn++;
  210. continue;
  211. }
  212. break;
  213. }
  214. if (check == 1) {
  215. check_file(argn, argc, argv);
  216. }
  217. if (argc == argn) {
  218. w = sizeof(hash_buffer);
  219. if ((err = hash_filehandle(idx, stdin, hash_buffer, &w)) != CRYPT_OK) {
  220. fprintf(stderr, "%s: File hash error: %s\n", hashsum, error_to_string(err));
  221. return EXIT_FAILURE;
  222. } else {
  223. for (x = 0; x < w; x++) {
  224. printf("%02x",hash_buffer[x]);
  225. }
  226. printf(" *-\n");
  227. }
  228. } else {
  229. for (z = 3; z < argc; z++) {
  230. w = sizeof(hash_buffer);
  231. if ((err = hash_file(idx,argv[z],hash_buffer,&w)) != CRYPT_OK) {
  232. fprintf(stderr, "%s: File hash error: %s\n", hashsum, error_to_string(err));
  233. return EXIT_FAILURE;
  234. } else {
  235. printf_hex(hash_buffer, w);
  236. printf(" *%s\n", argv[z]);
  237. }
  238. }
  239. }
  240. return EXIT_SUCCESS;
  241. }
  242. /* $Source$ */
  243. /* $Revision$ */
  244. /* $Date$ */