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