encode/decode Base-58 C++ I have built a base-58 encoder using this formula: https://www.youtube.com/watch?v=GedV3S9X89c&amp;feature=youtu.be

Is there a smarter way to encode/decode with base-58?

I read somewhere that you need a bignum library which I use Boost for.

My goal is to convert between these two:

008D4D508F5BF2C28B20A3863405F05D3CD374B045E4B316E7
1Dt8ty59tU9LkrXG2ocWeSzKFAY8fu6jga


Which so easily this website do: http://lenschulwitz.com/base58

I know bitcoin source code have a base-58 encoder/decoder, but I do not know how to implement it successfully.
Have added my own implementation, complete with a fuzz tester to ensure that it works properly.  (The CodecMapping parameter is provided so that you can change the alphabet string as I've had to do from time to time)

#include &lt;vector&gt;
#include &lt;random&gt;
#include &lt;string&gt;
#include &lt;algorithm&gt;
#include &lt;iomanip&gt;
#include &lt;iostream&gt;

inline static constexpr const uint8_t Base58Map[] = {
  '1', '2', '3', '4', '5', '6', '7', '8',
  '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
  'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q',
  'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
  'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
  'h', 'i', 'j', 'k', 'm', 'n', 'o', 'p',
  'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
  'y', 'z' };
inline static constexpr const uint8_t AlphaMap[] = {
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0xff, 0x11, 0x12, 0x13, 0x14, 0x15, 0xff,
  0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0xff, 0x2c, 0x2d, 0x2e,
  0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff };

using CodecMapping = struct _codecmapping
{
  _codecmapping(const uint8_t* amap, const uint8_t* bmap) : AlphaMapping(amap), BaseMapping(bmap) {}
  const uint8_t* AlphaMapping;
  const uint8_t* BaseMapping;
};

std::string Base58Encode(const std::vector&lt;uint8_t&gt;&amp; data, CodecMapping mapping)
{
  std::vector&lt;uint8_t&gt; digits((data.size() * 138 / 100) + 1);
  size_t digitslen = 1;
  for (size_t i = 0; i &lt; data.size(); i++)
  {
    uint32_t carry = static_cast&lt;uint32_t&gt;(data[i]);
    for (size_t j = 0; j &lt; digitslen; j++)
    {
      carry = carry + static_cast&lt;uint32_t&gt;(digits[j] &lt;&lt; 8);
      digits[j] = static_cast&lt;uint8_t&gt;(carry % 58);
      carry /= 58;
    }
    for (; carry; carry /= 58)
      digits[digitslen++] = static_cast&lt;uint8_t&gt;(carry % 58);
  }
  std::string result;
  for (size_t i = 0; i &lt; (data.size() - 1) &amp;&amp; !data[i]; i++)
    result.push_back(mapping.BaseMapping[0]);
  for (size_t i = 0; i &lt; digitslen; i++)
    result.push_back(mapping.BaseMapping[digits[digitslen - 1 - i]]);
  return result;
}

std::vector&lt;uint8_t&gt; Base58Decode(const std::string&amp; data, CodecMapping mapping)
{
  std::vector&lt;uint8_t&gt; result((data.size() * 138 / 100) + 1);
  size_t resultlen = 1;
  for (size_t i = 0; i &lt; data.size(); i++)
  {
    uint32_t carry = static_cast&lt;uint32_t&gt;(mapping.AlphaMapping[data[i] &amp; 0x7f]);
    for (size_t j = 0; j &lt; resultlen; j++, carry &gt;&gt;= 8)
    {
      carry += static_cast&lt;uint32_t&gt;(result[j] * 58);
      result[j] = static_cast&lt;uint8_t&gt;(carry);
    }
    for (; carry; carry &gt;&gt;=8)
      result[resultlen++] = static_cast&lt;uint8_t&gt;(carry);
  }
  result.resize(resultlen);
  for (size_t i = 0; i &lt; (data.size() - 1) &amp;&amp; data[i] == mapping.BaseMapping[0]; i++)
    result.push_back(0);
  std::reverse(result.begin(), result.end());
  return result;
}

// Fuzz Testing the Encoder &amp; Decoder
int main(int argc, char** argv)
{
  std::random_device device;
  std::mt19937 generator(device());
  std::uniform_int_distribution d1(1, 100);
  std::uniform_int_distribution d2(0, 255);
  CodecMapping mapping(AlphaMap, Base58Map);

  auto create_data = [&amp;]() -&gt; std::vector&lt;uint8_t&gt; {
    std::vector&lt;uint8_t&gt; data(d1(generator));
    std::cout &lt;&lt; "Generating: " &lt;&lt; std::dec &lt;&lt; static_cast&lt;int&gt;(data.size()) &lt;&lt; " points\nPoints:\n";
    for (uint8_t&amp; v : data)
    {
      v = static_cast&lt;uint8_t&gt;(d2(generator));
      std::cout &lt;&lt; std::uppercase &lt;&lt; std::hex &lt;&lt; std::setw(2) &lt;&lt; std::setfill('0') &lt;&lt; static_cast&lt;int&gt;(v);
    }
    std::cout &lt;&lt; std::endl;
    return data;
  };

  std::vector&lt;uint8_t&gt; test_data, decoded_data;
  std::string encoded_data;
  size_t passed = 0;

  for (size_t i = 0; i &lt; 1000; i++)    // Number of tests here!
  {
    test_data = create_data();
    encoded_data = Base58Encode(test_data, mapping);
    decoded_data = Base58Decode(encoded_data, mapping);

    std::cout &lt;&lt; "Encoded\n" &lt;&lt; encoded_data &lt;&lt; "\nDecoded:\n";

    for (uint8_t d : decoded_data)
      std::cout &lt;&lt; std::uppercase &lt;&lt; std::hex &lt;&lt; std::setw(2) &lt;&lt; std::setfill('0') &lt;&lt; static_cast&lt;int&gt;(d);

    std::cout &lt;&lt; "\nTest Result: ";
    if (test_data.size() == decoded_data.size() &amp;&amp; test_data == decoded_data)
    {
      std::cout &lt;&lt; "PASSED\n";
      passed++;
    }
    else
    {
      std::cout &lt;&lt; "FAILED\n";
      break;
    }
    std::cout &lt;&lt; std::endl;
  }
  std::cout &lt;&lt; "Passed Tests: " &lt;&lt; std::dec &lt;&lt; static_cast&lt;int&gt;(passed) &lt;&lt; std::endl;
  return 0;
}