aboutsummaryrefslogtreecommitdiff
path: root/src/util/crypto_hash.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-03-19 10:17:48 +0000
committerChristian Grothoff <christian@grothoff.org>2012-03-19 10:17:48 +0000
commitd79b3436609eb619247a8a682acf1fdd5e4d93fa (patch)
treeb53fe7e634183cb8673e2016c678c431c7504787 /src/util/crypto_hash.c
parent595ba59c3158e65100f4f832cf3bdf15d7e2a72e (diff)
downloadgnunet-d79b3436609eb619247a8a682acf1fdd5e4d93fa.tar.gz
gnunet-d79b3436609eb619247a8a682acf1fdd5e4d93fa.zip
adding API for short (256-bit) hash codes
Diffstat (limited to 'src/util/crypto_hash.c')
-rw-r--r--src/util/crypto_hash.c202
1 files changed, 114 insertions, 88 deletions
diff --git a/src/util/crypto_hash.c b/src/util/crypto_hash.c
index f89639045..aaf5175d7 100644
--- a/src/util/crypto_hash.c
+++ b/src/util/crypto_hash.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2001, 2002, 2003, 2004, 2005, 2006, 2009 Christian Grothoff (and other contributing authors) 3 (C) 2001, 2002, 2003, 2004, 2005, 2006, 2009, 2012 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -34,6 +34,7 @@
34#include "gnunet_common.h" 34#include "gnunet_common.h"
35#include "gnunet_crypto_lib.h" 35#include "gnunet_crypto_lib.h"
36#include "gnunet_disk_lib.h" 36#include "gnunet_disk_lib.h"
37#include "gnunet_strings_lib.h"
37#include <gcrypt.h> 38#include <gcrypt.h>
38 39
39#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) 40#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
@@ -55,6 +56,21 @@ GNUNET_CRYPTO_hash (const void *block, size_t size, GNUNET_HashCode * ret)
55 56
56 57
57/** 58/**
59 * Compute short (256-bit) hash of a given block.
60 *
61 * @param block the data to GNUNET_CRYPTO_hash, length is given as a second argument
62 * @param size the length of the data to GNUNET_CRYPTO_hash
63 * @param ret pointer to where to write the hashcode
64 */
65void
66GNUNET_CRYPTO_short_hash (const void *block, size_t size,
67 struct GNUNET_CRYPTO_ShortHashCode * ret)
68{
69 gcry_md_hash_buffer (GCRY_MD_SHA256, ret, block, size);
70}
71
72
73/**
58 * Context used when hashing a file. 74 * Context used when hashing a file.
59 */ 75 */
60struct GNUNET_CRYPTO_FileHashContext 76struct GNUNET_CRYPTO_FileHashContext
@@ -243,24 +259,6 @@ GNUNET_CRYPTO_hash_file_cancel (struct GNUNET_CRYPTO_FileHashContext *fhc)
243 259
244/* ***************** binary-ASCII encoding *************** */ 260/* ***************** binary-ASCII encoding *************** */
245 261
246/* FIXME: should use GNUNET_STRINGS_data_to_string and strings_to_data below!!! */
247
248/**
249 * Get the numeric value corresponding to a character.
250 *
251 * @param a a character
252 * @return corresponding numeric value
253 */
254static unsigned int
255getValue__ (unsigned char a)
256{
257 if ((a >= '0') && (a <= '9'))
258 return a - '0';
259 if ((a >= 'A') && (a <= 'V'))
260 return (a - 'A' + 10);
261 return -1;
262}
263
264 262
265/** 263/**
266 * Convert GNUNET_CRYPTO_hash to ASCII encoding. The ASCII encoding is rather 264 * Convert GNUNET_CRYPTO_hash to ASCII encoding. The ASCII encoding is rather
@@ -277,88 +275,32 @@ void
277GNUNET_CRYPTO_hash_to_enc (const GNUNET_HashCode * block, 275GNUNET_CRYPTO_hash_to_enc (const GNUNET_HashCode * block,
278 struct GNUNET_CRYPTO_HashAsciiEncoded *result) 276 struct GNUNET_CRYPTO_HashAsciiEncoded *result)
279{ 277{
280 /** 278 char *np;
281 * 32 characters for encoding (GNUNET_CRYPTO_hash => 32 characters) 279
282 */ 280 np = GNUNET_STRINGS_data_to_string ((const unsigned char *) block,
283 static char *encTable__ = "0123456789ABCDEFGHIJKLMNOPQRSTUV"; 281 sizeof (struct GNUNET_HashCode),
284 unsigned int wpos; 282 (char*) result,
285 unsigned int rpos; 283 sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1);
286 unsigned int bits; 284 GNUNET_assert (NULL != np);
287 unsigned int vbit; 285 *np = '\0';
288
289 GNUNET_assert (block != NULL);
290 GNUNET_assert (result != NULL);
291 vbit = 0;
292 wpos = 0;
293 rpos = 0;
294 bits = 0;
295 while ((rpos < sizeof (GNUNET_HashCode)) || (vbit > 0))
296 {
297 if ((rpos < sizeof (GNUNET_HashCode)) && (vbit < 5))
298 {
299 bits = (bits << 8) | ((unsigned char *) block)[rpos++]; /* eat 8 more bits */
300 vbit += 8;
301 }
302 if (vbit < 5)
303 {
304 bits <<= (5 - vbit); /* zero-padding */
305 GNUNET_assert (vbit == 2); /* padding by 3: 512+3 mod 5 == 0 */
306 vbit = 5;
307 }
308 GNUNET_assert (wpos < sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1);
309 result->encoding[wpos++] = encTable__[(bits >> (vbit - 5)) & 31];
310 vbit -= 5;
311 }
312 GNUNET_assert (wpos == sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1);
313 GNUNET_assert (vbit == 0);
314 result->encoding[wpos] = '\0';
315} 286}
316 287
317 288
318/** 289/**
319 * Convert ASCII encoding back to GNUNET_CRYPTO_hash 290 * Convert ASCII encoding back to hash code.
320 * 291 *
321 * @param enc the encoding 292 * @param enc the encoding
322 * @param enclen number of characters in 'enc' (without 0-terminator, which can be missing) 293 * @param enclen number of characters in 'enc' (without 0-terminator, which can be missing)
323 * @param result where to store the GNUNET_CRYPTO_hash code 294 * @param result where to store the hash code
324 * @return GNUNET_OK on success, GNUNET_SYSERR if result has the wrong encoding 295 * @return GNUNET_OK on success, GNUNET_SYSERR if result has the wrong encoding
325 */ 296 */
326int 297int
327GNUNET_CRYPTO_hash_from_string2 (const char *enc, size_t enclen, 298GNUNET_CRYPTO_hash_from_string2 (const char *enc, size_t enclen,
328 GNUNET_HashCode * result) 299 GNUNET_HashCode * result)
329{ 300{
330 unsigned int rpos; 301 return GNUNET_STRINGS_string_to_data (enc, enclen,
331 unsigned int wpos; 302 (unsigned char*) result,
332 unsigned int bits; 303 sizeof (struct GNUNET_HashCode));
333 unsigned int vbit;
334 int ret;
335
336 if (enclen != sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1)
337 return GNUNET_SYSERR;
338
339 vbit = 2; /* padding! */
340 wpos = sizeof (GNUNET_HashCode);
341 rpos = sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1;
342 bits = (ret = getValue__ (enc[--rpos])) >> 3;
343 if (-1 == ret)
344 return GNUNET_SYSERR;
345 while (wpos > 0)
346 {
347 GNUNET_assert (rpos > 0);
348 bits = ((ret = getValue__ (enc[--rpos])) << vbit) | bits;
349 if (-1 == ret)
350 return GNUNET_SYSERR;
351 vbit += 5;
352 if (vbit >= 8)
353 {
354 ((unsigned char *) result)[--wpos] = (unsigned char) bits;
355 bits >>= 8;
356 vbit -= 8;
357 }
358 }
359 GNUNET_assert (rpos == 0);
360 GNUNET_assert (vbit == 0);
361 return GNUNET_OK;
362} 304}
363 305
364 306
@@ -645,4 +587,88 @@ GNUNET_CRYPTO_hmac (const struct GNUNET_CRYPTO_AuthKey *key,
645} 587}
646 588
647 589
590
591/**
592 * Double short (256-bit) hash to create a long hash.
593 *
594 * @param sh short hash to double
595 * @param dh where to store the (doubled) long hash (not really a hash)
596 */
597void
598GNUNET_CRYPTO_short_hash_double (const struct GNUNET_CRYPTO_ShortHashCode *sh,
599 struct GNUNET_HashCode *dh)
600{
601 char *ptr;
602
603 ptr = (char*) dh;
604 memcpy (ptr, sh, sizeof (struct GNUNET_CRYPTO_ShortHashCode));
605 memcpy (&ptr[sizeof (struct GNUNET_CRYPTO_ShortHashCode)], sh, sizeof (struct GNUNET_CRYPTO_ShortHashCode));
606}
607
608
609/**
610 * Truncate doubled short hash back to a short hash.
611 *
612 * @param lh doubled short hash to reduce again
613 * @param sh where to store the short hash
614 * @return GNUNET_OK on success, GNUNET_SYSERR if this was not a
615 * doubled short hash
616 */
617int
618GNUNET_CRYPTO_short_hash_from_truncation (const struct GNUNET_HashCode *dh,
619 struct GNUNET_CRYPTO_ShortHashCode *sh)
620{
621 const struct GNUNET_CRYPTO_ShortHashCode *s;
622
623 s = (const struct GNUNET_CRYPTO_ShortHashCode *) dh;
624 if (0 != memcmp (&s[0],
625 &s[1],
626 sizeof (struct GNUNET_CRYPTO_ShortHashCode)))
627 return GNUNET_SYSERR;
628 *sh = *s;
629 return GNUNET_OK;
630}
631
632
633/**
634 * Convert ASCII encoding back to a 'struct GNUNET_CRYPTO_ShortHash'
635 *
636 * @param enc the encoding
637 * @param enclen number of characters in 'enc' (without 0-terminator, which can be missing)
638 * @param result where to store the GNUNET_CRYPTO_hash code
639 * @return GNUNET_OK on success, GNUNET_SYSERR if result has the wrong encoding
640 */
641int
642GNUNET_CRYPTO_short_hash_from_string2 (const char *enc, size_t enclen,
643 struct GNUNET_CRYPTO_ShortHashCode * result)
644{
645 return GNUNET_STRINGS_string_to_data (enc, enclen,
646 (unsigned char*) result,
647 sizeof (struct GNUNET_CRYPTO_ShortHashCode));
648}
649
650
651/**
652 * Convert short hash to ASCII encoding.
653 *
654 * @param block the hash code
655 * @param result where to store the encoding (struct GNUNET_CRYPTO_ShortHashAsciiEncoded can be
656 * safely cast to char*, a '\\0' termination is set).
657 */
658void
659GNUNET_CRYPTO_short_hash_to_enc (const struct GNUNET_CRYPTO_ShortHashCode * block,
660 struct GNUNET_CRYPTO_ShortHashAsciiEncoded *result)
661{
662 char *np;
663
664 np = GNUNET_STRINGS_data_to_string ((const unsigned char *) block,
665 sizeof (struct GNUNET_CRYPTO_ShortHashCode),
666 (char*) result,
667 sizeof (struct GNUNET_CRYPTO_ShortHashAsciiEncoded) - 1);
668 GNUNET_assert (NULL != np);
669 *np = '\0';
670}
671
672
673
648/* end of crypto_hash.c */ 674/* end of crypto_hash.c */