c++ base64

fragmento de decodificación base64 en c++



(8)

Aquí está mi modificación de la implementación que fue escrita originalmente por René Nyffenegger . ¿Y por qué lo he modificado? Bueno, porque no me pareció apropiado que debería trabajar con datos binarios almacenados dentro del objeto std::string ;)

base64.h :

#ifndef _BASE64_H_ #define _BASE64_H_ #include <vector> #include <string> typedef unsigned char BYTE; std::string base64_encode(BYTE const* buf, unsigned int bufLen); std::vector<BYTE> base64_decode(std::string const&); #endif

base64.cpp :

#include "base64.h" #include <iostream> static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; static inline bool is_base64(BYTE c) { return (isalnum(c) || (c == ''+'') || (c == ''/'')); } std::string base64_encode(BYTE const* buf, unsigned int bufLen) { std::string ret; int i = 0; int j = 0; BYTE char_array_3[3]; BYTE char_array_4[4]; while (bufLen--) { char_array_3[i++] = *(buf++); 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::vector<BYTE> base64_decode(std::string const& encoded_string) { int in_len = encoded_string.size(); int i = 0; int j = 0; int in_ = 0; BYTE char_array_4[4], char_array_3[3]; std::vector<BYTE> 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.push_back(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.push_back(char_array_3[j]); } return ret; }

Aquí está el uso:

std::vector<BYTE> myData; ... std::string encodedData = base64_encode(&myData[0], myData.size()); std::vector<BYTE> decodedData = base64_decode(encodedData);

Espero que alguien encuentre útil esta respuesta ^^

¿Alguien tiene un fragmento de código de decodificación base64 disponible gratuitamente en c ++?


Creo que este funciona mejor:

#include <string> #include <cstring> static const char* B64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static const int B64index [256] = { 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, 63, 62, 62, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 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, 0, 0, 0, 0, 63, 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 }; std::string b64encode(const void* data, const size_t len) { unsigned char* p = (unsigned char*)data; size_t d = len % 3; std::string str64(4 * (int(d > 0) + len / 3), ''=''); for (size_t i = 0, j = 0; i < len - d; i += 3) { int n = int(p[i]) << 16 | int(p[i + 1]) << 8 | p[i + 2]; str64[j++] = B64chars[n >> 18]; str64[j++] = B64chars[n >> 12 & 0x3F]; str64[j++] = B64chars[n >> 6 & 0x3F]; str64[j++] = B64chars[n & 0x3F]; } if (d--) /// padding { int n = d ? int(p[len - 2]) << 8 | p[len - 1] : p[len - 1]; str64[str64.size() - 2] = d ? B64chars[(n & 0xF) << 2] : ''=''; str64[str64.size() - 3] = d ? B64chars[n >> 4 & 0x03F] : B64chars[(n & 3) << 4]; str64[str64.size() - 4] = d ? B64chars[n >> 10] : B64chars[n >> 2]; } return str64; } std::string b64decode(const void* data, const size_t len) { unsigned char* p = (unsigned char*)data; int pad = len > 0 && (len % 4 || p[len - 1] == ''=''); const size_t L = ((len + 3) / 4 - pad) * 4; std::string str(L / 4 * 3 + pad, ''/0''); for (size_t i = 0, j = 0; i < L; i += 4) { int n = B64index[p[i]] << 18 | B64index[p[i + 1]] << 12 | B64index[p[i + 2]] << 6 | B64index[p[i + 3]]; str[j++] = n >> 16; str[j++] = n >> 8 & 0xFF; str[j++] = n & 0xFF; } if (pad) { int n = B64index[p[L]] << 18 | B64index[p[L + 1]] << 12; str[str.size() - 1] = n >> 16; if (len > L + 2 && p[L + 2] != ''='') { n |= B64index[p[L + 2]] << 6; str.push_back(n >> 8 & 0xFF); } } return str; } std::string b64decode(const std::string& str64) { return b64decode(str64.c_str(), str64.size()); }

Gracias a @Jens Alfke por señalar un problema de rendimiento, hice algunas modificaciones a esta publicación anterior. Ahora esto funciona mucho más rápido que antes. La principal ventaja es que también puede manejar datos corruptos sin problemas.


