3 * General hashing tool. */
5 /* nettle, low-level cryptographics library
7 * Copyright (C) 2011 Niels Möller
9 * The nettle library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or (at your
12 * option) any later version.
14 * The nettle library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 * License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with the nettle library; see the file COPYING.LIB. If not, write to
21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
34 #include "nettle-meta.h"
43 list_algorithms (void)
46 const struct nettle_hash *alg;
47 printf ("%10s digestsize (internal block size), in units of octets\n", "name");
49 for (i = 0; (alg = nettle_hashes[i]); i++)
50 printf ("%10s %d (%d)\n",
51 alg->name, alg->digest_size, alg->block_size);
54 static const struct nettle_hash *
55 find_algorithm (const char *name)
57 const struct nettle_hash *alg;
60 for (i = 0; (alg = nettle_hashes[i]); i++)
61 if (!strcmp(name, alg->name))
67 /* Also in examples/io.c */
69 hash_file(const struct nettle_hash *hash, void *ctx, FILE *f)
74 size_t res = fread(buffer, 1, sizeof(buffer), f);
78 hash->update(ctx, res, buffer);
85 digest_file(const struct nettle_hash *alg,
86 unsigned digest_length, int raw,
91 ctx = xalloc(alg->context_size);
95 if (!hash_file (alg, ctx, f))
101 digest = xalloc(digest_length);
102 alg->digest(ctx, digest_length, digest);
106 fwrite (digest, digest_length, 1, stdout);
111 char *hex = xalloc(BASE16_ENCODE_LENGTH(8) + 1);
112 for (i = 0; i + 8 < digest_length; i += 8)
114 base16_encode_update(hex, 8, digest + i);
115 hex[BASE16_ENCODE_LENGTH(8)] = 0;
118 base16_encode_update(hex, digest_length - i, digest + i);
119 hex[BASE16_ENCODE_LENGTH(digest_length - i)] = 0;
120 printf("%s %s\n", hex, alg->name);
129 /* FIXME: Be more compatible with md5sum and sha1sum. Options -c
130 (check), -b (binary), -t (text), and output format with hex hash
131 sum, optional star (meaning binary mode), and file name. */
133 main (int argc, char **argv)
135 const char *alg_name = NULL;
136 const struct nettle_hash *alg;
141 enum { OPT_HELP = 0x300, OPT_RAW, OPT_LIST };
142 static const struct option options[] =
144 /* Name, args, flag, val */
145 { "help", no_argument, NULL, OPT_HELP },
146 { "version", no_argument, NULL, 'V' },
147 { "algorithm", required_argument, NULL, 'a' },
148 { "length", required_argument, NULL, 'l' },
149 { "list", no_argument, NULL, OPT_LIST },
150 { "raw", no_argument, NULL, OPT_RAW },
155 while ( (c = getopt_long(argc, argv, "Va:l:", options, NULL)) != -1)
161 printf("nettle-hash -a ALGORITHM [OPTIONS] [FILE ...]\n"
163 " --help Show this help.\n"
164 " -V, --version Show version information.\n"
165 " --list List supported hash algorithms.\n"
166 " -a, --algorithm=ALG Hash algorithm to use.\n"
167 " -l, --length=LENGTH Desired digest length (octets)\n"
168 " --raw Raw binary output.\n");
171 printf("nettle-hash (" PACKAGE_STRING ")\n");
181 die ("Invalid length argument: `%s'\n", optarg);
194 die("Algorithm argument (-a option) is mandatory.\n"
195 "See nettle-hash --help for further information.\n");
197 alg = find_algorithm (alg_name);
199 die("Hash algorithm `%s' not supported or .\n"
200 "Use nettle-hash --list to list available algorithms.\n",
204 length = alg->digest_size;
205 else if (length > alg->digest_size)
206 die ("Length argument %d too large for selected algorithm.\n",
213 digest_file (alg, length, raw, stdin);
217 for (i = 0; i < argc; i++)
219 FILE *f = fopen (argv[i], "rb");
221 die ("Cannot open `%s': %s\n", argv[i], STRERROR(errno));
222 printf("%s: ", argv[i]);
223 if (!digest_file (alg, length, raw, f))
224 die("Reading `%s' failed: %s\n", argv[i], STRERROR(errno));
228 if (fflush(stdout) != 0 )
229 die("Write failed: %s\n", STRERROR(errno));