【问题标题】:Decode Base64 String Using Boost使用 Boost 解码 Base64 字符串
【发布时间】:2020-03-17 20:51:49
【问题描述】:

我已经能够使用 boost 和以下代码将 std::vector<char> 编码为 Base64:

using namespace boost::archive::iterators;

std::string message(binary.begin(), binary.end());
std::stringstream os;
using base64_text = insert_linebreaks<base64_from_binary<transform_width<const char *, 6, 8>>, 72>;

std::copy(
    base64_text(message.c_str()),
    base64_text(message.c_str() + message.size()),
    ostream_iterator<char>(os)
);

return os.str();

我在 Stackoverflow 上找到了这个。好吧,现在我想反过来做同样的事情,放入一个 Base64 格式的 std::string 并最终得到一个 std::vector&lt;char&gt;。但我不能让我的例子反过来做。我在网上找到了一些其他代码,它适用于 Hello World 示例,但是当实际更大的 Base64 还包含一些关键字符(如反斜杠)时,整个事情就会崩溃。

这就是我现在正在做的解码:

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

typedef
    transform_width<
        binary_from_base64<string::const_iterator>, 8, 6
        > binary_t;
string dec(binary_t(str.begin()), binary_t(str.end()));
return dec;

当我要创建字符串时,它在返回前的最后一行崩溃。 你看看有什么问题吗?

【问题讨论】:

  • base64 编码字符串中的反斜杠有什么作用? | “整个事情都崩溃了”——细节?它是否由于输入无效而引发异常并且您没有捕获它?
  • 根据维基百科,它是值为 63 的字符。
  • 在这种情况下,你的斜线混淆了:/ 是向前的,\ 是向后的。
  • 啊,当然,我的错。我的 base64 字符串中没有反斜杠,只有普通的正斜杠。
  • 添加一个 try/catch 或在调试器中运行它,看看你能找出崩溃的原因。如果您可以提供minimal reproducible example,包括导致错误的示例输入,这也会很有用。

标签: c++ boost base64


【解决方案1】:

base64 要求输入和输出分别填充为 3 和 4 的倍数。

这是一个使用boost解码base64的函数:

#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 <algorithm>    

std::string decode(std::string input)
{
  using namespace boost::archive::iterators;
  typedef transform_width<binary_from_base64<remove_whitespace
      <std::string::const_iterator> >, 8, 6> ItBinaryT;

  try
  {
    // If the input isn't a multiple of 4, pad with =
    size_t num_pad_chars((4 - input.size() % 4) % 4);
    input.append(num_pad_chars, '=');

    size_t pad_chars(std::count(input.begin(), input.end(), '='));
    std::replace(input.begin(), input.end(), '=', 'A');
    std::string output(ItBinaryT(input.begin()), ItBinaryT(input.end()));
    output.erase(output.end() - pad_chars, output.end());
    return output;
  }
  catch (std::exception const&)
  {
    return std::string("");
  }
}

取自here,其中还可以找到使用boost 进行填充的编码函数。

【讨论】:

  • 此代码有错误,我已在下面的代码中修复。
【解决方案2】:

我尝试了 kenba 公认的解决方案,但遇到了一些我在下面修复的问题。首先,尾随空格将导致任何 remove_whitespace 迭代器跳过 end(),从而导致内存错误。其次,因为您正在计算未过滤字符串的填充,所以任何包含空格的 base64 编码字符串都会产生不正确的 pad_chars 数量。解决方案是在对字符串执行任何其他操作之前预先过滤空格。

#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 <algorithm> 

inline void decode_base64( std::string input, std::vector<char>& output )
{
    using namespace boost::archive::iterators;
    typedef remove_whitespace<std::string::const_iterator> StripIt;
    typedef transform_width<binary_from_base64<std::string::const_iterator>, 8, 6> ItBinaryT;
    try
    {
        /// Trailing whitespace makes remove_whitespace barf because the iterator never == end().
        while (!input.empty() && std::isspace( input.back() )) { input.pop_back(); }
        input.swap( std::string( StripIt( input.begin() ), StripIt( input.end() ) ) );
        /// If the input isn't a multiple of 4, pad with =
        input.append( (4 - input.size() % 4) % 4, '=' );
        size_t pad_chars( std::count( input.end() - 4, input.end(), '=' ) );
        std::replace( input.end() - 4, input.end(), '=', 'A' );
        output.clear();
        output.reserve( input.size() * 1.3334 );
        output.assign( ItBinaryT( input.begin() ), ItBinaryT( input.end() ) );
        output.erase( output.end() - (pad_chars < 2 ? pad_chars : 2), output.end() );
    }
    catch (std::exception const&)
    {
        output.clear();
    }
}

【讨论】:

  • 这不会编译,即使使用最新的 C++。请修改您的答案...
【解决方案3】:

这是1_65_1/boost/archive/iterators/transform_width.hpp的引述

// iterator which takes elements of x bits and returns elements of y bits.
// used to change streams of 8 bit characters into streams of 6 bit characters.
// and vice-versa for implementing base64 encodeing/decoding. Be very careful
// when using and end iterator.  end is only reliable detected when the input
// stream length is some common multiple of x and y.  E.G. Base64 6 bit
// character and 8 bit bytes. Lowest common multiple is 24 => 4 6 bit characters
// or 3 8 bit characters

所以看起来您必须填充字符串以进行编码(例如使用零字符)以避免此类问题,并在解码后截断它们

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-26
    • 1970-01-01
    相关资源
    最近更新 更多