view 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 source
1 /*
2 * $Id: base32.c,v 1.2 2004/03/27 00:34:25 mkern Exp $
3 *
4 * Copyright (C) 2003-2004 giFT project (gift.sourceforge.net)
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 */
17 #include "gt_gnutella.h"
18 #include "encoding/base32.h"
20 /*****************************************************************************/
22 /* base32 alphabet */
23 static const char *ALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
25 static uint8_t base32_bits[256] = { 0 };
27 /*****************************************************************************/
29 /* convert 5 bytes to 8 characters in base 32 */
30 static void bin_to_base32 (const uint8_t *in, char *out)
31 {
32 out[0] = ALPHA[(in[0] ) >> 3];
33 out[1] = ALPHA[(in[0] & 0x07) << 2 | (in[1] & 0xc0) >> 6];
34 out[2] = ALPHA[(in[1] & 0x3e) >> 1];
35 out[3] = ALPHA[(in[1] & 0x01) << 4 | (in[2] & 0xf0) >> 4];
36 out[4] = ALPHA[(in[2] & 0x0f) << 1 | (in[3] & 0x80) >> 7];
37 out[5] = ALPHA[(in[3] & 0x7c) >> 2];
38 out[6] = ALPHA[(in[3] & 0x03) << 3 | (in[4] & 0xe0) >> 5];
39 out[7] = ALPHA[(in[4] & 0x1f)];
40 }
42 /* convert 8 characters in base 32 to 5 bytes */
43 static void base32_to_bin (const char *base32, uint8_t *out)
44 {
45 const unsigned char *in = base32;
46 const uint8_t *bits = base32_bits;
48 out[0] = ((bits[in[0]] ) << 3) | (bits[in[1]] & 0x1C) >> 2;
49 out[1] = ((bits[in[1]] & 0x03) << 6) | (bits[in[2]] ) << 1
50 | (bits[in[3]] & 0x10) >> 4;
51 out[2] = ((bits[in[3]] & 0x0F) << 4) | (bits[in[4]] & 0x1E) >> 1;
52 out[3] = ((bits[in[4]] & 0x01) << 7) | (bits[in[5]] ) << 2
53 | (bits[in[6]] & 0x18) >> 3;
54 out[4] = ((bits[in[6]] & 0x07) << 5) | (bits[in[7]]);
55 }
57 static void init_base32_bits (void)
58 {
59 int i;
60 char *pos;
62 /* set the each char's corresponding bit value in a lookup table */
63 for (i = 0; i < sizeof(base32_bits); i++)
64 {
65 if ((pos = strchr (ALPHA, toupper (i))))
66 base32_bits[i] = pos - ALPHA;
67 }
68 }
70 /*****************************************************************************/
72 BOOL gt_base32_valid (const char *base32, size_t len)
73 {
74 while (len > 0)
75 {
76 unsigned char c = toupper (*base32);
78 if (!((c >= 'A' && c <= 'Z') || (c >= '2' && c <= '7')))
79 break;
81 base32++;
82 len--;
83 }
85 return (len > 0 ? FALSE : TRUE);
86 }
88 void gt_base32_encode (const uint8_t *in, size_t in_len,
89 char *out, size_t out_len)
90 {
91 assert (in_len == 20);
92 assert (out_len == 32);
94 bin_to_base32 (in, out);
95 bin_to_base32 (in + 5, out + 8);
96 bin_to_base32 (in + 10, out + 16);
97 bin_to_base32 (in + 15, out + 24);
98 }
100 void gt_base32_decode (const char *in, size_t in_len,
101 uint8_t *out, size_t out_len)
102 {
103 /* initialize lookup table */
104 if (base32_bits['b'] == 0)
105 init_base32_bits ();
107 assert (in_len == 32);
108 assert (out_len == 20);
110 base32_to_bin (in , out );
111 base32_to_bin (in + 8, out + 5);
112 base32_to_bin (in + 16, out + 10);
113 base32_to_bin (in + 24, out + 15);
114 }
116 /*****************************************************************************/
118 #if 0
119 static void test_str (const char *test)
120 {
121 unsigned char bin[20];
122 char hash[33];
124 hash[32] = 0;
126 gt_base32_decode (test, strlen (test), bin, sizeof(bin));
127 gt_base32_encode (bin, sizeof(bin), hash, sizeof(hash) - 1);
129 if (!gt_base32_valid (hash, 32))
130 abort ();
132 if (strcmp (hash, test) != 0)
133 {
134 printf ("\ntest=%s(%d)\nhash=%s(%d)\n", test,
135 strlen (test), hash, strlen (hash));
136 fflush (stdout);
137 }
138 }
140 int main (int argc, char **argv)
141 {
142 int i, j;
143 char str[33];
144 int len = strlen (ALPHA);
146 str[sizeof (str) - 1] = 0;
148 test_str (ALPHA);
150 for (i = 1; i <= 100000; i++)
151 {
152 for (j = 0; j < 32; j++)
153 str[j] = ALPHA[rand () % len];
155 if (!gt_base32_valid (str, 32))
156 abort ();
158 printf ("%i\r", i);
159 fflush (stdout);
160 test_str (str);
161 usleep (1);
162 }
164 printf ("\n");
165 return 0;
166 }
167 #endif