一、什么是Base32
Base32编码是使用32个可打印字符(字母A-Z和数字2-7)对任意字节数据进行编码的方案,编码后的字符串不用区分大小写并排除了容易混淆的字符,可以方便地由人类使用并由计算机处理。
二、编码方法
将任意字符串按照字节进行切分,并将每个字节对应的二进制值(不足8比特高位补0)串联起来,按照5比特一组进行切分,并将每组二进制值转换成十进制来对应32个可打印字符中的一个。
32是2的5次方,在进行2进制截位时,要一次截取5位。那么一个字节8位,截取了5位,剩下的3位怎么办?同理和下一个字节的前2位组成一个新的5位。那么多少个字节按照5位截取才能不丢位呢?我们要取5和8的最小公倍数,40位,按照5位截取,正好得到8个编码。
三、C语言实现的编码解码
废话不多说,上代码,该代码可直接运行
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <ctype.h>
// Base32字符表
static const char base32_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
// Base32编码函数
int base32_encode(char *dest, int destlen_chars,const void *srcbits, int srclen_bits) {
const uint8_t *src = srcbits;
int destlen_needed;
int didx = 0;
int i;
*dest = 0;
/* Make sure destination is big enough */
destlen_needed = (srclen_bits + 4) / 5; /* Symbols before adding CRC */
destlen_needed++; /* For terminating null */
if (destlen_chars < destlen_needed)
return -1; // Error: Destination buffer too small
for (i = 0; i < srclen_bits; i += 5) {
int sym;
int sidx = i / 8;
int bit_offs = i % 8;
if (bit_offs <= 3) {
/* Entire symbol fits in that byte */
sym = src[sidx] >> (3 - bit_offs);
} else {
/* Use the bits we have left */
sym = src[sidx] << (bit_offs - 3);
/* Use the bits from the next byte, if any */
if (i + 1 < srclen_bits)
sym |= src[sidx + 1] >> (11 - bit_offs);
}
sym &= 0x1f;
/* Pad incomplete symbol with 0 bits */
if (srclen_bits - i < 5)
sym &= 0x1f << (5 + i - srclen_bits);
dest[didx++] = base32_table[sym];
}
/* Calculate the number of padding characters needed */
int padding = (8 - (didx % 8)) % 8;
/* Pad the remaining characters with '=' */
for (i = 0; i < padding; i++) {
dest[didx++] = '=';
}
/* Terminate string and return */
dest[didx] = 0;
return 0; // Success
}
static int decode_sym(char c) {
if (c >= 'A' && c <= 'Z')
return c - 'A';
if (c >= '2' && c <= '7')
return c - '2' + 26;
return -1;
}
static int crc5_sym(int sym, int crc) {
return (crc << 5) ^ sym;
}
int base32_decode(uint8_t *dest, int destlen_bits, const char *src, int crc_after_every) {
int crc = 0, crc_count = 0;
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; /* Bad input symbol */
/* Check CRC if needed */
if (crc_after_every) {
if (crc_count == crc_after_every) {
if (crc != sym)
return -1;
crc_count = crc = 0;
continue;
} else {
crc = crc5_sym(sym, crc);
crc_count++;
}
}
/* Stop if we're out of space */
if (out_bits >= destlen_bits)
break;
/* See how many bits we get to use from this symbol */
sbits = MIN(5, destlen_bits - out_bits);
if (sbits < 5)
sym >>= (5 - sbits);
/* Fill up the rest of the current byte */
dbits = 8 - (out_bits & 7);
b = MIN(dbits, sbits);
if (dbits == 8)
dest[out_bits / 8] = 0; /* Starting a new byte */
dest[out_bits / 8] |= (sym << (dbits - b)) >> (sbits - b);
out_bits += b;
sbits -= b;
/* Start the next byte if there's space */
if (sbits > 0) {
dest[out_bits / 8] = sym << (8 - sbits);
out_bits += sbits;
}
}
/* If we have CRCs, should have a full group */
if (crc_after_every && crc_count)
return -1;
return out_bits;
}
int main() {
const char *input = "Hello,World!";
char output[100];
// 编码 "Hello" 的 Base32 值
int ret = base32_encode(output, sizeof(output), input, strlen(input) * 8);
if (ret == 0) {
printf("Base32 encoded string: %s\n", output);
} else {
printf("Error: Base32 encoding failed.\n");
}
const char *base32_encoded_string = "JBSWY3DPFRLW64TMMQQQ";
uint8_t decoded_data[20]; // Adjust the size accordingly
int decoded_bits = base32_decode(decoded_data, sizeof(decoded_data) * 8, base32_encoded_string, 0);
if (decoded_bits == -1) {
printf("Error decoding Base32 string.\n");
return 1;
}
printf("Decoded data: ");
for (int i = 0; i < decoded_bits / 8; i++) {
printf("%c", decoded_data[i]);
}
printf("\n");
return 0;
}