1 /* base64 encoder/decoder based on public domain implementation
7 #include <rpm/rpmbase64.h>
10 static char base64_encode_value(char value_in)
12 static const char encoding[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
13 if (value_in > 63) return '=';
14 return encoding[(int)value_in];
17 static char *base64_encode_block(const char *plaintext_in, int length_in, char *codechar)
19 const char *plainchar = plaintext_in;
20 const char *const plaintextend = plaintext_in + length_in;
25 if (plainchar == plaintextend) {
28 fragment = *plainchar++;
29 result = (fragment & 0x0fc) >> 2;
30 *codechar++ = base64_encode_value(result);
31 result = (fragment & 0x003) << 4;
32 if (plainchar == plaintextend)
34 *codechar++ = base64_encode_value(result);
39 fragment = *plainchar++;
40 result |= (fragment & 0x0f0) >> 4;
41 *codechar++ = base64_encode_value(result);
42 result = (fragment & 0x00f) << 2;
43 if (plainchar == plaintextend)
45 *codechar++ = base64_encode_value(result);
49 fragment = *plainchar++;
50 result |= (fragment & 0x0c0) >> 6;
51 *codechar++ = base64_encode_value(result);
52 result = (fragment & 0x03f) >> 0;
53 *codechar++ = base64_encode_value(result);
55 /* control should not reach here */
59 #define BASE64_DEFAULT_LINE_LENGTH 64
61 char *rpmBase64Encode(const void *data, size_t len, int linelen)
64 const char *dataptr = data;
72 linelen = BASE64_DEFAULT_LINE_LENGTH;
75 encodedlen = ((len + 2) / 3) * 4;
77 encodedlen += encodedlen/(linelen * 4) + 1;
79 ++encodedlen; /* for zero termination */
81 output = malloc(encodedlen);
87 if (linelen > 0 && len > linelen * 3) {
88 outptr = base64_encode_block(dataptr, linelen * 3, outptr);
90 dataptr += linelen * 3;
92 outptr = base64_encode_block(dataptr, len, outptr);
103 static int base64_decode_value(unsigned char value_in)
105 static const int decoding[] = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51};
107 if (value_in >= sizeof(decoding)/sizeof(int))
109 return decoding[value_in];
112 static size_t base64_decode_block(const char *code_in, const size_t length_in, char *plaintext_out)
114 const char *codechar = code_in;
115 char *plainchar = plaintext_out;
123 if (codechar == code_in+length_in)
125 return plainchar - plaintext_out;
127 fragment = base64_decode_value(*codechar++);
128 } while (fragment < 0);
129 *plainchar = (char)((fragment & 0x03f) << 2);
132 if (codechar == code_in+length_in)
134 return plainchar - plaintext_out;
136 fragment = base64_decode_value(*codechar++);
137 } while (fragment < 0);
138 *plainchar++ |= (char)((fragment & 0x030) >> 4);
139 *plainchar = (char)((fragment & 0x00f) << 4);
142 if (codechar == code_in+length_in)
144 return plainchar - plaintext_out;
146 fragment = base64_decode_value(*codechar++);
147 } while (fragment < 0);
148 *plainchar++ |= (char)((fragment & 0x03c) >> 2);
149 *plainchar = (char)((fragment & 0x003) << 6);
152 if (codechar == code_in+length_in)
154 return plainchar - plaintext_out;
156 fragment = base64_decode_value(*codechar++);
157 } while (fragment < 0);
158 *plainchar++ |= (char)(fragment & 0x03f);
160 /* control should not reach here */
161 return plainchar - plaintext_out;
164 int rpmBase64Decode(const char *in, void **out, size_t *outlen)
167 const char *inptr = in;
175 while (*inptr != '\0') {
176 /* assume all ASCII control chars as whitespace */
178 if (base64_decode_value(*inptr) != -1) {
190 outcnt = (outcnt / 4) * 3;
192 *out = malloc(outcnt + 1); /* base64_decode_block can write one extra character */
197 *outlen = base64_decode_block(in, inptr - in, *out);
202 #define CRC24_INIT 0xb704ce
203 #define CRC24_POLY 0x1864cfb
205 char *rpmBase64CRC(const unsigned char *data, size_t len)
207 uint32_t crc = CRC24_INIT;
211 crc ^= (*data++) << 16;
212 for (i = 0; i < 8; i++) {
218 crc = htonl(crc & 0xffffff);
219 data = (unsigned char *)&crc;
221 return rpmBase64Encode(data, 3, 0);
228 int main(int argc, char *argv[])
230 static char tst[]="wtrt8122čLýáj\x20s ~ýhž\t4\x02šjjmBvž^%$RTš#á.íěj\x1hčýčŤc+";
235 printf("Original: %lu\n%s\n", sizeof(tst)-1, tst);
236 encoded = rpmBase64Encode(tst, sizeof(tst)-1, 64);
237 printf("Encoded: %lu\n%s\n", strlen(encoded), encoded);
238 if ((err = rpmBase64Decode(encoded, &decoded, &size)) != 0) {
239 fprintf(stderr, "Error in decode: %d\n", err);
242 printf("Decoded:\n%.*s\n", (int)size, (char *)decoded);
243 if (size != sizeof(tst)-1) {
244 fprintf(stderr, "Size differs orig: %lu new: %lu\n", sizeof(tst)-1, size);
247 if (memcmp(tst, decoded, size) != 0) {
248 fprintf(stderr, "Decoded data differs.\n");
251 fprintf(stderr, "OK\n");