Bitcoin ABC  0.22.12
P2P Digital Currency
base58.cpp
Go to the documentation of this file.
1 // Copyright (c) 2014-2016 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <base58.h>
6 
7 #include <hash.h>
8 #include <uint256.h>
9 #include <util/strencodings.h>
10 #include <util/string.h>
11 
12 #include <cassert>
13 #include <cstdint>
14 #include <cstring>
15 #include <limits>
16 
18 static const char *pszBase58 =
19  "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
20 static const int8_t mapBase58[256] = {
21  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
22  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
23  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7,
24  8, -1, -1, -1, -1, -1, -1, -1, 9, 10, 11, 12, 13, 14, 15, 16, -1, 17, 18,
25  19, 20, 21, -1, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, -1,
26  -1, -1, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, -1, 44, 45, 46, 47, 48,
27  49, 50, 51, 52, 53, 54, 55, 56, 57, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
28  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
29  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
30  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
31  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
32  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
33  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
34  -1, -1, -1, -1, -1, -1, -1, -1, -1,
35 };
36 
37 bool DecodeBase58(const char *psz, std::vector<uint8_t> &vch, int max_ret_len) {
38  // Skip leading spaces.
39  while (*psz && IsSpace(*psz)) {
40  psz++;
41  }
42  // Skip and count leading '1's.
43  int zeroes = 0;
44  int length = 0;
45  while (*psz == '1') {
46  zeroes++;
47  if (zeroes > max_ret_len) {
48  return false;
49  }
50  psz++;
51  }
52  // Allocate enough space in big-endian base256 representation.
53  // log(58) / log(256), rounded up.
54  int size = strlen(psz) * 733 / 1000 + 1;
55  std::vector<uint8_t> b256(size);
56  // Process the characters.
57  // guarantee not out of range
58  static_assert(sizeof(mapBase58) / sizeof(mapBase58[0]) == 256,
59  "mapBase58.size() should be 256");
60  while (*psz && !IsSpace(*psz)) {
61  // Decode base58 character
62  int carry = mapBase58[(uint8_t)*psz];
63  // Invalid b58 character
64  if (carry == -1) {
65  return false;
66  }
67  int i = 0;
68  for (std::vector<uint8_t>::reverse_iterator it = b256.rbegin();
69  (carry != 0 || i < length) && (it != b256.rend()); ++it, ++i) {
70  carry += 58 * (*it);
71  *it = carry % 256;
72  carry /= 256;
73  }
74  assert(carry == 0);
75  length = i;
76  if (length + zeroes > max_ret_len) {
77  return false;
78  }
79  psz++;
80  }
81  // Skip trailing spaces.
82  while (IsSpace(*psz)) {
83  psz++;
84  }
85  if (*psz != 0) {
86  return false;
87  }
88  // Skip leading zeroes in b256.
89  std::vector<uint8_t>::iterator it = b256.begin() + (size - length);
90 
91  // Copy result into output vector.
92  vch.reserve(zeroes + (b256.end() - it));
93  vch.assign(zeroes, 0x00);
94  while (it != b256.end()) {
95  vch.push_back(*(it++));
96  }
97  return true;
98 }
99 
100 std::string EncodeBase58(const uint8_t *pbegin, const uint8_t *pend) {
101  // Skip & count leading zeroes.
102  int zeroes = 0;
103  int length = 0;
104  while (pbegin != pend && *pbegin == 0) {
105  pbegin++;
106  zeroes++;
107  }
108  // Allocate enough space in big-endian base58 representation.
109  // log(256) / log(58), rounded up.
110  int size = (pend - pbegin) * 138 / 100 + 1;
111  std::vector<uint8_t> b58(size);
112  // Process the bytes.
113  while (pbegin != pend) {
114  int carry = *pbegin;
115  int i = 0;
116  // Apply "b58 = b58 * 256 + ch".
117  for (std::vector<uint8_t>::reverse_iterator it = b58.rbegin();
118  (carry != 0 || i < length) && (it != b58.rend()); it++, i++) {
119  carry += 256 * (*it);
120  *it = carry % 58;
121  carry /= 58;
122  }
123 
124  assert(carry == 0);
125  length = i;
126  pbegin++;
127  }
128  // Skip leading zeroes in base58 result.
129  std::vector<uint8_t>::iterator it = b58.begin() + (size - length);
130  while (it != b58.end() && *it == 0) {
131  it++;
132  }
133  // Translate the result into a string.
134  std::string str;
135  str.reserve(zeroes + (b58.end() - it));
136  str.assign(zeroes, '1');
137  while (it != b58.end()) {
138  str += pszBase58[*(it++)];
139  }
140  return str;
141 }
142 
143 std::string EncodeBase58(const std::vector<uint8_t> &vch) {
144  return EncodeBase58(vch.data(), vch.data() + vch.size());
145 }
146 
147 bool DecodeBase58(const std::string &str, std::vector<uint8_t> &vchRet,
148  int max_ret_len) {
149  if (!ValidAsCString(str)) {
150  return false;
151  }
152  return DecodeBase58(str.c_str(), vchRet, max_ret_len);
153 }
154 
155 std::string EncodeBase58Check(const std::vector<uint8_t> &vchIn) {
156  // add 4-byte hash check to the end
157  std::vector<uint8_t> vch(vchIn);
158  uint256 hash = Hash(vch.begin(), vch.end());
159  vch.insert(vch.end(), (uint8_t *)&hash, (uint8_t *)&hash + 4);
160  return EncodeBase58(vch);
161 }
162 
163 bool DecodeBase58Check(const char *psz, std::vector<uint8_t> &vchRet,
164  int max_ret_len) {
165  if (!DecodeBase58(psz, vchRet,
166  max_ret_len > std::numeric_limits<int>::max() - 4
167  ? std::numeric_limits<int>::max()
168  : max_ret_len + 4) ||
169  (vchRet.size() < 4)) {
170  vchRet.clear();
171  return false;
172  }
173  // re-calculate the checksum, ensure it matches the included 4-byte checksum
174  uint256 hash = Hash(vchRet.begin(), vchRet.end() - 4);
175  if (memcmp(&hash, &vchRet[vchRet.size() - 4], 4) != 0) {
176  vchRet.clear();
177  return false;
178  }
179  vchRet.resize(vchRet.size() - 4);
180  return true;
181 }
182 
183 bool DecodeBase58Check(const std::string &str, std::vector<uint8_t> &vchRet,
184  int max_ret) {
185  if (!ValidAsCString(str)) {
186  return false;
187  }
188  return DecodeBase58Check(str.c_str(), vchRet, max_ret);
189 }
NODISCARD bool ValidAsCString(const std::string &str) noexcept
Check if a string does not contain any embedded NUL (\0) characters.
Definition: string.h:60
bool DecodeBase58Check(const char *psz, std::vector< uint8_t > &vchRet, int max_ret_len)
Decode a base58-encoded string (psz) that includes a checksum into a byte vector (vchRet), return true if decoding is successful.
Definition: base58.cpp:163
bool DecodeBase58(const char *psz, std::vector< uint8_t > &vch, int max_ret_len)
Decode a base58-encoded string (psz) into a byte vector (vchRet).
Definition: base58.cpp:37
uint256 Hash(const T1 pbegin, const T1 pend)
Compute the 256-bit hash of an object.
Definition: hash.h:72
static const char * pszBase58
All alphanumeric characters except for "0", "I", "O", and "l".
Definition: base58.cpp:18
std::string EncodeBase58(const uint8_t *pbegin, const uint8_t *pend)
Why base-58 instead of standard base-64 encoding?
Definition: base58.cpp:100
256-bit opaque blob.
Definition: uint256.h:120
constexpr bool IsSpace(char c) noexcept
Tests if the given character is a whitespace character.
Definition: strencodings.h:90
static const int8_t mapBase58[256]
Definition: base58.cpp:20
std::string EncodeBase58Check(const std::vector< uint8_t > &vchIn)
Encode a byte vector into a base58-encoded string, including checksum.
Definition: base58.cpp:155