bool Base58::raw_decode (char const* first, char const* last, void* dest, std::size_t size, bool checked, Alphabet const& alphabet) { CAutoBN_CTX pctx; CBigNum bn58 = 58; CBigNum bn = 0; CBigNum bnChar; // Convert big endian string to bignum for (char const* p = first; p != last; ++p) { int i (alphabet.from_char (*p)); if (i == -1) return false; bnChar.setuint ((unsigned int) i); int const success (BN_mul (&bn, &bn, &bn58, pctx)); assert (success); (void) success; bn += bnChar; } // Get bignum as little endian data Blob vchTmp = bn.getvch (); // Trim off sign byte if present if (vchTmp.size () >= 2 && vchTmp.end ()[-1] == 0 && vchTmp.end ()[-2] >= 0x80) vchTmp.erase (vchTmp.end () - 1); char* const out (static_cast <char*> (dest)); // Count leading zeros int nLeadingZeros = 0; for (char const* p = first; p!=last && *p==alphabet[0]; p++) nLeadingZeros++; // Verify that the size is correct if (vchTmp.size() + nLeadingZeros != size) return false; // Fill the leading zeros memset (out, 0, nLeadingZeros); // Copy little endian data to big endian std::reverse_copy (vchTmp.begin (), vchTmp.end (), out + nLeadingZeros); if (checked) { char hash4 [4]; fourbyte_hash256 (hash4, out, size - 4); if (memcmp (hash4, out + size - 4, 4) != 0) return false; } return true; }
bool Base58::decode (const char* psz, Blob& vchRet, Alphabet const& alphabet) { CAutoBN_CTX pctx; vchRet.clear (); CBigNum bn58 = 58; CBigNum bn = 0; CBigNum bnChar; while (isspace (*psz)) psz++; // Convert big endian string to bignum for (const char* p = psz; *p; p++) { // VFALCO TODO Make this use the inverse table! // Or better yet ditch this and call raw_decode // const char* p1 = strchr (alphabet.chars(), *p); if (p1 == nullptr) { while (isspace (*p)) p++; if (*p != '\0') return false; break; } bnChar.setuint (p1 - alphabet.chars()); if (!BN_mul (&bn, &bn, &bn58, pctx)) throw bignum_error ("DecodeBase58 : BN_mul failed"); bn += bnChar; } // Get bignum as little endian data Blob vchTmp = bn.getvch (); // Trim off sign byte if present if (vchTmp.size () >= 2 && vchTmp.end ()[-1] == 0 && vchTmp.end ()[-2] >= 0x80) vchTmp.erase (vchTmp.end () - 1); // Restore leading zeros int nLeadingZeros = 0; for (const char* p = psz; *p == alphabet.chars()[0]; p++) nLeadingZeros++; vchRet.assign (nLeadingZeros + vchTmp.size (), 0); // Convert little endian data to big endian std::reverse_copy (vchTmp.begin (), vchTmp.end (), vchRet.end () - vchTmp.size ()); return true; }