diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-03-19 10:17:48 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-03-19 10:17:48 +0000 |
commit | d79b3436609eb619247a8a682acf1fdd5e4d93fa (patch) | |
tree | b53fe7e634183cb8673e2016c678c431c7504787 /src/util/crypto_hash.c | |
parent | 595ba59c3158e65100f4f832cf3bdf15d7e2a72e (diff) | |
download | gnunet-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.c | 202 |
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 | */ | ||
65 | void | ||
66 | GNUNET_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 | */ |
60 | struct GNUNET_CRYPTO_FileHashContext | 76 | struct 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 | */ | ||
254 | static unsigned int | ||
255 | getValue__ (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 | |||
277 | GNUNET_CRYPTO_hash_to_enc (const GNUNET_HashCode * block, | 275 | GNUNET_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 | */ |
326 | int | 297 | int |
327 | GNUNET_CRYPTO_hash_from_string2 (const char *enc, size_t enclen, | 298 | GNUNET_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 | */ | ||
597 | void | ||
598 | GNUNET_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 | */ | ||
617 | int | ||
618 | GNUNET_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 | */ | ||
641 | int | ||
642 | GNUNET_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 | */ | ||
658 | void | ||
659 | GNUNET_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 */ |