zb32: New z-base-32 encoder
[wk-misc.git] / zb32.c
1 /* zb32.c - z-base-32 encoder
2  * Copyright (C) 2014, 2015  Werner Koch
3  *
4  * This file is part of GnuPG.
5  *
6  * This file is free software; you can redistribute it and/or modify
7  * it under the terms the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 3 of the
9  * License, or (at your option) any later version.
10  *
11  * This file is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 /* The code is based on GnuPG's common/zb32.c  */
21
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27
28 #define PGM "zb32"
29
30
31 /* Zooko's base32 variant. See RFC-6189 and
32    http://philzimmermann.com/docs/human-oriented-base-32-encoding.txt
33    Caller must xfree the returned string.  Returns NULL and sets ERRNO
34    on error.  To avoid integer overflow DATALEN is limited to 2^16
35    bytes.  Note, that DATABITS is measured in bits!.  */
36 static char *
37 zb32_encode (const void *data, unsigned int databits)
38 {
39   static char const zb32asc[32] = {'y','b','n','d','r','f','g','8',
40                                    'e','j','k','m','c','p','q','x',
41                                    'o','t','1','u','w','i','s','z',
42                                    'a','3','4','5','h','7','6','9' };
43   const unsigned char *s;
44   char *output, *d;
45   size_t datalen;
46
47   datalen = (databits + 7) / 8;
48   if (datalen > (1 << 16))
49     {
50       errno = EINVAL;
51       return NULL;
52     }
53
54   d = output = malloc (8 * (datalen / 5)
55                            + 2 * (datalen % 5)
56                            - ((datalen%5)>2)
57                            + 1);
58   if (!output)
59     return NULL;
60
61   /* I use straightforward code.  The compiler should be able to do a
62      better job on optimization than me and it is easier to read.  */
63   for (s = data; datalen >= 5; s += 5, datalen -= 5)
64     {
65       *d++ = zb32asc[((s[0]      ) >> 3)               ];
66       *d++ = zb32asc[((s[0] &   7) << 2) | (s[1] >> 6) ];
67       *d++ = zb32asc[((s[1] &  63) >> 1)               ];
68       *d++ = zb32asc[((s[1] &   1) << 4) | (s[2] >> 4) ];
69       *d++ = zb32asc[((s[2] &  15) << 1) | (s[3] >> 7) ];
70       *d++ = zb32asc[((s[3] & 127) >> 2)               ];
71       *d++ = zb32asc[((s[3] &   3) << 3) | (s[4] >> 5) ];
72       *d++ = zb32asc[((s[4] &  31)     )               ];
73     }
74
75   switch (datalen)
76     {
77     case 4:
78       *d++ = zb32asc[((s[0]      ) >> 3)               ];
79       *d++ = zb32asc[((s[0] &   7) << 2) | (s[1] >> 6) ];
80       *d++ = zb32asc[((s[1] &  63) >> 1)               ];
81       *d++ = zb32asc[((s[1] &   1) << 4) | (s[2] >> 4) ];
82       *d++ = zb32asc[((s[2] &  15) << 1) | (s[3] >> 7) ];
83       *d++ = zb32asc[((s[3] & 127) >> 2)               ];
84       *d++ = zb32asc[((s[3] &   3) << 3)               ];
85       break;
86     case 3:
87       *d++ = zb32asc[((s[0]      ) >> 3)               ];
88       *d++ = zb32asc[((s[0] &   7) << 2) | (s[1] >> 6) ];
89       *d++ = zb32asc[((s[1] &  63) >> 1)               ];
90       *d++ = zb32asc[((s[1] &   1) << 4) | (s[2] >> 4) ];
91       *d++ = zb32asc[((s[2] &  15) << 1)               ];
92       break;
93     case 2:
94       *d++ = zb32asc[((s[0]      ) >> 3)               ];
95       *d++ = zb32asc[((s[0] &   7) << 2) | (s[1] >> 6) ];
96       *d++ = zb32asc[((s[1] &  63) >> 1)               ];
97       *d++ = zb32asc[((s[1] &   1) << 4)               ];
98       break;
99     case 1:
100       *d++ = zb32asc[((s[0]      ) >> 3)               ];
101       *d++ = zb32asc[((s[0] &   7) << 2)               ];
102       break;
103     default:
104       break;
105     }
106   *d = 0;
107
108   /* Need to strip some bytes if not a multiple of 40.  */
109   output[(databits + 5 - 1) / 5] = 0;
110   return output;
111 }
112
113
114
115
116 int
117 main (int argc, char **argv )
118 {
119   int c, i;
120   char buffer[500]; /* Needs to be a multiple of 5! */
121   char *output;
122
123   if ( argc > 1 )
124     {
125       fprintf (stderr, "usage: " PGM " < input\n");
126       return 1;
127     }
128
129   i = 0;
130   while ((c = getchar ()) != EOF)
131     {
132       buffer[i++] = c;
133       if (i == sizeof buffer)
134         {
135           output = zb32_encode (buffer, 8 * sizeof buffer);
136           if (!output)
137             {
138               fprintf (stderr, PGM ": error converting data: %s\n",
139                        strerror (errno));
140               return 1;
141             }
142           fputs (output, stdout);
143           free (output);
144           i = 0;
145         }
146     }
147   if (ferror (stdin))
148     {
149       fprintf (stderr, PGM ": read error: %s\n", strerror (errno));
150       return 1;
151     }
152
153   if (i)
154     {
155       output = zb32_encode (buffer, 8 * i);
156       if (!output)
157         {
158           fprintf (stderr, PGM ": error converting data: %s\n",
159                    strerror (errno));
160           return 1;
161         }
162       fputs (output, stdout);
163       free (output);
164     }
165
166   putchar ('\n');
167
168   if (fflush (stdout) || ferror (stdout))
169     {
170       fprintf (stderr, PGM ": write error: %s\n", strerror (errno));
171       return 1;
172     }
173
174   return 0;
175 }