Mercurial > hg > index.fcgi > gift-gnutella > gift-gnutella-0.0.11-1pba
comparison 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 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:d9b130e82637 |
---|---|
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 */ | |
16 | |
17 #include "gt_gnutella.h" | |
18 #include "encoding/base32.h" | |
19 | |
20 /*****************************************************************************/ | |
21 | |
22 /* base32 alphabet */ | |
23 static const char *ALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; | |
24 | |
25 static uint8_t base32_bits[256] = { 0 }; | |
26 | |
27 /*****************************************************************************/ | |
28 | |
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 } | |
41 | |
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; | |
47 | |
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 } | |
56 | |
57 static void init_base32_bits (void) | |
58 { | |
59 int i; | |
60 char *pos; | |
61 | |
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 } | |
69 | |
70 /*****************************************************************************/ | |
71 | |
72 BOOL gt_base32_valid (const char *base32, size_t len) | |
73 { | |
74 while (len > 0) | |
75 { | |
76 unsigned char c = toupper (*base32); | |
77 | |
78 if (!((c >= 'A' && c <= 'Z') || (c >= '2' && c <= '7'))) | |
79 break; | |
80 | |
81 base32++; | |
82 len--; | |
83 } | |
84 | |
85 return (len > 0 ? FALSE : TRUE); | |
86 } | |
87 | |
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); | |
93 | |
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 } | |
99 | |
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 (); | |
106 | |
107 assert (in_len == 32); | |
108 assert (out_len == 20); | |
109 | |
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 } | |
115 | |
116 /*****************************************************************************/ | |
117 | |
118 #if 0 | |
119 static void test_str (const char *test) | |
120 { | |
121 unsigned char bin[20]; | |
122 char hash[33]; | |
123 | |
124 hash[32] = 0; | |
125 | |
126 gt_base32_decode (test, strlen (test), bin, sizeof(bin)); | |
127 gt_base32_encode (bin, sizeof(bin), hash, sizeof(hash) - 1); | |
128 | |
129 if (!gt_base32_valid (hash, 32)) | |
130 abort (); | |
131 | |
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 } | |
139 | |
140 int main (int argc, char **argv) | |
141 { | |
142 int i, j; | |
143 char str[33]; | |
144 int len = strlen (ALPHA); | |
145 | |
146 str[sizeof (str) - 1] = 0; | |
147 | |
148 test_str (ALPHA); | |
149 | |
150 for (i = 1; i <= 100000; i++) | |
151 { | |
152 for (j = 0; j < 32; j++) | |
153 str[j] = ALPHA[rand () % len]; | |
154 | |
155 if (!gt_base32_valid (str, 32)) | |
156 abort (); | |
157 | |
158 printf ("%i\r", i); | |
159 fflush (stdout); | |
160 test_str (str); | |
161 usleep (1); | |
162 } | |
163 | |
164 printf ("\n"); | |
165 return 0; | |
166 } | |
167 #endif |