http_base64

libghttp中也有base加密代码,这里主要是权限认证部分使用到了,base64的代码有很多的介绍,核心思想就是3个字节用4个字节来表示,因此这里不过多介绍理论部分了,在代码中笔者做了很详细的注释,估计看代码注释就能看懂了,唯一不舒服的地方可能是字节的各种逻辑运算处理起来比较绕,但是这个不算难。

 

b64_alphabet提供了一个转换表,只要使用base64加密,那么计算机中的一切字符转换后都是通过这65个字符来表述,转换后的一切数据都是通过查这个表来获得一个字符进行表述的:

const char b64_alphabet[65] = { 
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "abcdefghijklmnopqrstuvwxyz"
    "0123456789+/=" };

源码就一个加密接口,在这个库中没有解密代码,对加密代码的算法注释说明的非常的清晰,直接看代码应该不难:

/*
 * 输入参数:text,待加密的字符串
 * 返回值: base加密后的字符串
 */    
char *
http_base64_encode(const char *text) 
{
    char *buffer = NULL;
    char *point = NULL;
    int inlen = 0;
    int outlen = 0;

    /* check our args */
    if (text == NULL)
        return NULL;

    /* 使用buffer存储输出数据,首先计算大小 */
    inlen = strlen( text );

    if (inlen == 0)
    {
        //传入字符串长度为0则直接返回
        buffer = malloc(sizeof(char));
        buffer[0] = '\0';
        return buffer;
    }
    outlen = (inlen*4)/3;
    if( (inlen % 3) > 0 ) /*outlen避免传入字符串长度不是3的倍数的时候outlen会缺少一部分,这里增加上 */
        outlen += 4 - (inlen % 3);

    buffer = malloc( outlen + 1 ); 
    memset(buffer, 0, outlen + 1); 

    /* 循环中每次处理3个字节,剩余的在循环外面处理,这是base的核心思想就是将 将3个字节转换成4个字节,算法是3*8=4*6,
        也就是将三个字节转换为24位之后,取6个位组成一个新的字节,6bit高两位补零。
    */
    for( point=buffer; inlen>=3; inlen-=3, text+=3 )
    {
        /*
        B=第一个字节
        I=第二个字节
        T=第三个字节
        三个字节的位顺序就是:
        B1B2B3B4 B5B6B7B8 | I1I2I3I4 I5I6I7I8 | T1T2T3T4 T5T6T7T8

        获取转换后的第一个字节:
        进行移位取出第一个字节的高6bit
        B1B2B3B4 B5B6 | 00 | 0000 0000 | 0000 0000
        *text>>2 = B1B2B3B4 B5B6 
        则取出来前6位,高2位补零后,转换后第一个字节的索引值是a= 00B1B2 B3B4B5B6
        那么:
        *(point++) = b64_alphabet[a];*/
        
        *(point++) = b64_alphabet[ *text>>2 ]; 
        /*
        获取转换后的第二个字节:
        1)将第一个字节的高4位先移除掉,并且与0011 0000进行按位与,这个目的就是将第一个字节的后面两个bit取出来,
          这样第一个字节的所有位都处理完了
            *text<<4 = B5B6B7B8 0000
            (*text<<4 & 0x30) = (B5B6B7B8 0000) & (0011 0000)        
          
        2)现在6bit只获取了两个bit,剩下的4bit则从第二个字节获得,因此此时需要对text指针进行移位即(text+1),
        已经有两个bit了只需要在第二个字节里面取出高4bit即可,因此进行了*(text+1)>>4操作
            *(text+1) = I1I2I3I4 I5I6I7I8
            *(text+1)>>4 = 0000 I1I2I3I4
            
        3)后面再将第一个字节获得的2bit和第二个字节获取到的4bit组成到一块就可以了,也就是按位或,那么此时就是
        (*text<<4 & 0x30) | *(text+1)>>4 = B5B6 I1I2I3I4
          ,转换后第二个字节的索引值是a= 00B5B6 I1I2I3I4
          *(point++) = b64_alphabet[a];
        */
        *(point++) = b64_alphabet[ (*text<<4 & 0x30) | *(text+1)>>4 ]; 
        /*
        获取转换后的第三个字节:
        1)将第二个字节的高2位先移除掉,并且与0011 1100进行按位与,这个目的就是将第二个字节的后面四个bit取出来,
          这样第二个字节的所有位都处理完了
          *(text+1) = I1I2I3I4 I5I6I7I8
          *(text+1)<<2 = I3I4 I5I6 I7I8 00
          *(text+1)<<2 & 0x3c = (I3I4 I5I6 I7I8 00) & (0011 1100) = 00I5I6 I7I800
        2)现在取出来第三个字节的高两位
          *(text+2) = T1T2T3T4 T5T6T7T8
          *(text+2)>>6 = 0000 00T1T2
          *(text+1)<<2 & 0x3c) | *(text+2)>>6  = (00I5I6 I7I800) | (0000 00T1T2) = I5I6 I7I8 T1T2
          那么转换后第三个字节的索引值是a= 00I5I6 I7I8 T1T2
          *(point++) = b64_alphabet[a];
        */
        *(point++) = b64_alphabet[ (*(text+1)<<2 & 0x3c) | *(text+2)>>6 ];
        /*
        获取转换后的第四个字节:
        1)此时转换前的第三个字节只剩下六位
          *(text+2) = T1T2T3T4 T5T6T7T8
          *(text+2) & 0x3f = (T1T2T3T4 T5T6T7T8) & (0011 1111) = 00T3T4 T5T6T7T8
          那么转换后第四个字节的索引值是a= 00T3T4 T5T6T7T8
          *(point++) = b64_alphabet[a];
        */
        *(point++) = b64_alphabet[ *(text+2) & 0x3f ];
    }

    /*text字符串并长度不一定是3的倍数,因此上述循环处理之后可能剩下一个或者2个字节,还要继续处理*/
    if( inlen ) 
    {
        /* We always have one trailing byte */
        //获取转换后的第二个字节:首先取出来高6位组成一个索引字节
        *(point++) = b64_alphabet[ *text>>2 ];
        /*
        获取转换后的第二个字节:
        1)将剩余的第一个字节的剩余2bit取出来
          第一个字节的完整8bit数据:xxxx xxxx
          先屏蔽高4位
          *text<<4 = xxxx 0000
          然后再去出来最后2bit
          (*text<<4 & 0x30) = (xxxx 0000) & (0011 0000)
         2)如果循环处理后剩余了一个字节,那么转换后的第二个字节索引就是1)中剩余的后两个bit
          即转换后的索引值就是a = 0000 00xx
         3)如果循环处理后剩余了2个字节
         第二个字节完整的8bit是:yyyy yyyy
         那么在1)的基础上现在需要取出来第二个字节的高4bit
         *(text+1) = yyyy yyyy
         (text+1)>>4 = 0000 yyyy
         即转换后的索引值就是a = 00xx yyyy
        */
        *(point++) = b64_alphabet[ (*text<<4 & 0x30) | (inlen==2?*(text+1)>>4:0) ]; 
        /*
        获取转换后的第三个字节:
        1)如果循环处理后剩余了一个字节,那么转换后的第三个字节就是'='
        2)如果循环处理后剩余了2个字节
         那么此时提取第二个字节的低4bit
         *(text+1) = yyyy yyyy
          *(text+1)<<2 = yy yyyy 00
          *(text+1)<<2 & 0x3c = (yy yyyy 00) & (0011 1100) = 00yy yy00
        */
        *(point++) = (inlen==1?'=':b64_alphabet[ *(text+1)<<2 & 0x3c ] );
        /*
        获取转换后的第四个字节:
        此时转换后的第四个字节就是'='
        */
        *(point++) = '=';
    }
    *point = '\0';
    return buffer;
}

如果想了解更多base64加密解密可以上网查资料,或者看我的另外的文章,里面有实例:

https://blog.csdn.net/kongshuai19900505/article/details/79589877

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值