Line data Source code
1 : // Copyright (c) 2014 The Bitcoin developers 2 : // Copyright (c) 2017-2021 The PIVX Core developers 3 : // Distributed under the MIT software license, see the accompanying 4 : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 5 : 6 : #include "base58.h" 7 : 8 : #include "hash.h" 9 : #include "util/string.h" 10 : 11 : #include "uint256.h" 12 : 13 : #include <algorithm> 14 : #include <assert.h> 15 : #include <sstream> 16 : #include <vector> 17 : 18 : #include <limits> 19 : 20 : /** All alphanumeric characters except for "0", "I", "O", and "l" */ 21 : static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; 22 : 23 6838 : bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch, int max_ret_len) 24 : { 25 : // Skip leading spaces. 26 6852 : while (*psz && isspace(*psz)) 27 14 : psz++; 28 : // Skip and count leading '1's. 29 : int zeroes = 0; 30 63316 : int length = 0; 31 63316 : while (*psz == '1') { 32 56704 : zeroes++; 33 56704 : if (zeroes > max_ret_len) return false; 34 56478 : psz++; 35 : } 36 : // Allocate enough space in big-endian base256 representation. 37 6612 : int size = strlen(psz) * 733 /1000 + 1; // log(58) / log(256), rounded up. 38 13450 : std::vector<unsigned char> b256(size); 39 : // Process the characters. 40 386962 : while (*psz && !isspace(*psz)) { 41 : // Decode base58 character 42 381561 : const char* ch = strchr(pszBase58, *psz); 43 381561 : if (ch == nullptr) 44 : return false; 45 : // Apply "b256 = b256 * 58 + ch". 46 381210 : int carry = ch - pszBase58; 47 381210 : int i = 0; 48 17219970 : for (std::vector<unsigned char>::reverse_iterator it = b256.rbegin(); (carry != 0 || i < length) && (it != b256.rend()); ++it, ++i) { 49 16838770 : carry += 58 * (*it); 50 16838770 : *it = carry % 256; 51 16838770 : carry /= 256; 52 : } 53 381210 : assert(carry == 0); 54 381210 : length = i; 55 381210 : if (length + zeroes > max_ret_len) return false; 56 380350 : psz++; 57 : } 58 : // Skip trailing spaces. 59 5578 : while (isspace(*psz)) 60 177 : psz++; 61 5401 : if (*psz != 0) 62 : return false; 63 : // Skip leading zeroes in b256. 64 5399 : std::vector<unsigned char>::iterator it = b256.begin() + (size - length); 65 : // Copy result into output vector. 66 5399 : vch.reserve(zeroes + (b256.end() - it)); 67 5399 : vch.assign(zeroes, 0x00); 68 233112 : while (it != b256.end()) 69 227713 : vch.push_back(*(it++)); 70 : return true; 71 : } 72 : 73 15215 : std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend) 74 : { 75 : // Skip & count leading zeroes. 76 15215 : int zeroes = 0; 77 15215 : int length = 0; 78 49504 : while (pbegin != pend && *pbegin == 0) { 79 34289 : pbegin++; 80 34289 : zeroes++; 81 : } 82 : // Allocate enough space in big-endian base58 representation. 83 15215 : int size = (pend - pbegin) * 138 / 100 + 1; // log(256) / log(58), rounded up. 84 15215 : std::vector<unsigned char> b58(size); 85 : // Process the bytes. 86 498528 : while (pbegin != pend) { 87 483313 : int carry = *pbegin; 88 483313 : int i = 0; 89 : // Apply "b58 = b58 * 256 + ch". 90 18651050 : for (std::vector<unsigned char>::reverse_iterator it = b58.rbegin(); (carry != 0 || i < length) && (it != b58.rend()); it++, i++) { 91 18167720 : carry += 256 * (*it); 92 18167720 : *it = carry % 58; 93 18167720 : carry /= 58; 94 : } 95 : 96 483313 : assert(carry == 0); 97 483313 : length = i; 98 483313 : pbegin++; 99 : } 100 : // Skip leading zeroes in base58 result. 101 15215 : std::vector<unsigned char>::iterator it = b58.begin() + (size - length); 102 15213 : while (it != b58.end() && *it == 0) 103 15215 : it++; 104 : // Translate the result into a string. 105 15215 : std::string str; 106 15215 : str.reserve(zeroes + (b58.end() - it)); 107 15215 : str.assign(zeroes, '1'); 108 674006 : while (it != b58.end()) 109 658791 : str += pszBase58[*(it++)]; 110 30430 : return str; 111 : } 112 : 113 15202 : std::string EncodeBase58(const std::vector<unsigned char>& vch) 114 : { 115 15202 : return EncodeBase58(vch.data(), vch.data() + vch.size()); 116 : } 117 : 118 18 : bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet, int max_ret_len) 119 : { 120 18 : if (!ValidAsCString(str)) { 121 : return false; 122 : } 123 16 : return DecodeBase58(str.c_str(), vchRet, max_ret_len); 124 : } 125 : 126 15202 : std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn) 127 : { 128 : // add 4-byte hash check to the end 129 15202 : std::vector<unsigned char> vch(vchIn); 130 15202 : uint256 hash = Hash(vch.begin(), vch.end()); 131 15202 : vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4); 132 30404 : return EncodeBase58(vch); 133 : } 134 : 135 6818 : bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet, int max_ret_len) 136 : { 137 6818 : if (!DecodeBase58(psz, vchRet, max_ret_len > std::numeric_limits<int>::max() - 4 ? std::numeric_limits<int>::max() : max_ret_len + 4) || 138 5384 : (vchRet.size() < 4)) { 139 1439 : vchRet.clear(); 140 1439 : return false; 141 : } 142 : // re-calculate the checksum, insure it matches the included 4-byte checksum 143 5379 : uint256 hash = Hash(vchRet.begin(), vchRet.end() - 4); 144 5379 : if (memcmp(&hash, &vchRet[vchRet.size() - 4], 4) != 0) { 145 17 : vchRet.clear(); 146 17 : return false; 147 : } 148 5362 : vchRet.resize(vchRet.size() - 4); 149 : return true; 150 : } 151 : 152 6819 : bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet, int max_ret) 153 : { 154 6819 : if (!ValidAsCString(str)) { 155 : return false; 156 : } 157 6818 : return DecodeBase58Check(str.c_str(), vchRet, max_ret); 158 : }