Mercurial > hg > index.fcgi > gift-gnutella > gift-gnutella-0.0.11-1pba
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