zoukankan      html  css  js  c++  java
  • Base64原理与实现

    Base64编码说明
      Base64编码要求把3个8位字节(3*8=24)转化为4个6位的字节(4*6=24),之后在6位的前面补两个0,形成8位一个字节的形式。 如果剩下的字符不足3个字节,则用0填充,输出字符使用'=',因此编码后输出的文本末尾可能会出现1或2个'='。

      为了保证所输出的编码位可读字符,Base64制定了一个编码表,以便进行统一转换。编码表的大小为2^6=64,这也是Base64名称的由来。

    转码过程举例:
      3*8=4*6
      内存1个字符占8位
      转前: s 1 3
      先转成ascii:对应 115 49 51
      2进制: 01110011 00110001 00110011
      6个一组(4组) 011100110011000100110011
      然后才有后面的 011100 110011 000100 110011
      然后计算机是8位8位的存数 6不够,自动就补两个高位0了
      所有有了 高位补0
      科学计算器输入 00011100 00110011 00000100 00110011
      得到 28 51 4 51
      查对下照表 c z E z

    Base64编码表

    码值字符   码值字符   码值字符   码值字符
    0 A 16 Q 32 g 48 w
    1 B 17 R 33 h 49 x
    2 C 18 S 34 i 50 y
    3 D 19 T 35 j 51 z
    4 E 20 U 36 k 52 0
    5 F 21 V 37 l 53 1
    6 G 22 W 38 m 54 2
    7 H 23 X 39 n 55 3
    8 I 24 Y 40 o 56 4
    9 J 25 Z 41 p 57 5
    10 K 26 a 42 q 58 6
    11 L 27 b 43 r 59 7
    12 M 28 c 44 s 60 8
    13 N 29 d 45 t 61 9
    14 O 30 e 46 u 62 +
    15 P 31 f 47 v 63 /

    C++实现:

    base64.h

     1 #ifndef _BASE64_HH  
     2 #define _BASE64_HH  
     3 
     4 #ifdef __cplusplus  
     5 extern "C" {  
     6 #endif    //__cplusplus 
     7 
     8 unsigned char* base64Decode(char* pszInput, unsigned int& iReturnSize, bool trimTrailingZeros = true);
     9 
    10 char* base64Encode(char const* origSigned, unsigned iOrigLength); 
    11 
    12 #ifdef __cplusplus  
    13 }  
    14 #endif  //__cplusplus 
    15   
    16 #endif    //_BASE64_HH

    base64.cpp

      1 #include "base64.h"  
      2 #include <string.h>  
      3 
      4 static char base64DecodeTable[65];  
      5 //初始化编码对照表
      6 static const char base64Char[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";  
      7 
      8 char* strDupSize(char const* str)   
      9 {  
     10     if (str == NULL) return NULL;  
     11     size_t len = strlen(str) + 1;  
     12     char* copy = new char[len];  
     13   
     14     return copy;  
     15 }
     16 
     17 //初始化解码对照表
     18 static void initBase64DecodeTable()  
     19 {   
     20   for (int i = 0; i < 65; ++i) 
     21       base64DecodeTable[i] = (char)0x80;   // default value: invalid  
     22   
     23   for (int i = 'A'; i <= 'Z'; ++i) 
     24       base64DecodeTable[i] = 0 + (i - 'A');  
     25   for (int i = 'a'; i <= 'z'; ++i) 
     26       base64DecodeTable[i] = 26 + (i - 'a');  
     27   for (int i = '0'; i <= '9'; ++i) 
     28       base64DecodeTable[i] = 52 + (i - '0');  
     29   base64DecodeTable[(unsigned char)'+'] = 62;  
     30   base64DecodeTable[(unsigned char)'/'] = 63;  
     31   base64DecodeTable[(unsigned char)'='] = 64;  //0x40
     32 }  
     33 
     34 // 解码
     35 unsigned char* base64Decode(char* pszInput, unsigned int& iReturnSize, bool trimTrailingZeros)   
     36 {  
     37     static bool haveInitedBase64DecodeTable = false;  
     38     if (!haveInitedBase64DecodeTable)  
     39     {  
     40         initBase64DecodeTable();  
     41         haveInitedBase64DecodeTable = true;  
     42     }  
     43 
     44     unsigned char* pszOutput = new unsigned char[strlen(pszInput)];
     45     int k = 0;  
     46     /*******************************************************************************************
     47      *技巧:先减去3 ---in case "pszInput" is not a multiple of 4 bytes (although it should be) *
     48      *      个人觉得这里不用做处理,因为编码时候已经做过处理,密文肯定为4的整数倍               *
     49      *******************************************************************************************/
     50     int const jMax = strlen(pszInput) - 3;  
     51 
     52     //将密文四个字节为一组,每组解码为三个字节
     53     for (int j = 0; j < jMax; j += 4)   
     54     {  
     55         char inTmp[4], outTmp[4];  
     56         for (int i = 0; i < 4; ++i)   
     57         {  
     58             inTmp[i] = pszInput[i+j];  
     59             outTmp[i] = base64DecodeTable[(unsigned char)inTmp[i]];  
     60             if ((outTmp[i]&0x40) != 0)    //如果遇到'=',将其视为结束字符
     61                 outTmp[i] = 0x00; 
     62         }  
     63 
     64         pszOutput[k++] = (outTmp[0]<<2) | (outTmp[1]>>4);  
     65         pszOutput[k++] = (outTmp[1]<<4) | (outTmp[2]>>2);  
     66         pszOutput[k++] = (outTmp[2]<<6) | outTmp[3];  
     67     }  
     68 
     69     if (trimTrailingZeros)   
     70     {  
     71         while (k > 0 && pszOutput[k-1] == '0') 
     72             --k;  
     73     }  
     74     iReturnSize = k;  
     75     unsigned char* result = new unsigned char[iReturnSize];  
     76     memset(result, 0, iReturnSize);
     77     memmove(result, pszOutput, iReturnSize);  
     78     delete[] pszOutput;  
     79     return result;  
     80 }  
     81 
     82 // 编码
     83 char* base64Encode(char const* origSigned, unsigned iOrigLength)   
     84 {  
     85   unsigned char const* orig = (unsigned char const*)origSigned;  
     86   if (orig == NULL) 
     87       return NULL;
     88 
     89   unsigned const iNumResultBytes = 4*(iOrigLength/3 + (iOrigLength%3 ? 1 : 0));
     90   char* result = new char[iNumResultBytes + 1]; 
     91   
     92   //源码三个字节为一组,编码后将三个字节变为四个字节
     93   unsigned i;  
     94   for (i = 0; i < iOrigLength/3; ++i)   
     95   {  
     96     // 取源码的第一个字节的前六位,前面加两个零生成第一个字节
     97     result[4*i+0] = base64Char[(orig[3*i]>>2) & 0x3F];    
     98     // 取源码的第一个字节的后两位和第二个字节的前四位,前面补两个零生成第二个字节
     99     result[4*i+1] = base64Char[((orig[3*i]<<4) | (orig[3*i+1]>>4)) & 0x3F];
    100     // 取源码的第二个字节的后四位和第三个字节的前两位,前面补两个零生成第三个字节
    101     result[4*i+2] = base64Char[((orig[3*i+1]<<2) | (orig[3*i+2]>>6)) & 0x3F];
    102     // 取源码的第三个字节的后六位,前面补两个零生成第四个字节
    103     result[4*i+3] = base64Char[orig[3*i+2]&0x3F];                                
    104   }
    105   //不足三个字节的最后补'='字符,补足三个字节
    106   if (iOrigLength%3)
    107   {
    108     result[4*i+0] = base64Char[(orig[3*i]>>2) & 0x3F];
    109     if (iOrigLength%3 == 2)
    110     {
    111       result[4*i+1] = base64Char[((orig[3*i]<<4) | (orig[3*i+1]>>4))&0x3F];  
    112       result[4*i+2] = base64Char[(orig[3*i+1]<<2)&0x3C];  
    113     }
    114     else
    115     {
    116       result[4*i+1] = base64Char[((orig[3*i])<<4)&0x3F];
    117       result[4*i+2] = '=';
    118     }
    119     result[4*i+3] = '=';
    120   }
    121 
    122   result[iNumResultBytes] = '';  
    123   return result;  
    124 }  

    测试代码main.cpp

     1 #include "base64.h"
     2 #include <iostream>
     3 
     4 using namespace std;
     5 
     6 int main()
     7 {
     8     cout << "请输入要转换的字符串(支持中文):" << endl;
     9     char szStrOrigin[256];
    10     scanf("%s", szStrOrigin);
    11     unsigned int iReturnSize;
    12     cout << "编码之前字符串:" << szStrOrigin << endl;
    13     char *pEncodeStr = base64Encode(szStrOrigin, strlen(szStrOrigin));
    14     cout << "编码之后字符串:" <<  pEncodeStr << endl;
    15     unsigned char *pDecodeStr = base64Decode(pEncodeStr, iReturnSize);
    16     cout << "解码之后字符串:" << pDecodeStr << endl;
    17     system("pause");
    18 }

    运行结果:

     

  • 相关阅读:
    ubuntu 11.04 Gnome 恢复默认的任务栏面板
    (转载)学习腾讯的产品管理之道
    (转载)项目管理之外谈项目管理
    windows 下键盘映射
    该留意的文章
    一些常用的工具
    ubuntu 11.04 old sources.list
    一个css3流程导图
    echarts雷达图
    highcharts图表
  • 原文地址:https://www.cnblogs.com/dongsheng/p/4379933.html
Copyright © 2011-2022 走看看