annotate 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
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