Base 64编码
目前,许多手机病毒使用URL都采用Base64编码加密下载地址,下面我们了解一下Base64编码.
The Base64 Alphabet:
索引 | 对应字符 | 索引 | 对应字符 | 索引 | 对应字符 | 索引 | 对应字符 |
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 | (pad) | = |
14 | O | 31 | f | 48 | w | ||
15 | P | 32 | g | 49 | x | ||
16 | Q | 33 | h | 50 | y |
Base64编码的算法是:
1. 把3个8位字节(3*8 = 24)转化成4个6位的字节(4*6 = 24),之后在六位的前面补两个0,形成一个8位一个字节的形式.
2. 每76个字符加一个换行符
3. 最后的结束符也要处理
例子:
转换前: 11010101 11000101 00110011
方法:从左开始顺序选6个数之后,在这个六位数的前面添加两个0, 之后再选出6个,再添加两个0,一次类推,直到24个二进制数全部被选完.
转换后: 00110101 00011100 00010100 00110011
对应10进制: 53 34 20 51
查阅上The Base64 Alphabet表得到: 1iuz
注意: Base64将3个字节转变为4个字节,因此,编码后的代码量(以字节为单位,下同)约比编码前的代码量多了1/3。之所以说是“约”,是因为如果代码量正好是3的整数倍,那么自然是多了1/3,为了解决这个问题.(看下文引用部分)。
编程的思维:
1. 第一个字符通过右移2位获得第一个目标字符的Base64表位置,根据这个数值取到表上相应的字符,就是第一个目标字符.
2. 然后将第一个字符左移4位加上第二个字符右移4位,即获得第二个目标字符.
3. 再将第二个字符左移2位加上第三个字符右移6位,获得第三个目标字符.
4. 最后取第三个字符的右6位即获得第四个目标字符.
5. 在以上的每一个步骤之后,再把结果与 0x3F 进行 AND 位操作,就可以得到编码后的字符了.
注意:原文的字节数量应该是3的倍数,如果这个条件不能满足的话,我们做一下处理。
解决办法:原文的字节不够的地方可以用全0来补足,转换时Base64编码用=号来代替。但等号最多只有两个。因为:
余数 = 原文字节数 MOD 3所以余数任何情况下都只可能是0,1,2这三个数中的一个.如果余数是0的话,就表示原文字节数正好是3的倍数(最理想的情况啦).如果是1的话,为了让Base64编码是3的倍数,就要补2个等号.如果是2的话,就要补1个等号.
C++ 源代码
------------------------------------------------.h--------------------------------------------------------
#include <string> using namespace std; class ZBase64 { public: /*编码 DataByte [in]输入的数据长度,以字节为单位 */ string Encode(const unsigned char* Data,int DataByte); /*解码 DataByte [in]输入的数据长度,以字节为单位 OutByte [out]输出的数据长度,以字节为单位,请不要通过返回值计算 输出数据的长度 */ string Decode(const char* Data,int DataByte,int& OutByte); }; ------------------------------------------------.cpp-------------------------------------------------------- #include "stdAfx.h" #include "ZBase64.h" string ZBase64::Encode(const unsigned char* Data,int DataByte) { //编码表 const char EncodeTable[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; //返回值 string strEncode; unsigned char Tmp[4]={0}; int LineLength=0; for(int i=0;i<(int)(DataByte / 3);i++) { Tmp[1] = *Data++; Tmp[2] = *Data++; Tmp[3] = *Data++; strEncode+= EncodeTable[Tmp[1] >> 2]; strEncode+= EncodeTable[((Tmp[1] << 4) | (Tmp[2] >> 4)) & 0x3F]; strEncode+= EncodeTable[((Tmp[2] << 2) | (Tmp[3] >> 6)) & 0x3F]; strEncode+= EncodeTable[Tmp[3] & 0x3F]; if(LineLength+=4,LineLength==76) {strEncode+="\r\n";LineLength=0;} } //对剩余数据进行编码 int Mod=DataByte % 3; if(Mod==1) { Tmp[1] = *Data++; strEncode+= EncodeTable[(Tmp[1] & 0xFC) >> 2]; strEncode+= EncodeTable[((Tmp[1] & 0x03) << 4)]; strEncode+= "=="; } else if(Mod==2) { Tmp[1] = *Data++; Tmp[2] = *Data++; strEncode+= EncodeTable[(Tmp[1] & 0xFC) >> 2]; strEncode+= EncodeTable[((Tmp[1] & 0x03) << 4) | ((Tmp[2] & 0xF0) >> 4)]; strEncode+= EncodeTable[((Tmp[2] & 0x0F) << 2)]; strEncode+= "="; } return strEncode; } string ZBase64::Decode(const char* Data,int DataByte,int& OutByte) { //解码表 const char DecodeTable[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, // '+' 0, 0, 0, 63, // '/' 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // '0'-'9' 0, 0, 0, 0, 0, 0, 0, 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, // 'A'-'Z' 0, 0, 0, 0, 0, 0, 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, // 'a'-'z' }; //返回值 string strDecode; int nValue; int i= 0; while (i < DataByte) { if (*Data != '\r' && *Data!='\n') { nValue = DecodeTable[*Data++] << 18; nValue += DecodeTable[*Data++] << 12; strDecode+=(nValue & 0x00FF0000) >> 16; OutByte++; if (*Data != '=') { nValue += DecodeTable[*Data++] << 6; strDecode+=(nValue & 0x0000FF00) >> 8; OutByte++; if (*Data != '=') { nValue += DecodeTable[*Data++]; strDecode+=nValue & 0x000000FF; OutByte++; } } i += 4; } else// 回车换行,跳过 { Data++; i++; } } return strDecode; }