#include const char base32_map[33] = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"; /** No type safety */ #define MAX(a, b) ((a) > (b) ? (a) : (b)) #define MIN(a, b) ((a) < (b) ? (a) : (b)) /** return sym value or -1 if not found */ static int decode_sym(int sym) { int i; for (i = 0; i < 32; i++) { if (sym == base32_map[i]) { return i; } } return -1; } int base32_encode(char *dest, int destlen_chars, const void *srcbits, int srclen_bits) { const unsigned char *src = srcbits; int dstlen_need = (srclen_bits + 4) / 5 + 1, i, didx = 0; *dest = 0; if (destlen_chars < dstlen_need) { return 0; } for (i = 0; i < srclen_bits; i += 5) { int sym, sidx = i / 8, bit_offs = i % 8; if (bit_offs <= 3) { sym = src[sidx] >> (3 - bit_offs); } else { sym = src[sidx] << (bit_offs - 3); if (i + 1 < srclen_bits) { sym |= src[sidx + 1] >> (11 - bit_offs); } } sym &= 0x1f; if (srclen_bits - i < 5) { sym &= 0x1f << (5 + i - srclen_bits); } dest[didx++] = base32_map[sym]; } for (i = 0; i < (8 - (didx % 8)) % 8; i++) { dest[didx++] = '='; } dest[didx] = '\0'; return 0; } int base32_decode(unsigned char *dest, int destlen_bits, const char *src) { int out_bits = 0; for (; *src; src++) { int sym, sbits, dbits, b; if (isspace(*src) || *src == '-') { continue; } sym = decode_sym(*src); if (sym < 0) { return -1; } if (out_bits >= destlen_bits) { break; } sbits = MIN(5, destlen_bits - out_bits); if (sbits < 5) { sym >>= (5 - sbits); } dbits = 8 - (out_bits & 7); b = MIN(dbits, sbits); if (dbits == 8) { dest[out_bits / 8] = 0; } dest[out_bits / 8] |= (sym << (dbits - b)) >> (sbits - b); out_bits += b; sbits -= b; if (sbits > 0) { dest[out_bits / 8] = sym << (8 - sbits); out_bits += sbits; } } return out_bits; }