Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I encode a string to base64 using only boost?

I'm trying to quickly encode a simple ASCII string to base64 (Basic HTTP Authentication using boost::asio) and not paste in any new code code or use any libraries beyond boost.

Simple signature would look like: string Base64Encode(const string& text);

Again I realize the algorithm is easy and there are many libraries/examples doing this but I'm looking for a clean boost example. I found boost serialization but no clear examples there or from Google. http://www.boost.org/doc/libs/1_46_1/libs/serialization/doc/dataflow.html

Is this possible without adding the actual base64 algorithm explicitly to my code?

like image 791
MattiasF Avatar asked Aug 13 '11 21:08

MattiasF


People also ask

How do you convert a string to Base64?

To convert a string into a Base64 character the following steps should be followed: Get the ASCII value of each character in the string. Compute the 8-bit binary equivalent of the ASCII values. Convert the 8-bit characters chunk into chunks of 6 bits by re-grouping the digits.

Which is the method that encodes a string to Base64?

The encodeToString() method will encode our input into a Base64 representation of the input, and pack it into a String. You can also use the encode() method to encode it into a byte stream or a ByteBuffer instead.

Why do Base64 strings end with ==?

Q Why does an = get appended at the end? A: As a short answer: The last character ( = sign) is added only as a complement (padding) in the final process of encoding a message with a special number of characters.

Do you need to URL encode Base64?

No, you would need to url-encode it, since base64 strings can contain the "+", "=" and "/" characters which could alter the meaning of your data - look like a sub-folder.


2 Answers

Here is my solution. It uses the same basic technique as the other solutions on this page, but solves the problem of the padding in what I feel is a more elegant way. This solution also makes use of C++11.

I think that most of the code is self explanatory. The bit of math in the encode function calculates the number of '=' characters we need to add. The modulo 3 of val.size() the remainder, but what we really want is the difference between val.size() and the next number divisible by three. Since we have the remainder we can just subtract the remainder from 3, but that leaves 3 in the case that we want 0, so we have to modulo 3 one more time.

#include <boost/archive/iterators/binary_from_base64.hpp> #include <boost/archive/iterators/base64_from_binary.hpp> #include <boost/archive/iterators/transform_width.hpp> #include <boost/algorithm/string.hpp>  std::string decode64(const std::string &val) {     using namespace boost::archive::iterators;     using It = transform_width<binary_from_base64<std::string::const_iterator>, 8, 6>;     return boost::algorithm::trim_right_copy_if(std::string(It(std::begin(val)), It(std::end(val))), [](char c) {         return c == '\0';     }); }  std::string encode64(const std::string &val) {     using namespace boost::archive::iterators;     using It = base64_from_binary<transform_width<std::string::const_iterator, 6, 8>>;     auto tmp = std::string(It(std::begin(val)), It(std::end(val)));     return tmp.append((3 - val.size() % 3) % 3, '='); } 
like image 90
ltc Avatar answered Oct 07 '22 11:10

ltc


I improved the example in the link you provided a little:

#include <boost/archive/iterators/base64_from_binary.hpp> #include <boost/archive/iterators/insert_linebreaks.hpp> #include <boost/archive/iterators/transform_width.hpp> #include <boost/archive/iterators/ostream_iterator.hpp> #include <sstream> #include <string> #include <iostream>   int main() {     using namespace boost::archive::iterators;      std::string test = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce ornare ullamcorper ipsum ac gravida.";      std::stringstream os;     typedef          insert_linebreaks<         // insert line breaks every 72 characters             base64_from_binary<    // convert binary values to base64 characters                 transform_width<   // retrieve 6 bit integers from a sequence of 8 bit bytes                     const char *,                     6,                     8                 >             >              ,72         >          base64_text; // compose all the above operations in to a new iterator      std::copy(         base64_text(test.c_str()),         base64_text(test.c_str() + test.size()),         ostream_iterator<char>(os)     );      std::cout << os.str(); } 

This prints the string encoded base64 nicely formated with a line break every 72 characters onto the console, ready to be put into an email. If you don't like the linebreaks, just stay with this:

    typedef          base64_from_binary<            transform_width<                 const char *,                 6,                 8             >         >          base64_text; 
like image 42
Tobias Schlegel Avatar answered Oct 07 '22 12:10

Tobias Schlegel