chc2203 发表于 2015-1-9 10:11:38

Base64编码原理详解及c++编码解码实现

Base64是一种基于64个可打印字符来表示二进制数据的表示方法。由于2的6次方等于64,所以每6个位元为一个单元,对应某个可打印字符。三个字节有24个位元,对应于4个Base64单元,即3个字节需要用4个可打印字符来表示。它可用来作为电子邮件的传输编码。在Base64中的可打印字符包括字母A-Z、a-z、数字0-9 ,这样共有62个字符,此外两个可打印符号在不同的系统中而不同。
举例解释:

转换前 101 0,1101 1011 10,10 0111 0110

转换后 0010101,1 00011011 00,101001 ,00110110

十进制 43 27 41 54

对应码表中的值 r b p 2

所以上面的24位编码,编码后的Base64值为 rbp2

解码同理,把 rbq2 的二进制位连接上再重组得到三个8位值,得出原码。

(解码只是编码的逆过程,在此我就不多说了,另外有关MIME的RFC还是有很多的,如果需要详细情况请自行查找。)

第一个字节,根据源字节的第一个字节处理。

规则:源第一字节右移两位,去掉低2位,高2位补零。

既:00 + 高6位

第二个字节,根据源字节的第一个字节和第二个字节联合处理。

规则如下,第一个字节高6位去掉左移四位,第二个字节右移四位

即:源第一字节低2位 + 源第2字节高4位

第三个字节,根据源字节的第二个字节和第三个字节联合处理,

规则第二个字节去掉高4位并左移两位(得高6位),第三个字节右移6位并去掉高6位(得低2位),相加即可

第四个字节,规则,源第三字节去掉高2位即可

根据base64的编码规则,每76个字符需要一个换行

// 用更接近于编程的思维来说,编码的过程是这样的:

//第一个字符通过右移2位获得第一个目标字符的Base64表位置,根据这个数值取到表上相应的字符,就是第一//个目标字符。

// 然后将第一个字符左移4位加上第二个字符右移4位,即获得第二个目标字符。

//再将第二个字符左移2位加上第三个字符右移6位,获得第三个目标字符。

//最后取第三个字符的右6位即获得第四个目标字符。

//在以上的每一个步骤之后,再把结果与 0x3F 进行 AND 位操作,就可以得到编码后的字符了。

可是等等……聪明的你可能会问到,原文的字节数量应该是3的倍数啊,如果这个条件不能满足的话,那该怎么办呢?

我们的解决办法是这样的:原文的字节不够的地方可以用全0来补足,转换时Base64编码用=号来代替。这就是为什么有些Base64编码会以一个或两个等号结束的原因,但等号最多只有两个。因为:

余数 = 原文字节数 MOD 3

所以余数任何情况下都只可能是0,1,2这三个数中的一个。如果余数是0的话,就表示原文字节数正好是3的倍数(最理想的情况啦)。如果是1的话,为了让Base64编码是3的倍数,就要补2个等号;同理,如果是2的话,就要补1个等号。



基于c++的base64编码解码函数:

#include <string>
std::string base64_encode(unsigned char const* , unsigned int len);
std::string base64_decode(std::string const& s);
////////////////
static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static inline bool is_base64(unsigned char c) {
    return (isalnum(c) || (c == '+') || (c == '/'));
}
std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) {
    std::string ret;
    int i = 0;
    int j = 0;
    unsigned char char_array_3;
    unsigned char char_array_4;
    while (in_len--) {
      char_array_3 = *(bytes_to_encode++);
      if (i == 3) {
            char_array_4 = (char_array_3 & 0xfc) >> 2;
            char_array_4 = ((char_array_3 & 0x03) << 4) + ((char_array_3 & 0xf0) >> 4);
            char_array_4 = ((char_array_3 & 0x0f) << 2) + ((char_array_3 & 0xc0) >> 6);
            char_array_4 = char_array_3 & 0x3f;
            for(i = 0; (i <4) ; i++)
                ret += base64_chars];
            i = 0;
      }
    }
    if (i)
    {
      for(j = i; j < 3; j++)
            char_array_3 = '\0';
      char_array_4 = (char_array_3 & 0xfc) >> 2;
      char_array_4 = ((char_array_3 & 0x03) << 4) + ((char_array_3 & 0xf0) >> 4);
      char_array_4 = ((char_array_3 & 0x0f) << 2) + ((char_array_3 & 0xc0) >> 6);
      char_array_4 = char_array_3 & 0x3f;
      for (j = 0; (j < i + 1); j++)
            ret += base64_chars];
      while((i++ < 3))
            ret += '=';
    }
    return ret;
}
std::string base64_decode(std::string const& encoded_string) {
    int in_len = encoded_string.size();
    int i = 0;
    int j = 0;
    int in_ = 0;
    unsigned char char_array_4, char_array_3;
    std::string ret;
    while (in_len-- && ( encoded_string != '=') && is_base64(encoded_string)) {
      char_array_4 = encoded_string; in_++;
      if (i ==4) {
            for (i = 0; i <4; i++)
                char_array_4 = base64_chars.find(char_array_4);
            char_array_3 = (char_array_4 << 2) + ((char_array_4 & 0x30) >> 4);
            char_array_3 = ((char_array_4 & 0xf) << 4) + ((char_array_4 & 0x3c) >> 2);
            char_array_3 = ((char_array_4 & 0x3) << 6) + char_array_4;
            for (i = 0; (i < 3); i++)
                ret += char_array_3;
            i = 0;
      }
    }
    if (i) {
      for (j = i; j <4; j++)
            char_array_4 = 0;
      for (j = 0; j <4; j++)
            char_array_4 = base64_chars.find(char_array_4);
      char_array_3 = (char_array_4 << 2) + ((char_array_4 & 0x30) >> 4);
      char_array_3 = ((char_array_4 & 0xf) << 4) + ((char_array_4 & 0x3c) >> 2);
      char_array_3 = ((char_array_4 & 0x3) << 6) + char_array_4;
      for (j = 0; (j < i - 1); j++) ret += char_array_3;
    }
    return ret;
}
页: [1]
查看完整版本: Base64编码原理详解及c++编码解码实现