base58的编码原理为,将待编码数据的ascii整体看作一个256进制数,再把这个256进制数转为58进制,并查表找到对应字符。解码时先找到每个字节的字符在表中的位置,并把数组整体看作一个58进制数,再将58进制数转为256进制。base58默认码表为"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz",码表可以更改。
base36的编码原理为,将待编码数据的ascii整体看作一个10进制数(注意,代编码字符串中只能包含数字),再把这个10进制数转为36进制,并查表找到对应字符。解码时先找到每个字节的字符在表中的位置,并把数组整体看作一个58进制数,再将36进制数转为10进制。base36默认码表为"0123456789abcdefghijklmnopqrstuvwxyz",码表可以更改。
base62的编码原理为,将待编码数据的ascii整体看作一个10进制数(注意,代编码字符串中只能包含数字),再把这个10进制数转为62进制,并查表找到对应字符。解码时先找到每个字节的字符在表中的位置,并把数组整体看作一个62进制数,再将62进制数转为10进制。base62默认码表为"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",码表可以更改。
base.h
#ifndef __BASE_H__
#define __BASE_H__
size_t Base64_Encode(const unsigned char*src, size_t src_len, char* dst, const char* pcharset, int newline_flag);
size_t Base64_Decode(const char* src, size_t src_len, unsigned char* dst, const char* pcharset, int newline_flag);
size_t Base16_Encode(const unsigned char* src, size_t src_len, char* dst, const char* pcharset);
size_t Base16_Decode(const char* src, size_t src_len, unsigned char* dst, const char* pcharset);
size_t Base24_Encode(const unsigned char* src, size_t src_len, char* dst, const char* pcharset);
size_t Base24_Decode(const char* src, size_t src_len, unsigned char* dst, const char* pcharset);
size_t Base32_Encode(const unsigned char* src, size_t src_len, char* dst, const char* pcharset);
size_t Base32_Decode(const char* src, size_t src_len, unsigned char* dst, const char* pcharset);
size_t Base58_Encode(const unsigned char* src, size_t src_len, char* dst, const char* pcharset);
size_t Base58_Decode(const char* src, size_t src_len, unsigned char* dst, const char* pcharset);
size_t Base36_Encode(const char* src, size_t src_len, char* dst, const char* pcharset);
size_t Base36_Decode(const char* src, size_t src_len, char* dst, const char* pcharset);
size_t Base62_Encode(const char* src, size_t src_len, char* dst, const char* pcharset);
size_t Base62_Decode(const char* src, size_t src_len, char* dst, const char* pcharset);
#endif
base.c
#include "stdlib.h"
#include "string.h"
#ifndef _WINDOWS
#include
#endif
#include "ctype.h"
#include "Base.h"
typedef enum _BaseType
{
En_Base_Type_Base16,
En_Base_Type_Base24,
En_Base_Type_Base32,
En_Base_Type_Base64,
En_Base_Type_Base36,
En_Base_Type_Base58,
En_Base_Type_Base62,
En_Base_Type_Base85,
En_Base_Type_Base91,
En_Base_Type_Base92,
En_Base_Type_Base45,
En_Base_Type_Base100,
}En_Base_Type;
#define NEWLINE_INVL 76
static const char* pacCharset[] =
{
"0123456789ABCDEF",
"BCDFGHJKMPQRTVWXY2346789",
"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
"0123456789abcdefghijklmnopqrstuvwxyz",
"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz",
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
};
static const int blkLen[] =
{
4,
4,
5,
6,
};
//encodeBlkLen控制编码模块大小,其中base36、base58、base62代表字符串转换进制数
static const int encodeBlkLen[] =
{
1,
1,
5,
3,
10,
256,
10
};
//encodeBlkLen控制编码目标模块大小,其中base36、base58、base62代表字符串转换目标进制数
static const int targetBlkLen[] =
{
2,
2,
8,
4,
36,
58,
62
};
static int is_numeric(const char* str, size_t len) {
for (size_t i = 0; i < len;i++) {
if (!isdigit(str[i]))
return 0;
}
return 1;
}
static unsigned char revchar(char ch, const char* charset)
{
for (unsigned char c = 0;c < strlen(charset); c++)
{
if (charset[c] == ch)
return c;
}
return -1;
}
static unsigned char divmod(unsigned char* number, size_t len, unsigned short base, unsigned short divisor) {
unsigned char remainder = 0;
for (size_t i = 0; i < len; i++) {
unsigned char digit = number[i];
int temp = remainder * base + digit;
number[i] = temp / divisor;
remainder = temp % divisor;
}
return remainder;
}
static size_t Base_Encode(En_Base_Type type, const unsigned char* src, size_t src_len, char* dst, const char* pcharset, int newline_flag)
{
const char* charset = pacCharset[type];
if (pcharset)
charset = pcharset;
if (type <= En_Base_Type_Base64)
{
if (type != En_Base_Type_Base64)
{
newline_flag = 0;
}
size_t idx, idx2 = 0, blks, left_over, newline_count = 0;
blks = (src_len / encodeBlkLen[type]);
left_over = src_len % encodeBlkLen[type];
if (dst == nullptr) {
idx2 = blks * targetBlkLen[type];
if (left_over)
idx2 += targetBlkLen[type];
if (newline_flag)
idx2 += src_len / ((NEWLINE_INVL / targetBlkLen[type]) * encodeBlkLen[type]);
}
else {
int tmpVlaue = 0;
int pos = blkLen[type];
for (idx = 0; idx < src_len; idx++) {
int right_shift = 8 - pos % 8;
dst[idx2] = charset[tmpVlaue | (src[idx] >> right_shift)];
while (right_shift > blkLen[type])
{
right_shift -= blkLen[type];
tmpVlaue = (((src[idx] >> right_shift) & ((1 << blkLen[type]) - 1)));
dst[++idx2] = charset[tmpVlaue];
pos += blkLen[type];
}
int left_shift = blkLen[type] - right_shift;
tmpVlaue = ((src[idx] & ((1 << right_shift) - 1)) << left_shift);
pos += blkLen[type];
if (pos % 8 == 0)
{
pos = blkLen[type];
dst[++idx2] = charset[tmpVlaue];
if (type == En_Base_Type_Base24)
{
dst[idx2] = charset[23 - tmpVlaue];
}
idx2++;
tmpVlaue = 0;
}
else
{
idx2++;
}
if (((idx2 - newline_count + targetBlkLen[type]) % NEWLINE_INVL == 0) && newline_flag) {
dst[idx2 + targetBlkLen[type]] = '\n';
idx2++;
newline_count++;
}
}
if (left_over)
{
dst[idx2++] = charset[tmpVlaue];
int leftChar = targetBlkLen[type] - ((left_over * 8 + blkLen[type] - 1) / blkLen[type]);
for (int i = 0;i < leftChar;i++)
{
dst[idx2++] = '=';
}
}
}
return(idx2);
}
else if (type <= En_Base_Type_Base62)
{
unsigned char* psrc = (unsigned char*)malloc(src_len);
memcpy(psrc, src, src_len);
unsigned char* pStart = psrc;
char* p = (char*)malloc(src_len * 2 + 1);
size_t dstLen = 0;
memset(p, 0, src_len * 2 + 1);
for (size_t i = 0;i < src_len;)
{
p[dstLen++] = divmod(psrc + i, src_len - i, encodeBlkLen[type], targetBlkLen[type]);
while (psrc[i] == 0)
{
i++;
}
}
if (dst)
{
for (size_t i = 0;i < dstLen;i++)
{
dst[i] = charset[p[dstLen - i - 1]];
}
}
return dstLen;
}
else
{
return 0;
}
}
static size_t Base_Decode(En_Base_Type type, const char* src, size_t src_len, unsigned char* dst, const char* pcharset, int newline_flag)
{
const char* charset = pacCharset[type];
if (pcharset)
charset = pcharset;
if (type <= En_Base_Type_Base64)
{
size_t idx = 0, idx2, blks, left_over;
while (src[src_len - 1] == '=')
src_len--;
blks = src_len / targetBlkLen[type];
left_over = src_len % targetBlkLen[type];
if (dst == nullptr) {
if (src_len > NEWLINE_INVL && src[NEWLINE_INVL] == '\n') // Verify that newlines where used.
src_len -= src_len / (NEWLINE_INVL + 1);
blks = src_len / targetBlkLen[type];
left_over = src_len % targetBlkLen[type];
idx = blks * encodeBlkLen[type];
idx += (left_over * blkLen[type] + 7) / 8;
}
else {
for (idx2 = 0; idx2 < src_len; idx2++) {
if (src[idx2] == '\n')
idx2++;
int left_shift = ((8 - blkLen[type]) * (idx2 + 1)) % 8;
dst[idx] = (revchar(src[idx2], charset) << left_shift);
while (blkLen[type] <= left_shift)
{
left_shift -= blkLen[type];
if (type == En_Base_Type_Base24)
dst[idx] |= ((23 - revchar(src[++idx2], charset)) << left_shift);
else
dst[idx] |= (revchar(src[++idx2], charset) << left_shift);
}
if (left_shift)
{
int right_shift = blkLen[type] - left_shift;
dst[idx] |= ((revchar(src[idx2 + 1], charset)) >> right_shift);
}
idx++;
}
}
return(idx);
}
else if (type <= En_Base_Type_Base62)
{
unsigned char* psrc = (unsigned char*)malloc(src_len);
for (size_t i = 0;i < src_len;i++)
{
psrc[i] = revchar(src[i], charset);
}
unsigned char* pStart = psrc;
char* p = (char*)malloc(src_len * 2 + 1);
size_t dstLen = 0;
memset(p, 0, src_len * 2 + 1);
for (size_t i = 0;i < src_len;)
{
p[dstLen++] = divmod(psrc + i, src_len - i, targetBlkLen[type], encodeBlkLen[type]);
while (psrc[i] == 0)
{
i++;
}
}
if (dst)
{
for (size_t i = 0;i < dstLen;i++)
{
dst[i] = p[dstLen - i - 1];
}
}
return dstLen;
}
else
{
return 0;
}
}
size_t Base64_Encode(const unsigned char* src, size_t src_len, char* dst, const char* pcharset, int newline_flag)
{
return Base_Encode(En_Base_Type_Base64, src, src_len, dst, pcharset, newline_flag);
}
size_t Base64_Decode(const char* src, size_t src_len, unsigned char* dst, const char* pcharset, int newline_flag)
{
return Base_Decode(En_Base_Type_Base64, src, src_len, dst, pcharset, newline_flag);
}
size_t Base16_Encode(const unsigned char* src, size_t src_len, char* dst, const char* pcharset)
{
return Base_Encode(En_Base_Type_Base16, src, src_len, dst, pcharset, 0);
}
size_t Base16_Decode(const char* src, size_t src_len, unsigned char* dst, const char* pcharset)
{
return Base_Decode(En_Base_Type_Base16, src, src_len, dst, pcharset, 0);
}
size_t Base24_Encode(const unsigned char* src, size_t src_len, char* dst, const char* pcharset)
{
return Base_Encode(En_Base_Type_Base24, src, src_len, dst, pcharset, 0);
}
size_t Base24_Decode(const char* src, size_t src_len, unsigned char* dst, const char* pcharset)
{
return Base_Decode(En_Base_Type_Base24, src, src_len, dst, pcharset, 0);
}
size_t Base32_Encode(const unsigned char* src, size_t src_len, char* dst, const char* pcharset)
{
return Base_Encode(En_Base_Type_Base32, src, src_len, dst, pcharset, 0);
}
size_t Base32_Decode(const char* src, size_t src_len, unsigned char* dst, const char* pcharset)
{
return Base_Decode(En_Base_Type_Base32, src, src_len, dst, pcharset, 0);
}
size_t Base58_Encode(const unsigned char* src, size_t src_len, char* dst, const char* pcharset)
{
return Base_Encode(En_Base_Type_Base58, src, src_len, dst, pcharset, 0);
}
size_t Base58_Decode(const char* src, size_t src_len, unsigned char* dst, const char* pcharset)
{
return Base_Decode(En_Base_Type_Base58, src, src_len, dst, pcharset, 0);
}
size_t Base36_Encode(const char* src, size_t src_len, char* dst, const char* pcharset)
{
size_t ret = 0;
if (is_numeric(src, src_len))
{
unsigned char *src_buf = (unsigned char*)malloc(src_len);
for(size_t i = 0; i < src_len; i++)
src_buf[i] = (unsigned char)src[i] - 48;
ret = Base_Encode(En_Base_Type_Base36, src_buf, src_len, dst, pcharset, 0);
free(src_buf);
}
return ret;
}
size_t Base36_Decode(const char* src, size_t src_len, char* dst, const char* pcharset)
{
size_t ret = Base_Decode(En_Base_Type_Base36, src, src_len, (unsigned char*)dst, pcharset, 0);
if (dst)
{
for (size_t i = 0; i < ret; i++)
{
dst[i] += 48;
}
}
return ret;
}
size_t Base62_Encode(const char* src, size_t src_len, char* dst, const char* pcharset)
{
size_t ret = 0;
if (is_numeric(src, src_len))
{
unsigned char* src_buf = (unsigned char*)malloc(src_len);
for (size_t i = 0; i < src_len; i++)
src_buf[i] = (unsigned char)src[i] - 48;
ret = Base_Encode(En_Base_Type_Base62, src_buf, src_len, dst, pcharset, 0);
free(src_buf);
}
return ret;
}
size_t Base62_Decode(const char* src, size_t src_len, char* dst, const char* pcharset)
{
size_t ret = Base_Decode(En_Base_Type_Base62, src, src_len, (unsigned char*)dst, pcharset, 0);
if (dst)
{
for (size_t i = 0; i < ret; i++)
{
dst[i] += 48;
}
}
return ret;
}
测试示例
#include "Base.h"
int main(void) /* finds cube of entered number */
{
unsigned char test[] = "123456789";
char* enc;
size_t size;
size = Base64_Encode(test, 9, NULL, NULL, 0);
enc = (char*)malloc(size + 1);
memset(enc, 0, size + 1);
Base64_Encode(test, 9, enc, NULL, 0);
printf("%s\n", enc);
unsigned char* dec;
size = Base64_Decode(enc, strlen(enc), NULL, NULL, 0);
dec = (unsigned char*)malloc(size + 1);
memset(dec, 0, size + 1);
Base64_Decode(enc, strlen(enc), dec, NULL, 0);
printf("%s\n", dec);
free(dec);
free(enc);
size = Base16_Encode(test, 9, NULL, NULL);
enc = (char*)malloc(size + 1);
memset(enc, 0, size + 1);
Base16_Encode(test, 9, enc, NULL);
printf("%s\n", enc);
size = Base16_Decode(enc, strlen(enc), NULL, NULL);
dec = (unsigned char*)malloc(size + 1);
memset(dec, 0, size + 1);
Base16_Decode(enc, strlen(enc), dec, NULL);
printf("%s\n", dec);
free(dec);
free(enc);
size = Base32_Encode(test, 9, NULL, NULL);
enc = (char*)malloc(size + 1);
memset(enc, 0, size + 1);
Base32_Encode(test, 9, enc, NULL);
printf("%s\n", enc);
size = Base32_Decode(enc, strlen(enc), NULL, NULL);
dec = (unsigned char*)malloc(size + 1);
memset(dec, 0, size + 1);
Base32_Decode(enc, strlen(enc), dec, NULL);
printf("%s\n", dec);
free(dec);
free(enc);
size = Base24_Encode(test, 9, NULL, NULL);
enc = (char*)malloc(size + 1);
memset(enc, 0, size + 1);
Base24_Encode(test, 9, enc, NULL);
printf("%s\n", enc);
size = Base24_Decode(enc, strlen(enc), NULL, NULL);
dec = (unsigned char*)malloc(size + 1);
memset(dec, 0, size + 1);
Base24_Decode(enc, strlen(enc), dec, NULL);
printf("%s\n", dec);
free(dec);
free(enc);
size = Base58_Encode(test, 9, NULL, NULL);
enc = (char*)malloc(size + 1);
memset(enc, 0, size + 1);
Base58_Encode(test, 9, enc, NULL);
printf("%s\n", enc);
size = Base58_Decode(enc, strlen(enc), NULL, NULL);
dec = (unsigned char*)malloc(size + 1);
memset(dec, 0, size + 1);
Base58_Decode(enc, strlen(enc), dec, NULL);
printf("%s\n", dec);
free(dec);
free(enc);
size = Base36_Encode((const char*)test, 9, NULL, NULL);
enc = (char*)malloc(size + 1);
memset(enc, 0, size + 1);
Base36_Encode((const char*)test, 9, enc, NULL);
printf("%s\n", enc);
size = Base36_Decode(enc, strlen(enc), NULL, NULL);
dec = (unsigned char*)malloc(size + 1);
memset(dec, 0, size + 1);
Base36_Decode(enc, strlen(enc), (char*)dec, NULL);
printf("%s\n", dec);
free(dec);
free(enc);
size = Base62_Encode((const char*)test, 9, NULL, NULL);
enc = (char*)malloc(size + 1);
memset(enc, 0, size + 1);
Base62_Encode((const char*)test, 9, enc, NULL);
printf("%s\n", enc);
size = Base62_Decode(enc, strlen(enc), NULL, NULL);
dec = (unsigned char*)malloc(size + 1);
memset(dec, 0, size + 1);
Base62_Decode(enc, strlen(enc), (char*)dec, NULL);
printf("%s\n", dec);
free(dec);
free(enc);
return 0;
}