Hay varios fragmentos aquí. Sin embargo, este es compacto, eficiente y amigable con c ++ 11:

static std::string base64_encode(const std::string &in) { std::string out; int val=0, valb=-6; for (uchar c : in) { val = (val<<8) + c; valb += 8; while (valb>=0) { out.push_back("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(val>>valb)&0x3F]); valb-=6; } } if (valb>-6) out.push_back("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[((val<<8)>>(valb+8))&0x3F]); while (out.size()%4) out.push_back(''=''); return out; } static std::string base64_decode(const std::string &in) { std::string out; std::vector<int> T(256,-1); for (int i=0; i<64; i++) T["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[i]] = i; int val=0, valb=-8; for (uchar c : in) { if (T[c] == -1) break; val = (val<<6) + T[c]; valb += 6; if (valb>=0) { out.push_back(char((val>>valb)&0xFF)); valb-=8; } } return out; }


Mi variación en la respuesta de @DaedalusAlpha. Evita copiar los parámetros a expensas de un par de pruebas.

Utiliza uint8_t en lugar de BYTE.

Agrega algunas funciones útiles para tratar con cadenas, aunque generalmente los datos de entrada son binarios y pueden tener cero bytes adentro, por lo que normalmente no deberían manipularse como una cadena (lo que a menudo implica datos terminados en nulo).

También agrega algunos lanzamientos para corregir las advertencias del compilador (al menos en GCC, aún no lo he pasado por MSVC).

parte de base64.hpp:

void base64_encode(string & out, const vector<uint8_t>& buf); void base64_encode(string & out, const uint8_t* buf, size_t bufLen); void base64_encode(string & out, string const& buf); void base64_decode(vector<uint8_t> & out, string const& encoded_string); // use this if you know the output should be a valid string void base64_decode(string & out, string const& encoded_string);

base64.cpp:

static const uint8_t from_base64[128] = { // 8 rows of 16 = 128 // note: only require 123 entries, as we only lookup for <= z , which z=122 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 62, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 0, 255, 255, 255, 255, 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, 255, 255, 255, 255, 63, 255, 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, 255, 255, 255, 255, 255 }; static const char to_base64[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; void base64_encode(string & out, string const& buf) { if (buf.empty()) base64_encode(out, NULL, 0); else base64_encode(out, reinterpret_cast<uint8_t const*>(&buf[0]), buf.size()); } void base64_encode(string & out, std::vector<uint8_t> const& buf) { if (buf.empty()) base64_encode(out, NULL, 0); else base64_encode(out, &buf[0], buf.size()); } void base64_encode(string & ret, uint8_t const* buf, size_t bufLen) { // Calculate how many bytes that needs to be added to get a multiple of 3 size_t missing = 0; size_t ret_size = bufLen; while ((ret_size % 3) != 0) { ++ret_size; ++missing; } // Expand the return string size to a multiple of 4 ret_size = 4*ret_size/3; ret.clear(); ret.reserve(ret_size); for (size_t i = 0; i < ret_size/4; ++i) { // Read a group of three bytes (avoid buffer overrun by replacing with 0) const size_t index = i*3; const uint8_t b3_0 = (index+0 < bufLen) ? buf[index+0] : 0; const uint8_t b3_1 = (index+1 < bufLen) ? buf[index+1] : 0; const uint8_t b3_2 = (index+2 < bufLen) ? buf[index+2] : 0; // Transform into four base 64 characters const uint8_t b4_0 = ((b3_0 & 0xfc) >> 2); const uint8_t b4_1 = ((b3_0 & 0x03) << 4) + ((b3_1 & 0xf0) >> 4); const uint8_t b4_2 = ((b3_1 & 0x0f) << 2) + ((b3_2 & 0xc0) >> 6); const uint8_t b4_3 = ((b3_2 & 0x3f) << 0); // Add the base 64 characters to the return value ret.push_back(to_base64[b4_0]); ret.push_back(to_base64[b4_1]); ret.push_back(to_base64[b4_2]); ret.push_back(to_base64[b4_3]); } // Replace data that is invalid (always as many as there are missing bytes) for (size_t i = 0; i != missing; ++i) ret[ret_size - i - 1] = ''=''; } template <class Out> void base64_decode_any( Out & ret, std::string const& in) { typedef typename Out::value_type T; // Make sure the *intended* string length is a multiple of 4 size_t encoded_size = in.size(); while ((encoded_size % 4) != 0) ++encoded_size; const size_t N = in.size(); ret.clear(); ret.reserve(3*encoded_size/4); for (size_t i = 0; i < encoded_size; i += 4) { // Note: ''z'' == 122 // Get values for each group of four base 64 characters const uint8_t b4_0 = ( in[i+0] <= ''z'') ? from_base64[static_cast<uint8_t>(in[i+0])] : 0xff; const uint8_t b4_1 = (i+1 < N and in[i+1] <= ''z'') ? from_base64[static_cast<uint8_t>(in[i+1])] : 0xff; const uint8_t b4_2 = (i+2 < N and in[i+2] <= ''z'') ? from_base64[static_cast<uint8_t>(in[i+2])] : 0xff; const uint8_t b4_3 = (i+3 < N and in[i+3] <= ''z'') ? from_base64[static_cast<uint8_t>(in[i+3])] : 0xff; // Transform into a group of three bytes const uint8_t b3_0 = ((b4_0 & 0x3f) << 2) + ((b4_1 & 0x30) >> 4); const uint8_t b3_1 = ((b4_1 & 0x0f) << 4) + ((b4_2 & 0x3c) >> 2); const uint8_t b3_2 = ((b4_2 & 0x03) << 6) + ((b4_3 & 0x3f) >> 0); // Add the byte to the return value if it isn''t part of an ''='' character (indicated by 0xff) if (b4_1 != 0xff) ret.push_back( static_cast<T>(b3_0) ); if (b4_2 != 0xff) ret.push_back( static_cast<T>(b3_1) ); if (b4_3 != 0xff) ret.push_back( static_cast<T>(b3_2) ); } } void base64_decode(vector<uint8_t> & out, string const& encoded_string) { base64_decode_any(out, encoded_string); } void base64_decode(string & out, string const& encoded_string) { base64_decode_any(out, encoded_string); }


Una pequeña variación con una tabla de búsqueda más compacta y usando las características de c ++ 17:

std::string base64_decode(const std::string_view in) { // table from ''+'' to ''z'' const uint8_t lookup[] = { 62, 255, 62, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 0, 255, 255, 255, 255, 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, 255, 255, 255, 255, 63, 255, 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}; static_assert(sizeof(lookup) == ''z'' - ''+'' + 1); std::string out; int val = 0, valb = -8; for (uint8_t c : in) { if (c < ''+'' || c > ''z'') break; c -= ''+''; if (lookup[c] >= 64) break; val = (val << 6) + lookup[c]; valb += 6; if (valb >= 0) { out.push_back(char((val >> valb) & 0xFF)); valb -= 8; } } return out; }

Si no tiene std :: string_view, intente en su lugar std :: experimental :: string_view.


Usando base-n mini lib, puede hacer lo siguiente:

some_data_t in[] { ... }; constexpr int len = sizeof(in)/sizeof(in[0]); std::string encoded; bn::encode_b64(in, in + len, std::back_inserter(encoded)); some_data_t out[len]; bn::decode_b64(encoded.begin(), encoded.end(), out);

La API es genérica, basada en iteradores.

Divulgación: soy el autor.


Google es tu amigo

Aquí está la implementación desde esa página:

/* 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 [email protected] */ 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; }


De acuerdo con this excelente comparación realizada por GaspardP, no elegiría esta solución. No es lo peor, pero tampoco es lo mejor. Lo único que funciona es que es posiblemente más fácil de entender.

Encontré que las otras dos respuestas son bastante difíciles de entender. También producen algunas advertencias en mi compilador y el uso de una función de búsqueda en la parte de decodificación debería dar como resultado una eficacia bastante mala. Así que decidí hacer mi propia versión.

Encabezamiento:

#ifndef _BASE64_H_ #define _BASE64_H_ #include <vector> #include <string> typedef unsigned char BYTE; class Base64 { public: static std::string encode(const std::vector<BYTE>& buf); static std::string encode(const BYTE* buf, unsigned int bufLen); static std::vector<BYTE> decode(std::string encoded_string); }; #endif

Cuerpo:

static const BYTE from_base64[] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 62, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 255, 255, 255, 255, 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, 255, 255, 255, 255, 63, 255, 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, 255, 255, 255, 255, 255}; static const char to_base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; std::string Base64::encode(const std::vector<BYTE>& buf) { if (buf.empty()) return ""; // Avoid dereferencing buf if it''s empty return encode(&buf[0], (unsigned int)buf.size()); } std::string Base64::encode(const BYTE* buf, unsigned int bufLen) { // Calculate how many bytes that needs to be added to get a multiple of 3 size_t missing = 0; size_t ret_size = bufLen; while ((ret_size % 3) != 0) { ++ret_size; ++missing; } // Expand the return string size to a multiple of 4 ret_size = 4*ret_size/3; std::string ret; ret.reserve(ret_size); for (unsigned int i=0; i<ret_size/4; ++i) { // Read a group of three bytes (avoid buffer overrun by replacing with 0) size_t index = i*3; BYTE b3[3]; b3[0] = (index+0 < bufLen) ? buf[index+0] : 0; b3[1] = (index+1 < bufLen) ? buf[index+1] : 0; b3[2] = (index+2 < bufLen) ? buf[index+2] : 0; // Transform into four base 64 characters BYTE b4[4]; b4[0] = ((b3[0] & 0xfc) >> 2); b4[1] = ((b3[0] & 0x03) << 4) + ((b3[1] & 0xf0) >> 4); b4[2] = ((b3[1] & 0x0f) << 2) + ((b3[2] & 0xc0) >> 6); b4[3] = ((b3[2] & 0x3f) << 0); // Add the base 64 characters to the return value ret.push_back(to_base64[b4[0]]); ret.push_back(to_base64[b4[1]]); ret.push_back(to_base64[b4[2]]); ret.push_back(to_base64[b4[3]]); } // Replace data that is invalid (always as many as there are missing bytes) for (size_t i=0; i<missing; ++i) ret[ret_size - i - 1] = ''=''; return ret; } std::vector<BYTE> Base64::decode(std::string encoded_string) { // Make sure string length is a multiple of 4 while ((encoded_string.size() % 4) != 0) encoded_string.push_back(''=''); size_t encoded_size = encoded_string.size(); std::vector<BYTE> ret; ret.reserve(3*encoded_size/4); for (size_t i=0; i<encoded_size; i += 4) { // Get values for each group of four base 64 characters BYTE b4[4]; b4[0] = (encoded_string[i+0] <= ''z'') ? from_base64[encoded_string[i+0]] : 0xff; b4[1] = (encoded_string[i+1] <= ''z'') ? from_base64[encoded_string[i+1]] : 0xff; b4[2] = (encoded_string[i+2] <= ''z'') ? from_base64[encoded_string[i+2]] : 0xff; b4[3] = (encoded_string[i+3] <= ''z'') ? from_base64[encoded_string[i+3]] : 0xff; // Transform into a group of three bytes BYTE b3[3]; b3[0] = ((b4[0] & 0x3f) << 2) + ((b4[1] & 0x30) >> 4); b3[1] = ((b4[1] & 0x0f) << 4) + ((b4[2] & 0x3c) >> 2); b3[2] = ((b4[2] & 0x03) << 6) + ((b4[3] & 0x3f) >> 0); // Add the byte to the return value if it isn''t part of an ''='' character (indicated by 0xff) if (b4[1] != 0xff) ret.push_back(b3[0]); if (b4[2] != 0xff) ret.push_back(b3[1]); if (b4[3] != 0xff) ret.push_back(b3[2]); } return ret; }

Uso:

BYTE buf[] = "ABCD"; std::string encoded = Base64::encode(buf, 4); // encoded = "QUJDRA==" std::vector<BYTE> decoded = Base64::decode(encoded);

Una ventaja aquí es que la función de decodificación también puede decodificar la variante url de la codificación de la base 64.