Base64编码 C++ 版

来源:互联网 发布:姚明nba全明星赛数据 编辑:程序博客网 时间:2024/05/24 01:46

      最近做C/S项目,需要把xml数据作为字符串上传到服务器端。鉴于xml字符串可能在服务器端传送过程中破坏xml结构,因此决定在上传之前进行简单Base64加密。Base64编码的原理,详细请参见Base64维基百科。下面简单介绍相关知识。

       Base 64 Encoding有什么用?举个简单的例子,你使用SMTP协议 (Simple Mail Transfer Protocol 简单邮件传输协议)来发送邮件。因为这个协议是基于文本的协议,所以如果邮件中包含一幅图片,我们知道图片的存储格式是二进制数据(binary data),而非文本格式,我们必须将二进制的数据编码成文本格式,这时候Base 64 Encoding就派上用场了。

  (一)编码原理

  Base 64 Encoding 的编码原理是将每三个字节(byte)转换为四个字符,每个字符占6 bit。


  6 bit一共有64种组合方式,也就是说该编码共需要使用至少64种字符(后面我们还会介绍一个特殊字符 =)。Base 64 Encoding使用了从 A 到 Z、a 到 z、0 到 9、以及 + 和 / 这些字符(即[A-Za-z0-9+/])。


  假设我们有三个字节的数据,byte[] {1, 2, 3},用二进制表示为:

  00000001 | 00000010 | 00000011

  依据上面的原理,使用Basee 64 Encoding编码后结果应该为:

  000000 | 010000 | 001000 | 000011

  转换为十进制为 0 | 16 | 8 | 3,对照上面的表,编码后的文本为 AQID

  既然Base 64 Encoding将每三个字节转换为四个字符,那如果一幅图片的字节数不能被3整除该怎么办?

  如果剩余一个字节,该字节同样被转换为四个字符。第一个6 bit转换成一个字符,接下来2 bit转换成一个字符(注意这里是向右添加0),最后添加两个=字符。


  假设我们有四个字节的数据,byte[] {1, 2, 3, 4},用二进制表示为:

  00000001 | 00000010 | 00000011 | 00000100

  依据上面的原理,使用Basee 64 Encoding编码后结果应该为:

  000000 | 010000 | 001000 | 000011 | 000001 | 000000

  转换为十进制为 0 | 16 | 8 | 3 | 1 | 0,对照上面的表,编码后的文本为 AQIDBA==

  如果不能被3整除,而余下两个字节,编码方式类似剩余一个字节,同样是转换成四个字符,最后一个字符用=。


  假设我们有五个字节的数据,byte[] {1, 2, 3, 4, 5},用二进制表示为:

  00000001 | 00000010 | 00000011 | 00000100 | 00000101

  依据上面的原理,使用Basee 64 Encoding编码后结果应该为:

  000000 | 010000 | 001000 | 000011 | 000001 | 000000 | 010100

  转换为十进制为 0 | 16 | 8 | 3 | 1 | 0 | 20,对照上面的表,编码后的文本为 AQIDBAU=


    上网找了下相关类,发现了René Nyffenegger的文章《Encoding and decoding base64 with C++》,以下是原文。该实现简单易用。

The cpp file

/*    base64.cpp and base64.h   Copyright (C) 2004-2008 René Nyffenegger   This source code is provided 'as-is', without any express or implied   warranty. In no event will the author be held liable for any damages   arising from the use of this software.   Permission is granted to anyone to use this software for any purpose,   including commercial applications, and to alter it and redistribute it   freely, subject to the following restrictions:   1. The origin of this source code must not be misrepresented; you must not      claim that you wrote the original source code. If you use this source code      in a product, an acknowledgment in the product documentation would be      appreciated but is not required.   2. Altered source versions must be plainly marked as such, and must not be      misrepresented as being the original source code.   3. This notice may not be removed or altered from any source distribution.   René Nyffenegger rene.nyffenegger@adp-gmbh.ch*/#include "base64.h"#include <iostream>static const std::string base64_chars =              "ABCDEFGHIJKLMNOPQRSTUVWXYZ"             "abcdefghijklmnopqrstuvwxyz"             "0123456789+/";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[3];  unsigned char char_array_4[4];  while (in_len--) {    char_array_3[i++] = *(bytes_to_encode++);    if (i == 3) {      char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;      char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);      char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);      char_array_4[3] = char_array_3[2] & 0x3f;      for(i = 0; (i <4) ; i++)        ret += base64_chars[char_array_4[i]];      i = 0;    }  }  if (i)  {    for(j = i; j < 3; j++)      char_array_3[j] = '\0';    char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;    char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);    char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);    char_array_4[3] = char_array_3[2] & 0x3f;    for (j = 0; (j < i + 1); j++)      ret += base64_chars[char_array_4[j]];    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[4], char_array_3[3];  std::string ret;  while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {    char_array_4[i++] = encoded_string[in_]; in_++;    if (i ==4) {      for (i = 0; i <4; i++)        char_array_4[i] = base64_chars.find(char_array_4[i]);      char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);      char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);      char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];      for (i = 0; (i < 3); i++)        ret += char_array_3[i];      i = 0;    }  }  if (i) {    for (j = i; j <4; j++)      char_array_4[j] = 0;    for (j = 0; j <4; j++)      char_array_4[j] = base64_chars.find(char_array_4[j]);    char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);    char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);    char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];    for (j = 0; (j < i - 1); j++) ret += char_array_3[j];  }  return ret;}

The header file

#include <string>std::string base64_encode(unsigned char const* , unsigned int len);std::string base64_decode(std::string const& s);

The test file

#include "base64.h"#include <iostream>int main() {  const std::string s = "ADP GmbH\nAnalyse Design & Programmierung\nGesellschaft mit beschränkter Haftung" ;  std::string encoded = base64_encode(reinterpret_cast<const unsigned char*>(s.c_str()), s.length());  std::string decoded = base64_decode(encoded);  std::cout << "encoded: " << encoded << std::endl;  std::cout << "decoded: " << decoded << std::endl;  return 0;}




原创粉丝点击