]> git.ipfire.org Git - thirdparty/nettle.git/commitdiff
* tools/Makefile.in (TARGETS): Added nettle-hash, and related
authorNiels Möller <nisse@lysator.liu.se>
Wed, 23 Mar 2011 12:01:11 +0000 (13:01 +0100)
committerNiels Möller <nisse@lysator.liu.se>
Wed, 23 Mar 2011 12:01:11 +0000 (13:01 +0100)
build rules.
(SOURCES): Added nettle-hash.c.

* tools/nettle-hash.c: New file.

Rev: nettle/tools/Makefile.in:1.5
Rev: nettle/tools/nettle-hash.c:1.1

tools/Makefile.in
tools/nettle-hash.c [new file with mode: 0644]

index 4115b4e1fae148bfda872bdc7a821eefb3ee21c4..5ca73b2073cf1ed9415442ae76418d1a7ad5f322 100644 (file)
@@ -18,7 +18,7 @@ PRE_CPPFLAGS = -I.. -I$(top_srcdir)
 PRE_LDFLAGS = -L..
 
 HOGWEED_TARGETS = pkcs1-conv$(EXEEXT)
-TARGETS = sexp-conv$(EXEEXT) nettle-lfib-stream$(EXEEXT) \
+TARGETS = sexp-conv$(EXEEXT) nettle-hash$(EXEEXT) nettle-lfib-stream$(EXEEXT) \
          @IF_HOGWEED@ $(HOGWEED_TARGETS)
 
 all: $(TARGETS)
@@ -26,8 +26,9 @@ all: $(TARGETS)
 sexp_conv_SOURCES = sexp-conv.c input.c output.c parse.c \
        getopt.c getopt1.c misc.c
 pkcs1_conv_SOURCES = pkcs1-conv.c getopt.c getopt1.c misc.c
+nettle_hash_SOURCES = nettle-hash.c getopt.c getopt1.c misc.c
 
-SOURCES = $(sexp_conv_SOURCES) nettle-lfib-stream.c pkcs1-conv.c
+SOURCES = $(sexp_conv_SOURCES) nettle-hash.c nettle-lfib-stream.c pkcs1-conv.c
 
 DISTFILES = $(SOURCES) Makefile.in getopt.h input.h misc.h output.h parse.h
 
@@ -42,6 +43,12 @@ pkcs1_conv_OBJS = $(pkcs1_conv_SOURCES:.c=.$(OBJEXT))
 pkcs1-conv$(EXEEXT): $(pkcs1_conv_OBJS) ../libnettle.a ../libhogweed.a
        $(LINK) $(pkcs1_conv_OBJS) -lhogweed -lnettle $(LIBS) -o $@
 
+# FIXME: Avoid linking with gmp
+nettle_hash_OBJS = $(nettle_hash_SOURCES:.c=.$(OBJEXT))
+nettle-hash$(EXEEXT): $(nettle_hash_OBJS) ../libnettle.a
+       $(LINK) $(nettle_hash_OBJS) -lnettle $(LIBS) -o $@
+
+
 .c.$(OBJEXT):
        $(COMPILE) -c $< && $(DEP_PROCESS)
 
