Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Base64 encode using boost throw exception

I trying to use boost base64 encoder, I found an example but I got and exception

typedef 
transform_width< binary_from_base64<std::string::const_iterator>, 8, 6 > it_binary_t

an I used

std::string b64E(it_binary_t(Encrip.begin()), it_binary_t(Encrip.end()));

I get it

Unhandled exception at 0x75b1b9bc in agentid_coder.exe: Microsoft C++ exception: boost::archive::iterators::dataflow_exception at memory location 0x0046ed94..

I found this workaround but I get the same result

 string dec( 
        it_binary_t(Encrip.begin()), 
        it_binary_t(Encrip.begin() + Encrip.length() - 1) 
        ); 

I am using MSVS2008 and boost 1.38

like image 850
Agus Avatar asked May 09 '12 18:05

Agus


People also ask

How do I throw an exception in boost?

The header <boost/throw_exception.hpp> provides a common Boost infrastructure for throwing exceptions, in the form of a function boost::throw_exception and a macro BOOST_THROW_EXCEPTION.

What is the use of throw_exception?

boost::throw_exception (x); is a replacement for throw x; that both degrades gracefully when exception handling support is not available, and integrates the thrown exception into facilities provided by Boost.Exception, such as automatically providing a base class of type boost::exception and support for boost::exception_ptr.

Is it possible to convert a 24-bit block to Base64?

It is required- "When the number of bytes to encode is not divisible by three (that is, if there are only one or two bytes of input for the last 24-bit block), then the following action is performed: Add extra bytes with value zero so there are three bytes, and perform the conversion to base64." - wikipedia. You could use beast's implementation.

Does base64_from_binary check if an iterator has terminated?

Unfortunately, base64_from_binary doesn't check if the iterator has terminated to pad the missing bits - the transformation stops, but only after we try to resolve the end iterator, which crashes the program (compare with how boost::filter_iterator deals with the source running out of data).


1 Answers

Unfortunately the combination of the two iterator_adaptors binary_from_base64 and transform_width is not a complete base64 encoder/decoder. Base64 represents groups of 24 bits (3 bytes) as 4 characters, each of which encodes 6 bits. If the input data is not an integer multiple of such 3 byte groups it has to be padded with one or two zero bytes. To indicate how many padding bytes were added, one or two = characters are appended to the encoded string.

transform_width, which is responsible for the 8bit binary to 6bit integer conversion does not apply this padding automatically, it has do be done by the user. A simple example:

#include <boost/archive/iterators/base64_from_binary.hpp>
#include <boost/archive/iterators/binary_from_base64.hpp>
#include <boost/archive/iterators/transform_width.hpp>
#include <boost/archive/iterators/insert_linebreaks.hpp>
#include <boost/archive/iterators/remove_whitespace.hpp>
#include <iostream>
#include <string>

using namespace boost::archive::iterators;
using namespace std;

int main(int argc, char **argv) {
  typedef transform_width< binary_from_base64<remove_whitespace<string::const_iterator> >, 8, 6 > it_binary_t;
  typedef insert_linebreaks<base64_from_binary<transform_width<string::const_iterator,6,8> >, 72 > it_base64_t;
  string s;
  getline(cin, s, '\n');
  cout << "Your string is: '"<<s<<"'"<<endl;

  // Encode
  unsigned int writePaddChars = (3-s.length()%3)%3;
  string base64(it_base64_t(s.begin()),it_base64_t(s.end()));
  base64.append(writePaddChars,'=');

  cout << "Base64 representation: " << base64 << endl;

  // Decode
  unsigned int paddChars = count(base64.begin(), base64.end(), '=');
  std::replace(base64.begin(),base64.end(),'=','A'); // replace '=' by base64 encoding of '\0'
  string result(it_binary_t(base64.begin()), it_binary_t(base64.end())); // decode
  result.erase(result.end()-paddChars,result.end());  // erase padding '\0' characters
  cout << "Decoded: " << result << endl;
  return 0;
}

Note that I added the insert_linebreaks and remove_whitespace iterators, so that the base64 output is nicely formatted and base64 input with line breaks can be decoded. These are optional though.

Run with different input strings which require different padding:

$ ./base64example
Hello World!
Your string is: 'Hello World!'
Base64 representation: SGVsbG8gV29ybGQh
Decoded: Hello World!
$ ./base64example
Hello World!!
Your string is: 'Hello World!!'
Base64 representation: SGVsbG8gV29ybGQhIQ==
Decoded: Hello World!!
$ ./base64example
Hello World!!!
Your string is: 'Hello World!!!'
Base64 representation: SGVsbG8gV29ybGQhISE=
Decoded: Hello World!!!

You can check the base64 strings with this online-encoder/decoder.

like image 172
PiQuer Avatar answered Sep 17 '22 17:09

PiQuer