Commit 23f70ce9 authored by Niels Möller's avatar Niels Möller

New program nettle-pbkdf2.

parent 8d1d5d6d
2013-06-25 Niels Möller <nisse@lysator.liu.se>
* tools/nettle-pbkdf2.c: New command line tool.
* tools/Makefile.in (TARGETS): Added nettle-pbkdf2.
(nettle-pbkdf2$(EXEEXT)): New target.
* testsuite/nettle-pbkdf2-test: New test case.
* testsuite/Makefile.in (TS_SH): Added nettle-pbkdf2-test.
* tools/nettle-hash.c (digest_file): Use stack allocation for the
small hex output buffer.
......
......@@ -47,7 +47,7 @@ TS_HOGWEED = $(TS_HOGWEED_SOURCES:.c=$(EXEEXT))
TS_C = $(TS_NETTLE) @IF_HOGWEED@ $(TS_HOGWEED)
TS_CXX = @IF_CXX@ $(CXX_SOURCES:.cxx=$(EXEEXT))
TARGETS = $(TS_C) $(TS_CXX)
TS_SH = sexp-conv-test pkcs1-conv-test symbols-test
TS_SH = sexp-conv-test pkcs1-conv-test nettle-pbkdf2-test symbols-test
TS_ALL = $(TARGETS) $(TS_SH)
EXTRA_SOURCES = sha1-huge-test.c
EXTRA_TARGETS = $(EXTRA_SOURCES:.c=$(EXEEXT))
......
#! /bin/sh
if [ -z "$srcdir" ] ; then
srcdir=`pwd`
fi
test_pbkdf2 () {
password="$1"
salt="$2"
iters="$3"
expected="$4"
length=`expr ${#expected} / 2`
printf "%s" "$password" | $EMULATOR ../tools/nettle-pbkdf2 \
-i "$iters" -l "$length" "$salt" > test1.out
echo "$expected" > test2.out
if cmp test1.out test2.out ; then
true
else
exit 1;
fi
}
test_pbkdf2 passwd salt 1 "55ac046e56e3089f ec1691c22544b605"
test_pbkdf2 Password NaCl 80000 "4ddcd8f60b98be21 830cee5ef22701f9"
exit 0
......@@ -18,7 +18,8 @@ PRE_CPPFLAGS = -I.. -I$(top_srcdir)
PRE_LDFLAGS = -L..
HOGWEED_TARGETS = pkcs1-conv$(EXEEXT)
TARGETS = sexp-conv$(EXEEXT) nettle-hash$(EXEEXT) nettle-lfib-stream$(EXEEXT) \
TARGETS = sexp-conv$(EXEEXT) nettle-hash$(EXEEXT) nettle-pbkdf2$(EXEEXT) \
nettle-lfib-stream$(EXEEXT) \
@IF_HOGWEED@ $(HOGWEED_TARGETS)
all: $(TARGETS)
......@@ -28,6 +29,7 @@ getopt_OBJS = ../getopt.$(OBJEXT) ../getopt1.$(OBJEXT)
sexp_conv_SOURCES = sexp-conv.c input.c output.c parse.c misc.c
pkcs1_conv_SOURCES = pkcs1-conv.c misc.c
nettle_hash_SOURCES = nettle-hash.c misc.c
nettle_pbkdf2_SOURCES = nettle-pbkdf2.c misc.c
SOURCES = $(sexp_conv_SOURCES) nettle-hash.c nettle-lfib-stream.c pkcs1-conv.c
......@@ -47,7 +49,11 @@ pkcs1-conv$(EXEEXT): $(pkcs1_conv_OBJS) ../libnettle.a ../libhogweed.a
# FIXME: Avoid linking with gmp
nettle_hash_OBJS = $(nettle_hash_SOURCES:.c=.$(OBJEXT)) $(getopt_OBJS)
nettle-hash$(EXEEXT): $(nettle_hash_OBJS) ../libnettle.a
$(LINK) $(nettle_hash_OBJS) -lnettle $(LIBS) -o $@
$(LINK) $(nettle_hash_OBJS) -lnettle -o $@
nettle_pbkdf2_OBJS = $(nettle_pbkdf2_SOURCES:.c=.$(OBJEXT)) $(getopt_OBJS)
nettle-pbkdf2$(EXEEXT): $(nettle_pbkdf2_OBJS) ../libnettle.a
$(LINK) $(nettle_pbkdf2_OBJS) -lnettle -o $@
.c.$(OBJEXT):
......
/* nettle-pbkdf2.c
*
* Command-line tool for pbkdf2 hashing. */
/* nettle, low-level cryptographics library
*
* Copyright (C) 2013 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., 51 Franklin Street, Fifth Floor, Boston,
* MA 02111-1301, USA.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pbkdf2.h"
#include "base16.h"
#include "getopt.h"
#include "misc.h"
#define DEFAULT_ITERATIONS 10000
#define DEFAULT_LENGTH 16
static void
usage (FILE *f)
{
fprintf(f, "nettle-pbkdf2 [OPTIONS] SALT\n"
"Options:\n"
" --help Show this help.\n"
" -V, --version Show version information.\n"
" -i, --iterations=COUNT Desired iteration count (default %d).\n"
" -l, --length=LENGTH Desired output length (octets, default %d)\n"
" --raw Raw binary output.\n"
" --hex-salt Use hex encoding for the salt.\n",
DEFAULT_ITERATIONS, DEFAULT_LENGTH);
}
#define MAX_PASSWORD 1024
int
main (int argc, char **argv)
{
unsigned iterations = DEFAULT_ITERATIONS;
unsigned output_length = DEFAULT_LENGTH;
char password[MAX_PASSWORD];
size_t password_length;
char *output;
size_t salt_length;
char *salt;
int raw = 0;
int hex_salt = 0;
int c;
enum { OPT_HELP = 0x300, OPT_RAW, OPT_HEX_SALT };
static const struct option options[] =
{
/* Name, args, flag, val */
{ "help", no_argument, NULL, OPT_HELP },
{ "version", no_argument, NULL, 'V' },
{ "length", required_argument, NULL, 'l' },
{ "iterations", required_argument, NULL, 'i' },
{ "raw", no_argument, NULL, OPT_RAW },
{ "hex-salt", no_argument, NULL, OPT_HEX_SALT },
{ NULL, 0, NULL, 0 }
};
while ( (c = getopt_long(argc, argv, "Vl:i:", options, NULL)) != -1)
switch (c)
{
default:
abort();
case OPT_HELP:
usage (stdout);
return EXIT_SUCCESS;
case 'V':
printf("nettle-pbkdf2 (" PACKAGE_STRING ")\n");
return EXIT_SUCCESS;
case 'l':
{
int arg;
arg = atoi (optarg);
if (arg <= 0)
die ("Invalid length argument: `%s'\n", optarg);
output_length = arg;
}
break;
case 'i':
{
int arg;
arg = atoi (optarg);
if (arg <= 0)
die ("Invalid iteration count: `%s'\n", optarg);
iterations = arg;
}
break;
case OPT_RAW:
raw = 1;
break;
case OPT_HEX_SALT:
hex_salt = 1;
break;
}
argv += optind;
argc -= optind;
if (argc != 1)
{
usage (stderr);
return EXIT_FAILURE;
}
salt = strdup (argv[0]);
salt_length = strlen(salt);
if (hex_salt)
{
struct base16_decode_ctx base16;
base16_decode_init (&base16);
if (!base16_decode_update (&base16,
&salt_length,
salt, salt_length, salt)
|| !base16_decode_final (&base16))
die ("Invalid salt (expecting hex encoding).\n");
}
password_length = fread (password, 1, sizeof(password), stdin);
if (password_length == sizeof(password))
die ("Password input to long. Current limit is %d characters.\n",
(int) sizeof(password) - 1);
if (ferror (stdin))
die ("Reading password input failed: %s.\n", strerror (errno));
output = xalloc (output_length);
pbkdf2_hmac_sha256 (password_length, password, iterations, salt_length, salt,
output_length, output);
free (salt);
if (raw)
fwrite (output, output_length, 1, stdout);
else
{
unsigned i;
char hex[BASE16_ENCODE_LENGTH(8) + 1];
for (i = 0; i + 8 < output_length; i += 8)
{
base16_encode_update(hex, 8, output + i);
hex[BASE16_ENCODE_LENGTH(8)] = 0;
printf("%s%c", hex, i % 64 == 56 ? '\n' : ' ');
}
base16_encode_update(hex, output_length - i, output + i);
hex[BASE16_ENCODE_LENGTH(output_length - i)] = 0;
printf("%s\n", hex);
}
if (fflush(stdout) != 0 )
die("Write failed: %s\n", STRERROR(errno));
return EXIT_SUCCESS;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment