关于 Base64的使用意义一直是我心中的一个疑问。之前疏于理解 只知道所以 不知道所以然。 今天赶着自己心情舒畅 惠风徐徐 再次整理了一下关于base64的相关知识点。
首先是参考的几篇有意义的文献
http://zh.wikipedia.org/wiki/Base64
http://www.ruanyifeng.com/blog/2008/06/base64.html
前辈给出的定义是这样的
所谓Base64,就是说选出64个字符——小写字母a-z、大写字母A-Z、数字0-9、符号“+”、“/”(再加上作为垫字的“=”,实际上是65个字符)——作为一个基本字符集。然后,其他所有符号都转换成这个字符集中的字符。
维基百科中是这样定义
Base64是一种使用64基的位置计数法。它使用2的最大次方来代表仅可打印的ASCII 字符。这使它可用来作为电子邮件的传输编码。在Base64中的变量使用字符A-Z、a-z和0-9 ,这样共有62个字符,用来作为开始的64个数字,最后两个用来作为数字的符号在不同的系统中而不同。
我个人觉得这两种解释已经够用的了。base64是为了在多系统中的持久化与正确性 毕竟 将字符保证在最小子集中 我们可以确信不会因为字符集产生问题。这样的代价是所占空间大小增加了1/3 .以为24bit的内容 需要使用32bit来保存 但是这个是可以接受的
采取的步骤
第一步,将每三个字节作为一组,一共是24个二进制位。
第二步,将这24个二进制位分为四组,每个组有6个二进制位。
第三步,在每组前面加两个00,扩展成32个二进制位,即四个字节。
第四步,根据映射表,得到扩展后的每个字节的对应符号,就是Base64的编码值。
以下是用到的关于c的 base64编码 希望能够对你有所帮助(摘自weibo c++ SDK)
/**
* Base64 encode one byte
*/
char oauth_b64_encode(unsigned char u) {
if(u < 26) return 'A'+u;
if(u < 52) return 'a'+(u-26);
if(u < 62) return '0'+(u-52);
if(u == 62) return '+';
return '/';
}
/**
* Base64 encode and return size data in 'src'. The caller must free the
* returned string.
*
* @param size The size of the data in src
* @param src The data to be base64 encode
* @return encoded string otherwise NULL
*/
char *oauth_encode_base64(int size, const unsigned char *src) {
int i;
char *out, *p;
if(!src) return NULL;
if(!size) size= strlen((char *)src);
// out= (char*) xcalloc(sizeof(char), size*4/3+4);
out= (char*) SysHeap_Calloc( sizeof(char) *(size*4/3+4));
p= out;
for(i=0; i<size; i+=3) {
unsigned char b1=0, b2=0, b3=0, b4=0, b5=0, b6=0, b7=0;
b1= src[i];
if(i+1<size) b2= src[i+1];
if(i+2<size) b3= src[i+2];
b4= b1>>2;
b5= ((b1&0x3)<<4)|(b2>>4);
b6= ((b2&0xf)<<2)|(b3>>6);
b7= b3&0x3f;
*p++= oauth_b64_encode(b4);
*p++= oauth_b64_encode(b5);
if(i+1<size) *p++= oauth_b64_encode(b6);
else *p++= '=';
if(i+2<size) *p++= oauth_b64_encode(b7);
else *p++= '=';
}
return out;
}
一般的 size设定 #define SHA_DIGESTSIZE 20
疑问得解 其心甚慰
ps:
今天看了一更行云流水般的实现 决定在这篇文章的后边附上 我觉得 这才是程序的艺术魅力 我深深折服中
static const char g_base64_chars [] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
void _encode_block ( u_char in[3], u_char out[4] )
{
out[0] = g_base64_chars [ ( in[0] >> 2 ) ];
out[1] = g_base64_chars [ ( ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ) ];
out[2] = g_base64_chars [ ( ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ) ];
out[3] = g_base64_chars [ ( in[2] & 0x3f ) ];
}
void encode_base64 ( u_char* input, int inputlen,
u_char* output, int outlen
)
{
while ( inputlen >= 3 )
{
_encode_block ( input, output );
inputlen -= 3;
input += 3;
output += 4;
}
if ( inputlen > 0 )
{
u_char temp[3];
memset ( temp, 0, sizeof(temp) );
memcpy ( temp, input, inputlen );
_encode_block ( temp, output );
output[3] = '=';
if ( inputlen == 1 )
output[2] = '=';
output += 4;
}
output[0] = 0;
}
ps: 解码参考表 对应的是ascii的数值//256 http://zh.wikipedia.org/wiki/ASCII
一下是ascii 对应的码值 我们需要将它与ascii 建立映射关系
0 A 17 R 34 i 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6 G 23 X 40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 +
12 M 29 d 46 u 63 /
13 N 30 e 47 v
14 O 31 f 48 w
15 P 32 g 49 x
16 Q 33 h 50 y
所以 在这个数组中 我们将64个值与ascii 建立了映射关系
static int g_base64_to_int6 [] =
{
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63,
52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-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,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
};
这里是解码的过程:
int decode_base64 ( u_char* input, int inputlen,
u_char* output,int outlen )
{
u_char *cur = 0;
u_char *end = 0;
u_char *out = 0;
u_char *outend = 0;
int i6val = 0;
int i6prev = 0;
int state = 0;
int minlen = 0;
u_char c;
if ( !input || !output )
return -1;
minlen = ((inputlen+2)/4)*3;
if ( outlen < minlen )
return -1;
cur = input;
end = cur + inputlen;
out = output;
outend = out + outlen;
for ( cur; cur != end && out < outend; ++cur )
{
i6val = g_base64_to_int6 [ (int)*cur];
if ( i6val != -1 )
{
switch ( state )
{
case 0:
{
++state;
break;
}
case 1:
{
c = ((i6prev << 2) | ((i6val & 0x30) >> 4));
*out++ = c;
++state;
break;
}
case 2:
{
c = (((i6prev & 0xf) << 4) | ((i6val & 0x3c) >> 2));
*out++ = c;
++state;
break;
}
case 3:
{
c = (((i6prev & 0x03 ) << 6) | i6val);
*out++ = c;
state = 0;
break;
}
}
i6prev = i6val;
}
}
if ( cur < end )
{
//insufficient out buffer.
return -1;
}
return (out - output);
}
本来以为挺明白 结果还是有些不明白 学习要加强啊 不能一知半解啊