尝试解码不在base64字符集中的值

attempt to decode a value not in base64 char set

本文关键字:字符集 集中 字符 base64 解码      更新时间:2023-10-16

我使用以下代码片段使用Boost C++库对字符串进行base64编码和解码。

//Base64 Encode Implementation using Boost C++ library
const std::string base64_padding[] = {"", "=", "=="};
std::string X_Privet_Token_Generator::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 X_Privet_Token_Generator::base64_decode(std::string & s)
{
  namespace bai = boost::archive::iterators;
  std::stringstream os;
  // convert binary values to base64 characters
  typedef bai::binary_from_base64
  <bai::transform_width<const char *, 8, 6> > base64_dec;
  unsigned int size = s.size();
  // Remove the padding characters, cf.
  if (size && s[size - 1] == '=')
  {
      --size;
      if (size && s[size - 1] == '=')
          --size;
  }
  if (size == 0)
      return std::string();
  LOGINFO("Hash decoded token : %s", s.c_str());
  std::copy(base64_dec(s.data()), base64_dec(s.data() + size), std::ostream_iterator<char>(os));
  std::cout<< os.str();
  return os.str();
}

编码工作得很好,然而,在解码时,我得到了以下错误:

抛出boost::archive::iterators::dataflow_exception 实例后调用的terminate

what():尝试解码不在base64字符集中的值

是填充字符导致了这个问题吗?我是不是遗漏了什么?

填充字符'='是b64编码数据的一部分,在解码之前不应删除。b64是以4个字符的块编码的,我怀疑在解码时,它读取的是"\0",而不是字符串末尾预期的"="。

更改

std::copy(base64_dec(s.data()), base64_dec(s.data() + size), std::ostream_iterator<char>(os))

return std::string( base64_dec(s.c_str()), base64_dec(s.c_str() + size))

解决了这个问题。

base64编码和解码的一个更有效的解决方案如下:

#include <boost/archive/iterators/base64_from_binary.hpp>
#include <boost/archive/iterators/binary_from_base64.hpp>
#include <boost/archive/iterators/insert_linebreaks.hpp>
#include <boost/archive/iterators/remove_whitespace.hpp>
#include <boost/archive/iterators/transform_width.hpp>
#include <boost/archive/iterators/ostream_iterator.hpp>
#include <boost/algorithm/string.hpp>
#include <bits/stl_algo.h>
std::string X_Privet_Token_Generator::base64_encode(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<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 X_Privet_Token_Generator::base64_decode(std::string s)
{
    namespace bai = boost::archive::iterators;
    std::stringstream os;
    typedef bai::transform_width<bai::binary_from_base64<char * >, 8, 6>
      base64_dec;
    unsigned int size = s.size();
    // Remove the padding characters.
    if(size && s[size - 1] == '=') {
        --size;
    if(size && s[size - 1] == '=')
        --size;
    }
    if(size == 0) return std::string();
    unsigned int paddChars = count(s.begin(), s.end(), '=');
    std::replace(s.begin(),s.end(), '=', 'A');
    std::string decoded_token(base64_dec(s.c_str()), base64_dec(s.c_str() + size));
    decoded_token.erase(decoded_token.end()-paddChars,decoded_token.end());
    return decoded_token;
}