diff --git a/tools/nettle-hash.c b/tools/nettle-hash.c
new file mode 100644 (file)
index 0000000..2874bb9
--- /dev/null
@@ -0,0 +1,246 @@
+/* nettle-hash.c
+ *
+ * General hashing tool. */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2011 Niels Möller
+ *  
+ * The nettle library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ * 
+ * The nettle library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ * License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the nettle library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "nettle-meta.h"
+#include "base16.h"
+
+#include "getopt.h"
+#include "misc.h"
+
+#define BUFSIZE 16384
+
+static void
+list_algorithms (void)
+{
+  unsigned i;
+  const struct nettle_hash *alg;
+  printf ("%10s digestsize (internal block size), in units of octest\n", "name");
+
+  for (i = 0; (alg = nettle_hashes[i]); i++)
+    printf ("%10s %d (%d)\n",
+           alg->name, alg->digest_size, alg->block_size);
+};
+
+static const struct nettle_hash *
+find_algorithm (const char *name)
+{
+  size_t length = strlen (name);
+  const struct nettle_hash *alg;
+  const struct nettle_hash *found = NULL;
+  unsigned i;
+  
+  for (i = 0; (alg = nettle_hashes[i]); i++)
+    {
+      if (!strncmp(name, alg->name, length))
+       {
+         /* Luckily, no valid algorithm name is a prefix of any
+            other, so we don't need to handle exact matches
+            specially. */
+            
+         if (found)
+           die("Hash algorithm `%s' is ambiguous (%s or %s or ...?).\n"
+               "Use nettle-hash --list to list all available algorithms.\n",
+               name, alg->name, found->name);
+         found = alg;
+       }
+    }
+  if (!found)
+    die("Hash algorithm `%s' is not supported.\n"
+       "Use nettle-hash --list to list all available algorithms.\n",
+       name);
+  return found;
+}
+
+/* Also in examples/io.c */
+static int
+hash_file(const struct nettle_hash *hash, void *ctx, FILE *f)
+{
+  for (;;)
+    {
+      char buffer[BUFSIZE];
+      size_t res = fread(buffer, 1, sizeof(buffer), f);
+      if (ferror(f))
+       return 0;
+      
+      hash->update(ctx, res, buffer);
+      if (feof(f))
+       return 1;
+    }
+}
+
+static int
+digest_file(const struct nettle_hash *alg,
+           unsigned digest_length, int raw,
+           FILE *f)
+{
+  void *ctx;
+  uint8_t *digest;
+  ctx = xalloc(alg->context_size);
+
+  alg->init(ctx);
+
+  if (!hash_file (alg, ctx, f))
+    {
+      free (ctx);
+      return 0;
+    }
+
+  digest = xalloc(digest_length);
+  alg->digest(ctx, digest_length, digest);
+  free(ctx);
+
+  if (raw)
+    fwrite (digest, digest_length, 1, stdout);
+
+  else
+    {
+      unsigned i;
+      char *hex = xalloc(BASE16_ENCODE_LENGTH(8) + 1);
+      for (i = 0; i + 8 < digest_length; i += 8)
+       {
+         base16_encode_update(hex, 8, digest + i);
+         hex[BASE16_ENCODE_LENGTH(8)] = 0;
+         printf("%s ", hex);
+       }
+      base16_encode_update(hex, digest_length - i, digest + i);
+      hex[BASE16_ENCODE_LENGTH(digest_length - i)] = 0;
+      printf("%s %s\n", hex, alg->name);
+      free(hex);
+    }
+  
+  free(digest);
+
+  return 1;
+}
+
+int
+main (int argc, char **argv)
+{
+  const char *alg_name = NULL;
+  const struct nettle_hash *alg;
+  unsigned length = 0;
+  int raw = 0;
+  int c;
+
+  enum { OPT_HELP = 0x300, OPT_RAW, OPT_LIST };
+  static const struct option options[] =
+    {
+      /* Name, args, flag, val */
+      { "help", no_argument, NULL, OPT_HELP },
+      { "version", no_argument, NULL, 'V' },
+      { "algorithm", required_argument, NULL, 'a' },
+      { "length", required_argument, NULL, 'l' },
+      { "list", no_argument, NULL, OPT_LIST },
+      { "raw", no_argument, NULL, OPT_RAW },
+
+      { NULL, 0, NULL, 0 }
+    };
+
+  while ( (c = getopt_long(argc, argv, "Va:l:", options, NULL)) != -1)
+    switch (c)
+      {
+      default:
+       abort();
+      case OPT_HELP:
+       printf("nettle-hash -a ALGORITHM [OPTIONS] [FILE ...]\n"
+              "Options:\n"
+              "  --help              Show this help.\n"
+              "  -V, --version       Show version information.\n"
+              "  --list              List supported hash algorithms.\n"
+              "  -a, --algorithm=ALG Hash algorithm to use.\n"
+              "  -l, --length=LENGTH Desired digest length (octets)\n"
+              "  --raw               Raw binary output.\n");
+       return EXIT_SUCCESS;
+      case 'V':
+       printf("nettle-hash (" PACKAGE_STRING ")\n");
+       return EXIT_SUCCESS;
+      case 'a':
+       alg_name = optarg;
+       break;
+      case 'l':
+       {
+         int arg;
+         arg = atoi (optarg);
+         if (arg <= 0)
+           die ("Invalid length argument: `%s'\n", optarg);
+         length = arg;
+       }
+       break;
+      case OPT_RAW:
+       raw = 1;
+       break;
+      case OPT_LIST:
+       list_algorithms();
+       return EXIT_SUCCESS;
+      }
+
+  if (!alg_name)
+    die("Algorithm argument (-a option) is mandatory.\n"
+       "See nettle-hash --help for further information.\n");
+      
+  alg = find_algorithm (alg_name);
+  if (!alg)
+    die("Hash algorithm `%s' not supported or .\n"
+       "Use nettle-hash --list to list available algorithms.\n",
+       alg_name);
+
+  if (length == 0)
+    length = alg->digest_size;
+  else if (length > alg->digest_size)
+    die ("Length argument %d too large for selected algorithm.\n",
+        length);
+    
+  argv += optind;
+  argc -= optind;
+
+  if (argc == 0)
+    digest_file (alg, length, raw, stdin);
+  else
+    {
+      int i;
+      for (i = 0; i < argc; i++)
+       {
+         FILE *f = fopen (argv[i], "rb");
+         if (!f)
+           die ("Cannot open `%s': %s\n", argv[i], STRERROR(errno));
+         printf("%s: ", argv[i]);
+         if (!digest_file (alg, length, raw, f))
+           die("Reading `%s' failed: %s\n", argv[i], STRERROR(errno));
+         fclose(f);
+       }
+    }
+  if (fflush(stdout) != 0 )
+    die("Write failed: %s\n", STRERROR(errno));
+
+  return EXIT_SUCCESS;
+}