Base64的 c实现

关于 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);
}

本来以为挺明白 结果还是有些不明白  学习要加强啊  不能一知半解啊

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值