diff src/encoding/base32.c @ 0:d39e1d0d75b6

initial add
author paulo@hit-nxdomain.opendns.com
date Sat, 20 Feb 2010 21:18:28 -0800
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/encoding/base32.c	Sat Feb 20 21:18:28 2010 -0800
     1.3 @@ -0,0 +1,167 @@
     1.4 +/*
     1.5 + * $Id: base32.c,v 1.2 2004/03/27 00:34:25 mkern Exp $
     1.6 + *
     1.7 + * Copyright (C) 2003-2004 giFT project (gift.sourceforge.net)
     1.8 + *
     1.9 + * This program is free software; you can redistribute it and/or modify it
    1.10 + * under the terms of the GNU General Public License as published by the
    1.11 + * Free Software Foundation; either version 2, or (at your option) any
    1.12 + * later version.
    1.13 + *
    1.14 + * This program is distributed in the hope that it will be useful, but
    1.15 + * WITHOUT ANY WARRANTY; without even the implied warranty of
    1.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    1.17 + * General Public License for more details.
    1.18 + */
    1.19 +
    1.20 +#include "gt_gnutella.h"
    1.21 +#include "encoding/base32.h"
    1.22 +
    1.23 +/*****************************************************************************/
    1.24 +
    1.25 +/* base32 alphabet */
    1.26 +static const char *ALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
    1.27 +
    1.28 +static uint8_t base32_bits[256] = { 0 };
    1.29 +
    1.30 +/*****************************************************************************/
    1.31 +
    1.32 +/* convert 5 bytes to 8 characters in base 32 */
    1.33 +static void bin_to_base32 (const uint8_t *in, char *out)
    1.34 +{
    1.35 +	out[0] = ALPHA[(in[0]       ) >> 3];
    1.36 +	out[1] = ALPHA[(in[0] & 0x07) << 2 | (in[1] & 0xc0) >> 6];
    1.37 +	out[2] = ALPHA[(in[1] & 0x3e) >> 1];
    1.38 +	out[3] = ALPHA[(in[1] & 0x01) << 4 | (in[2] & 0xf0) >> 4];
    1.39 +	out[4] = ALPHA[(in[2] & 0x0f) << 1 | (in[3] & 0x80) >> 7];
    1.40 +	out[5] = ALPHA[(in[3] & 0x7c) >> 2];
    1.41 +	out[6] = ALPHA[(in[3] & 0x03) << 3 | (in[4] & 0xe0) >> 5];
    1.42 +	out[7] = ALPHA[(in[4] & 0x1f)];
    1.43 +}
    1.44 +
    1.45 +/* convert 8 characters in base 32 to 5 bytes */
    1.46 +static void base32_to_bin (const char *base32, uint8_t *out)
    1.47 +{
    1.48 +	const unsigned char *in   = base32;
    1.49 +	const uint8_t       *bits = base32_bits;
    1.50 +
    1.51 +	out[0] = ((bits[in[0]]       ) << 3) | (bits[in[1]] & 0x1C) >> 2;
    1.52 +	out[1] = ((bits[in[1]] & 0x03) << 6) | (bits[in[2]]       ) << 1
    1.53 +	                                     | (bits[in[3]] & 0x10) >> 4;
    1.54 +	out[2] = ((bits[in[3]] & 0x0F) << 4) | (bits[in[4]] & 0x1E) >> 1;
    1.55 +	out[3] = ((bits[in[4]] & 0x01) << 7) | (bits[in[5]]       ) << 2
    1.56 +	                                     | (bits[in[6]] & 0x18) >> 3;
    1.57 +	out[4] = ((bits[in[6]] & 0x07) << 5) | (bits[in[7]]);
    1.58 +}
    1.59 +
    1.60 +static void init_base32_bits (void)
    1.61 +{
    1.62 +	int   i;
    1.63 +	char *pos;
    1.64 +
    1.65 +	/* set the each char's corresponding bit value in a lookup table */
    1.66 +	for (i = 0; i < sizeof(base32_bits); i++)
    1.67 +	{
    1.68 +		if ((pos = strchr (ALPHA, toupper (i))))
    1.69 +			base32_bits[i] = pos - ALPHA;
    1.70 +	}
    1.71 +}
    1.72 +
    1.73 +/*****************************************************************************/
    1.74 +
    1.75 +BOOL gt_base32_valid (const char *base32, size_t len)
    1.76 +{
    1.77 +	while (len > 0)
    1.78 +	{
    1.79 +		unsigned char c = toupper (*base32);
    1.80 +
    1.81 +		if (!((c >= 'A' && c <= 'Z') || (c >= '2' && c <= '7')))
    1.82 +			break;
    1.83 +
    1.84 +		base32++;
    1.85 +		len--;
    1.86 +	}
    1.87 +
    1.88 +	return (len > 0 ? FALSE : TRUE);
    1.89 +}
    1.90 +
    1.91 +void gt_base32_encode (const uint8_t *in, size_t in_len,
    1.92 +                       char *out, size_t out_len)
    1.93 +{
    1.94 +	assert (in_len == 20);
    1.95 +	assert (out_len == 32);
    1.96 +
    1.97 +	bin_to_base32 (in,      out);
    1.98 +	bin_to_base32 (in + 5,  out + 8);
    1.99 +	bin_to_base32 (in + 10, out + 16);
   1.100 +	bin_to_base32 (in + 15, out + 24);
   1.101 +}
   1.102 +
   1.103 +void gt_base32_decode (const char *in, size_t in_len,
   1.104 +                       uint8_t *out, size_t out_len)
   1.105 +{
   1.106 +	/* initialize lookup table */
   1.107 +	if (base32_bits['b'] == 0)
   1.108 +		init_base32_bits ();
   1.109 +
   1.110 +	assert (in_len == 32);
   1.111 +	assert (out_len == 20);
   1.112 +
   1.113 +	base32_to_bin (in     , out     );
   1.114 +	base32_to_bin (in +  8, out +  5);
   1.115 +	base32_to_bin (in + 16, out + 10);
   1.116 +	base32_to_bin (in + 24, out + 15);
   1.117 +}
   1.118 +
   1.119 +/*****************************************************************************/
   1.120 +
   1.121 +#if 0
   1.122 +static void test_str (const char *test)
   1.123 +{
   1.124 +	unsigned char bin[20];
   1.125 +	char          hash[33];
   1.126 +
   1.127 +	hash[32] = 0;
   1.128 +
   1.129 +	gt_base32_decode (test, strlen (test), bin, sizeof(bin));
   1.130 +	gt_base32_encode (bin, sizeof(bin), hash, sizeof(hash) - 1);
   1.131 +
   1.132 +	if (!gt_base32_valid (hash, 32))
   1.133 +		abort ();
   1.134 +
   1.135 +	if (strcmp (hash, test) != 0)
   1.136 +	{
   1.137 +		printf ("\ntest=%s(%d)\nhash=%s(%d)\n", test,
   1.138 +		         strlen (test), hash, strlen (hash));
   1.139 +		fflush (stdout);
   1.140 +	}
   1.141 +}
   1.142 +
   1.143 +int main (int argc, char **argv)
   1.144 +{
   1.145 +	int   i, j;
   1.146 +	char  str[33];
   1.147 +	int   len   = strlen (ALPHA);
   1.148 +
   1.149 +	str[sizeof (str) - 1] = 0;
   1.150 +
   1.151 +	test_str (ALPHA);
   1.152 +
   1.153 +	for (i = 1; i <= 100000; i++)
   1.154 +	{
   1.155 +		for (j = 0; j < 32; j++)
   1.156 +			str[j] = ALPHA[rand () % len];
   1.157 +
   1.158 +		if (!gt_base32_valid (str, 32))
   1.159 +			abort ();
   1.160 +
   1.161 +		printf ("%i\r", i);
   1.162 +		fflush (stdout);
   1.163 +		test_str (str);
   1.164 +		usleep (1);
   1.165 +	}
   1.166 +
   1.167 +	printf ("\n");
   1.168 +	return 0;
   1.169 +}
   1.170 +#endif