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

前端 未结 9 1008
南方客
南方客 2020-12-04 10:53

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 bo

相关标签:
9条回答
  • 2020-12-04 11:18

    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;
    
    0 讨论(0)
  • 2020-12-04 11:20

    This is another answer:

    #include <boost/archive/iterators/binary_from_base64.hpp>
    #include <boost/archive/iterators/base64_from_binary.hpp>
    #include <boost/archive/iterators/transform_width.hpp>
    
    std::string ToBase64(const std::vector<unsigned char>& binary)
    {
        using namespace boost::archive::iterators;
        using It = base64_from_binary<transform_width<std::vector<unsigned char>::const_iterator, 6, 8>>;
        auto base64 = std::string(It(binary.begin()), It(binary.end()));
        // Add padding.
        return base64.append((3 - binary.size() % 3) % 3, '=');
    }
    
    std::vector<unsigned char> FromBase64(const std::string& base64)
    {
        using namespace boost::archive::iterators;
        using It = transform_width<binary_from_base64<std::string::const_iterator>, 8, 6>;
        auto binary = std::vector<unsigned char>(It(base64.begin()), It(base64.end()));
        // Remove padding.
        auto length = base64.size();
        if(binary.size() > 2 && base64[length - 1] == '=' && base64[length - 2] == '=')
        {
            binary.erase(binary.end() - 2, binary.end());
        }
        else if(binary.size() > 1 && base64[length - 1] == '=')
        {
            binary.erase(binary.end() - 1, binary.end());
        }
        return binary;
    }
    
    0 讨论(0)
  • 2020-12-04 11:22

    Another solution using boost base64 encode decode:

    const std::string base64_padding[] = {"", "==","="};
    std::string base64_encode(const std::string& s) {
      namespace bai = boost::archive::iterators;
    
      std::stringstream os;
    
      // convert binary values to base64 characters
      typedef bai::base64_from_binary
      // retrieve 6 bit integers from a sequence of 8 bit bytes
      <bai::transform_width<const char *, 6, 8> > base64_enc; // compose all the above operations in to a new iterator
    
      std::copy(base64_enc(s.c_str()), base64_enc(s.c_str() + s.size()),
                std::ostream_iterator<char>(os));
    
      os << base64_padding[s.size() % 3];
      return os.str();
    }
    
    std::string base64_decode(const std::string& s) {
      namespace bai = boost::archive::iterators;
    
      std::stringstream os;
    
      typedef bai::transform_width<bai::binary_from_base64<const char *>, 8, 6> base64_dec;
    
      unsigned int size = s.size();
    
      // Remove the padding characters, cf. https://svn.boost.org/trac/boost/ticket/5629
      if (size && s[size - 1] == '=') {
        --size;
        if (size && s[size - 1] == '=') --size;
      }
      if (size == 0) return std::string();
    
      std::copy(base64_dec(s.data()), base64_dec(s.data() + size),
                std::ostream_iterator<char>(os));
    
      return os.str();
    }
    

    And here are the test cases:

        std::string t_e[TESTSET_SIZE] = {
            ""
          , "M"
          , "Ma"
          , "Man"
          , "pleasure."
          , "leasure."
          , "easure."
          , "asure."
          , "sure."
    };
    std::string t_d[TESTSET_SIZE] = {
            ""
          , "TQ=="
          , "TWE="
          , "TWFu"
          , "cGxlYXN1cmUu"
          , "bGVhc3VyZS4="
          , "ZWFzdXJlLg=="
          , "YXN1cmUu"
          , "c3VyZS4="
    };
    

    Hope this helps

    0 讨论(0)
  • 2020-12-04 11:24

    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, '=');
    }
    
    0 讨论(0)
  • 2020-12-04 11:33

    While the encoding works, the decoder is certainly broken. Also there is a bug opened: https://svn.boost.org/trac/boost/ticket/5629. I have not found a fix for that.

    0 讨论(0)
  • 2020-12-04 11:34

    Base64 encode text and data

    const std::string base64_padding[] = {"", "==","="};
    
    std::string base64EncodeText(std::string text) {
        using namespace boost::archive::iterators;
        typedef std::string::const_iterator iterator_type;
        typedef base64_from_binary<transform_width<iterator_type, 6, 8> > base64_enc;
        std::stringstream ss;
        std::copy(base64_enc(text.begin()), base64_enc(text.end()), ostream_iterator<char>(ss));
        ss << base64_padding[text.size() % 3];
        return ss.str();
    }
    
    std::string base64EncodeData(std::vector<uint8_t> data) {
        using namespace boost::archive::iterators;
        typedef std::vector<uint8_t>::const_iterator iterator_type;
        typedef base64_from_binary<transform_width<iterator_type, 6, 8> > base64_enc;
        std::stringstream ss;
        std::copy(base64_enc(data.begin()), base64_enc(data.end()), ostream_iterator<char>(ss));
        ss << base64_padding[data.size() % 3];
        return ss.str();
    }
    
    0 讨论(0)
提交回复
热议问题