• Base64编码和解码算法


    Base64么新鲜的算法了。只是假设你没从事过页面开发(或者说动态页面开发。尤其是邮箱服务),你都不怎么了解过,仅仅是听起来非常熟悉。

    对于黑客来说,Base64与MD5算法有着相同的位置。由于电子邮箱(e-mail)正文就是base64编码的。

    那么。我们就一起来深入的探讨一下这个东东吧。

     

    对于一种算法,与其问“它是什么?”,不如问“它实现了什么?”

    Base64实现了:将随意字节转为可读字符的编码。

    我们知道。除了页面上的文本,计算机中的数据还有非常多是不可见的。那么我们再扯一扯编码的问题吧。

     

    通俗的说,编码就是给某个文字符号边上一个数字序号,计算机在现实这个文字符号(字符)的时候,依据这个序号到字库中查找相应的点阵或矢量数据,

    在显示器上“画”出来。(关于点阵和矢量我们就不扯了。不然就真的太远了。

     

    起初的字符编码,没有把汉字、日文、朝鲜文和其它文字包含在内,仅仅有26个英文字母的大写和小写和10个阿拉伯数字。加上一些控制字符和空格,用一个字节

    就行全然的编码了。(不要告诉我你不知道2的7次方和2的8次方是多少,一个技术人员为这种问题困扰简直是一种耻辱。)

     

    然而。世界上除了文字还有数据。比方图片、压缩文件、程序等等都是二进制文件。这些文件一样以字节为单位存储数据。这些字节往往不不过2的7次方以内

    的可显示的文字字符编码,还有可能是大于127(有符号数小于0)的字节,这些字节没办法用字符显示出来,Base64就是通过某种算法将他们显示出来。

     

    *那么,Base64加密是安全的吗?

    没有绝对安全的加密。Base64不是为了安全,而是为了显示。并且Base64是可逆的。也就是说。通过简单的解密就能得到原文。事实上即便是不可逆的MD5算法。

    也能够通过明文数据库找出可能的原文(睡到知道e10adc3949ba59abbe56e057f20f883e的原文就是123456)。

     

    *那么,Base64是怎么实现的呢?

    事实上非常easy,只是为了URL等特殊用处,Base64选择了下面64个字符作为密文显示,着64个字符都是可显示的,他们是:

    ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

    假设密文有不属于他们的字符,那么不是Base64编码或者是山寨版的。

     

    一眼看去就知道是26个字母大写和小写和数字,加上“+”“/”两个符号。“?

    *-”因为正則表達式的问题,没有选用,而空格和回车这些是不能显示的。

    Base64处理的过程是,以3个字节为一组(3个字节就是24位嘛),每6位扩展成8位得到4个字节(就是32位):

    11111111 11111111 11111111 -> 111111 111111 111111 111111 -> 00111111 00111111 00111111 00111111

    那么,得到的每个字节,最大也就是2的6次方。

    或许你说:哇,小于2的7次方,能够显示了。

    事实上不是,得到的这2的6次方式上面那一串字符的索引,也就是说每一个字节的值仅仅是代表它在密文表中的位置。比方

    字符“a”的编码是97。 用16进制表示是0x61(VB表示为&H61)。二进制:01100001,由于不足3位。补0得到 00011000 00010000 000……

    前两个字节是十进制的24 和 16,那么相应那一串字符中的第24个字符和第16个字符为:YQ(索引从0開始算),那么单独“a”的Base64编码为

    YQ==(不足3为的每一个字符直接转为“=”)。简单吧!

     

    有了算法,解码的过程就各位聪明特达的程序猿取思考思考吧,最后C/C++版的编码解码代码贴上。

    1. /****************************************** 
    2.   Base64编码解码算法 C语言源码 
    3.   by 虎胆游侠 http://blog.csdn.net/prsniper 
    4. ******************************************/  
    5. #include <stdio.h>    //注意哦,VC中""是当前路径。<>是系统路径  
    6. #include <windows.h>  
    7.   
    8. const char BASE_CODE[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";  
    9.   
    10. //编码,參数:要编码的字符串指针,解码后存放的位置(编码字串长度的4/3),要编码的字符串长度 ->返回结果长度  
    11. int fnBase64Encode(char *lpString, char *lpBuffer, int sLen)   
    12. {   register int vLen = 0;  //寄存器局部变量,提速  
    13.     while(sLen > 0)      //处理整个字符串  
    14.     {   *lpBuffer++ = BASE_CODE[(lpString[0] >> 2 ) & 0x3F];  //右移两位,与00111111是防止溢出,自加  
    15.         if(sLen > 2) //够3个字符  
    16.         {   *lpBuffer++ = BASE_CODE[((lpString[0] & 3) << 4) | (lpString[1] >> 4)];  
    17.             *lpBuffer++ = BASE_CODE[((lpString[1] & 0xF) << 2) | (lpString[2] >> 6)];  
    18.             *lpBuffer++ = BASE_CODE[lpString[2] & 0x3F];  
    19.         }else  
    20.         {   switch(sLen)    //追加“=”  
    21.             {   case 1:  
    22.                     *lpBuffer ++ = BASE_CODE[(lpString[0] & 3) << 4 ];  
    23.                     *lpBuffer ++ = '=';  
    24.                     *lpBuffer ++ = '=';  
    25.                     break;  
    26.                 case 2:  
    27.                     *lpBuffer ++ = BASE_CODE[((lpString[0] & 3) << 4) | (lpString[1] >> 4)];  
    28.                     *lpBuffer ++ = BASE_CODE[((lpString[1] & 0x0F) << 2) | (lpString[2] >> 6)];  
    29.                     *lpBuffer ++ = '=';  
    30.                     break;  
    31.             }  
    32.         }  
    33.         lpString += 3;  
    34.         sLen -= 3;  
    35.         vLen +=4;  
    36.     }  
    37.     *lpBuffer = 0;  
    38.     return vLen;  
    39. }  
    40.   
    41. //子函数 - 取密文的索引  
    42. inline char GetCharIndex(char c) //内联函数能够省去函数调用过程。提速  
    43. {   if((c >= 'A') && (c <= 'Z'))  
    44.     {   return c - 'A';  
    45.     }else if((c >= 'a') && (c <= 'z'))  
    46.     {   return c - 'a' + 26;  
    47.     }else if((c >= '0') && (c <= '9'))  
    48.     {   return c - '0' + 52;  
    49.     }else if(c == '+')  
    50.     {   return 62;  
    51.     }else if(c == '/')  
    52.     {   return 63;  
    53.     }else if(c == '=')  
    54.     {   return 0;  
    55.     }  
    56.     return 0;  
    57. }  
    58.   
    59. //解码,參数:结果,密文,密文长度  
    60. int fnBase64Decode(char *lpString, char *lpSrc, int sLen)   //解码函数  
    61. {   static char lpCode[4];  
    62.     register int vLen = 0;  
    63.     if(sLen % 4)        //Base64编码长度必然是4的倍数,包含'='  
    64.     {   lpString[0] = '';  
    65.         return -1;  
    66.     }  
    67.     while(sLen > 2)      //不足三个字符。忽略  
    68.     {   lpCode[0] = GetCharIndex(lpSrc[0]);  
    69.         lpCode[1] = GetCharIndex(lpSrc[1]);  
    70.         lpCode[2] = GetCharIndex(lpSrc[2]);  
    71.         lpCode[3] = GetCharIndex(lpSrc[3]);  
    72.   
    73.         *lpString++ = (lpCode[0] << 2) | (lpCode[1] >> 4);  
    74.         *lpString++ = (lpCode[1] << 4) | (lpCode[2] >> 2);  
    75.         *lpString++ = (lpCode[2] << 6) | (lpCode[3]);  
    76.   
    77.         lpSrc += 4;  
    78.         sLen -= 4;  
    79.         vLen += 3;  
    80.     }  
    81.     return vLen;  
    82. }  
    83.   
    84. void main() //主函数,測试函数  
    85. {   char s[] = "a", str[32];  
    86.     int l = strlen(s);  
    87.     int i = fnBase64Encode(s, str, l);  
    88.     printf("fnBase64Encode("%s", str, %d) = "%s"; ", s, l, str);  
    89.     l = fnBase64Decode(s, str, i);  
    90.     printf("fnBase64Decode("%s", s, %d) = "%s"; ", str, i, s);  
    91. }  


    编译为控制台应用程序,执行如图:

    Base64编解码源代码执行效果

    原文地址:http://blog.csdn.net/prsniper/article/details/7097643

    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    pg之使用pg_upgrade进行大版本升级 规格严格
    Normalization(标准化)的一些记录
    深度学习面试的一些题目
    几篇关于Transformer和Bert讲得不错的文章
    两篇关于情感方面的文章,还不错
    Focal Loss的学习和理解
    一篇关于PLM和NLG领域的综述
    NLP一篇文章的读书笔记
    情感分析读书笔记
    学习率和训练过程的关系
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/4844592.html
Copyright © 2020-2023  润新知