aboutsummaryrefslogtreecommitdiff
path: root/src/util/crypto_hash.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-03-04 13:51:40 +0000
committerChristian Grothoff <christian@grothoff.org>2012-03-04 13:51:40 +0000
commit6a9425ddc6fa5de32bb97f05b46ab47c01106f80 (patch)
tree79211ae367b020cc79b103dab23b5e9d7c99688c /src/util/crypto_hash.c
parent5c130e7d8357711b3646a39813670885c0891633 (diff)
downloadgnunet-6a9425ddc6fa5de32bb97f05b46ab47c01106f80.tar.gz
gnunet-6a9425ddc6fa5de32bb97f05b46ab47c01106f80.zip
LRN: adding generic functions for conversion of binary data to ascii and back: GNUNET_CRYPTO_string_to_data and GNUNET_CRYPTO_data_to_string
Diffstat (limited to 'src/util/crypto_hash.c')
-rw-r--r--src/util/crypto_hash.c119
1 files changed, 118 insertions, 1 deletions
diff --git a/src/util/crypto_hash.c b/src/util/crypto_hash.c
index 63d965406..dce449ff0 100644
--- a/src/util/crypto_hash.c
+++ b/src/util/crypto_hash.c
@@ -241,7 +241,6 @@ GNUNET_CRYPTO_hash_file_cancel (struct GNUNET_CRYPTO_FileHashContext *fhc)
241} 241}
242 242
243 243
244
245/* ***************** binary-ASCII encoding *************** */ 244/* ***************** binary-ASCII encoding *************** */
246 245
247/** 246/**
@@ -262,6 +261,124 @@ getValue__ (unsigned char a)
262 261
263 262
264/** 263/**
264 * Convert binary data to ASCII encoding. The ASCII encoding is rather
265 * GNUnet specific. It was chosen such that it only uses characters
266 * in [0-9A-V], can be produced without complex arithmetics and uses a
267 * small number of characters. The GNUnet encoding uses 103 characters.
268 * Does not append 0-terminator, but returns a pointer to the place where
269 * it should be placed, if needed.
270 *
271 * @param data data to encode
272 * @param size size of data (in bytes)
273 * @param out buffer to fill
274 * @param out_size size of the buffer. Must be large enough to hold
275 * ((size*8) + (((size*8) % 5) > 0 ? 5 - ((size*8) % 5) : 0)) / 5 bytes
276 * @return pointer to the next byte in 'out' or NULL on error.
277 */
278char *
279GNUNET_CRYPTO_data_to_string (unsigned char *data, size_t size, char *out, size_t out_size)
280{
281 /**
282 * 32 characters for encoding (GNUNET_CRYPTO_hash => 32 characters)
283 */
284 static char *encTable__ = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
285 unsigned int wpos;
286 unsigned int rpos;
287 unsigned int bits;
288 unsigned int vbit;
289
290 GNUNET_assert (data != NULL);
291 GNUNET_assert (out != NULL);
292 GNUNET_assert (out_size >= (((size*8) + ((size*8) % 5)) % 5));
293 vbit = 0;
294 wpos = 0;
295 rpos = 0;
296 bits = 0;
297 while ((rpos < size) || (vbit > 0))
298 {
299 if ((rpos < size) && (vbit < 5))
300 {
301 bits = (bits << 8) | data[rpos++]; /* eat 8 more bits */
302 vbit += 8;
303 }
304 if (vbit < 5)
305 {
306 bits <<= (5 - vbit); /* zero-padding */
307 GNUNET_assert (vbit == ((size * 8) % 5));
308 vbit = 5;
309 }
310 if (wpos >= out_size)
311 return NULL;
312 out[wpos++] = encTable__[(bits >> (vbit - 5)) & 31];
313 vbit -= 5;
314 }
315 if (wpos != out_size)
316 return NULL;
317 GNUNET_assert (vbit == 0);
318 return &out[wpos];
319}
320
321
322/**
323 * Convert ASCII encoding back to data
324 * out_size must match exactly the size of the data before it was encoded.
325 *
326 * @param enc the encoding
327 * @param enclen number of characters in 'enc' (without 0-terminator, which can be missing)
328 * @param out location where to store the decoded data
329 * @param out_size sizeof the output buffer
330 * @return GNUNET_OK on success, GNUNET_SYSERR if result has the wrong encoding
331 */
332int
333GNUNET_CRYPTO_string_to_data (const char *enc, size_t enclen,
334 unsigned char *out, size_t out_size)
335{
336 unsigned int rpos;
337 unsigned int wpos;
338 unsigned int bits;
339 unsigned int vbit;
340 int ret;
341 int shift;
342 int encoded_len = out_size * 8;
343 if (encoded_len % 5 > 0)
344 {
345 vbit = encoded_len % 5; /* padding! */
346 shift = 5 - vbit;
347 }
348 else
349 {
350 vbit = 0;
351 shift = 0;
352 }
353 if ((encoded_len + shift) / 5 != enclen)
354 return GNUNET_SYSERR;
355
356 wpos = out_size;
357 rpos = enclen;
358 bits = (ret = getValue__ (enc[--rpos])) >> (5 - encoded_len % 5);
359 if (-1 == ret)
360 return GNUNET_SYSERR;
361 while (wpos > 0)
362 {
363 GNUNET_assert (rpos > 0);
364 bits = ((ret = getValue__ (enc[--rpos])) << vbit) | bits;
365 if (-1 == ret)
366 return GNUNET_SYSERR;
367 vbit += 5;
368 if (vbit >= 8)
369 {
370 out[--wpos] = (unsigned char) bits;
371 bits >>= 8;
372 vbit -= 8;
373 }
374 }
375 GNUNET_assert (rpos == 0);
376 GNUNET_assert (vbit == 0);
377 return GNUNET_OK;
378}
379
380
381/**
265 * Convert GNUNET_CRYPTO_hash to ASCII encoding. The ASCII encoding is rather 382 * Convert GNUNET_CRYPTO_hash to ASCII encoding. The ASCII encoding is rather
266 * GNUnet specific. It was chosen such that it only uses characters 383 * GNUnet specific. It was chosen such that it only uses characters
267 * in [0-9A-V], can be produced without complex arithmetics and uses a 384 * in [0-9A-V], can be produced without complex arithmetics and uses a