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 13157 : bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch, int max_ret_len) 24 : { 25 : // Skip leading spaces. 26 13171 : while (*psz && isspace(*psz)) 27 14 : psz++; 28 : // Skip and count leading '1's. 29 : int zeroes = 0; 30 64229 : int length = 0; 31 64229 : while (*psz == '1') { 32 51275 : zeroes++; 33 51275 : if (zeroes > max_ret_len) return false; 34 51072 : psz++; 35 : } 36 : // Allocate enough space in big-endian base256 representation. 37 12954 : int size = strlen(psz) * 733 /1000 + 1; // log(58) / log(256), rounded up. 38 26111 : std::vector<unsigned char> b256(size); 39 : // Process the characters. 40 583862 : while (*psz && !isspace(*psz)) { 41 : // Decode base58 character 42 573142 : const char* ch = strchr(pszBase58, *psz); 43 573142 : if (ch == nullptr) 44 : return false; 45 : // Apply "b256 = b256 * 58 + ch". 46 571793 : int carry = ch - pszBase58; 47 571793 : int i = 0; 48 20106170 : for (std::vector<unsigned char>::reverse_iterator it = b256.rbegin(); (carry != 0 || i < length) && (it != b256.rend()); ++it, ++i) { 49 19534420 : carry += 58 * (*it); 50 19534420 : *it = carry % 256; 51 19534420 : carry /= 256; 52 : } 53 571793 : assert(carry == 0); 54 571793 : length = i; 55 571793 : if (length + zeroes > max_ret_len) return false; 56 570908 : psz++; 57 : } 58 : // Skip trailing spaces. 59 10897 : while (isspace(*psz)) 60 177 : psz++; 61 10720 : if (*psz != 0) 62 : return false; 63 : // Skip leading zeroes in b256. 64 10718 : std::vector<unsigned char>::iterator it = b256.begin() + (size - length); 65 : // Copy result into output vector. 66 10718 : vch.reserve(zeroes + (b256.end() - it)); 67 10718 : vch.assign(zeroes, 0x00); 68 373056 : while (it != b256.end()) 69 362338 : vch.push_back(*(it++)); 70 : return true; 71 : } 72 : 73 1993256 : std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend) 74 : { 75 : // Skip & count leading zeroes. 76 1993256 : int zeroes = 0; 77 1993256 : int length = 0; 78 2023907 : while (pbegin != pend && *pbegin == 0) { 79 30651 : pbegin++; 80 30651 : zeroes++; 81 : } 82 : // Allocate enough space in big-endian base58 representation. 83 1993256 : int size = (pend - pbegin) * 138 / 100 + 1; // log(256) / log(58), rounded up. 84 1993256 : std::vector<unsigned char> b58(size); 85 : // Process the bytes. 86 51928166 : while (pbegin != pend) { 87 49934930 : int carry = *pbegin; 88 49934930 : int i = 0; 89 : // Apply "b58 = b58 * 256 + ch". 90 962424200 : for (std::vector<unsigned char>::reverse_iterator it = b58.rbegin(); (carry != 0 || i < length) && (it != b58.rend()); it++, i++) { 91 912489300 : carry += 256 * (*it); 92 912489300 : *it = carry % 58; 93 912489300 : carry /= 58; 94 : } 95 : 96 49934930 : assert(carry == 0); 97 49934930 : length = i; 98 49934930 : pbegin++; 99 : } 100 : // Skip leading zeroes in base58 result. 101 1993256 : std::vector<unsigned char>::iterator it = b58.begin() + (size - length); 102 1993254 : while (it != b58.end() && *it == 0) 103 1993256 : it++; 104 : // Translate the result into a string. 105 1993256 : std::string str; 106 1993256 : str.reserve(zeroes + (b58.end() - it)); 107 1993256 : str.assign(zeroes, '1'); 108 69906239 : while (it != b58.end()) 109 67913003 : str += pszBase58[*(it++)]; 110 3986512 : return str; 111 : } 112 : 113 1993244 : std::string EncodeBase58(const std::vector<unsigned char>& vch) 114 : { 115 1993244 : 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 1993244 : std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn) 127 : { 128 : // add 4-byte hash check to the end 129 1993244 : std::vector<unsigned char> vch(vchIn); 130 1993244 : uint256 hash = Hash(vch.begin(), vch.end()); 131 1993244 : vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4); 132 3986478 : return EncodeBase58(vch); 133 : } 134 : 135 13137 : bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet, int max_ret_len) 136 : { 137 13137 : if (!DecodeBase58(psz, vchRet, max_ret_len > std::numeric_limits<int>::max() - 4 ? std::numeric_limits<int>::max() : max_ret_len + 4) || 138 10703 : (vchRet.size() < 4)) { 139 2439 : vchRet.clear(); 140 2439 : return false; 141 : } 142 : // re-calculate the checksum, insure it matches the included 4-byte checksum 143 10698 : uint256 hash = Hash(vchRet.begin(), vchRet.end() - 4); 144 10698 : if (memcmp(&hash, &vchRet[vchRet.size() - 4], 4) != 0) { 145 17 : vchRet.clear(); 146 17 : return false; 147 : } 148 10681 : vchRet.resize(vchRet.size() - 4); 149 : return true; 150 : } 151 : 152 13138 : bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet, int max_ret) 153 : { 154 13138 : if (!ValidAsCString(str)) { 155 : return false; 156 : } 157 13137 : return DecodeBase58Check(str.c_str(), vchRet, max_ret); 158 : }