1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin Developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
8 // Why base-58 instead of standard base-64 encoding?
9 // - Don't want 0OIl characters that look the same in some fonts and
10 // could be used to create visually identical looking account numbers.
11 // - A string with non-alphanumeric characters is not as easily accepted as an account number.
12 // - E-mail usually won't line-break if there's no punctuation to break at.
13 // - Double-clicking selects the whole number as one word if it's all alphanumeric.
20 static const std::array<char, 58> digits = {
21 '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
22 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
23 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm',
24 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
27 static const std::array<signed char, 128> characterMap = {
28 -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,
30 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
31 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8,-1,-1,-1,-1,-1,-1,
32 -1, 9,10,11,12,13,14,15,16,-1,17,18,19,20,21,-1,
33 22,23,24,25,26,27,28,29,30,31,32,-1,-1,-1,-1,-1,
34 -1,33,34,35,36,37,38,39,40,41,42,43,-1,44,45,46,
35 47,48,49,50,51,52,53,54,55,56,57,-1,-1,-1,-1,-1,
38 // Encode a byte sequence as a base58-encoded string
39 std::string EncodeBase58(const unsigned char* begin, const unsigned char* end)
41 // Skip & count leading zeroes.
44 while (begin != end && *begin == 0) {
49 // Allocate enough space in big-endian base58 representation.
50 auto base58Size = (end - begin) * 138 / 100 + 1; // log(256) / log(58), rounded up.
51 std::vector<unsigned char> b58(base58Size);
53 while (begin != end) {
56 // Apply "b58 = b58 * 256 + ch".
57 for (auto b58it = b58.rbegin(); (carry != 0 || i < length) && (b58it != b58.rend());
59 carry += 256 * (*b58it);
69 // Skip leading zeroes in base58 result.
70 auto it = b58.begin() + (base58Size - length);
71 while (it != b58.end() && *it == 0) {
75 // Translate the result into a string.
77 str.reserve(zeroes + (b58.end() - it));
78 str.assign(zeroes, digits[0]);
79 while (it != b58.end()) {
86 // Encode a byte vector as a base58-encoded string
87 std::string EncodeBase58(const std::vector<unsigned char>& vch)
89 return EncodeBase58(&vch[0], &vch[0] + vch.size());
92 // Decode a base58-encoded string psz into byte vector vchRet
93 // returns true if decoding is successful
94 bool DecodeBase58(const char* psz, std::vector<unsigned char>& vchRet)
97 const char* end = it + strlen(psz);
99 // Skip leading spaces.
100 it = std::find_if_not(it, end, [](char c) { return std::isspace(c);});
102 // Skip and count leading zeros.
103 std::size_t zeroes = 0;
104 std::size_t length = 0;
105 while (it != end && *it == digits[0]) {
110 // Allocate enough space in big-endian base256 representation.
111 std::size_t base258Size = (end - it) * 733 / 1000 + 1; // log(58) / log(256), rounded up.
112 std::vector<unsigned char> b256(base258Size);
114 // Process the characters.
115 while (it != end && !std::isspace(*it)) {
116 if (static_cast<unsigned char>(*it) >= 128) {
117 // Invalid b58 character
121 // Decode base58 character
122 int carry = characterMap[static_cast<unsigned char>(*it)];
124 // Invalid b58 character
129 for (auto b256it = b256.rbegin(); (carry != 0 || i < length) && (b256it != b256.rend());
131 carry += 58 * (*b256it);
132 *b256it = static_cast<uint8_t>(carry % 256);
140 // Skip trailing spaces.
141 it = std::find_if_not(it, end, [](char c) { return std::isspace(c);});
143 // Extra charaters at the end
147 // Skip leading zeroes in b256.
148 auto b256it = b256.begin() + (base258Size - length);
149 while (b256it != b256.end() && *b256it == 0) {
153 // Copy result into output vector.
154 vchRet.reserve(zeroes + (b256.end() - b256it));
155 vchRet.assign(zeroes, 0x00);
156 std::copy(b256it, b256.end(), std::back_inserter(vchRet));
161 // Decode a base58-encoded string str into byte vector vchRet
162 // returns true if decoding is successful
163 bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet)
165 return DecodeBase58(str.c_str(), vchRet);
168 // Encode a byte vector to a base58-encoded string, including checksum
169 std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
171 // add 4-byte hash check to the end
172 std::vector<unsigned char> vch(vchIn);
173 uint256 hash = Hash(vch.begin(), vch.end());
174 vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
175 return EncodeBase58(vch);
178 // Decode a base58-encoded string psz that includes a checksum, into byte vector vchRet
179 // returns true if decoding is successful
180 bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet)
182 if (!DecodeBase58(psz, vchRet))
184 if (vchRet.size() < 4)
189 uint256 hash = Hash(vchRet.begin(), vchRet.end()-4);
190 if (memcmp(&hash, &vchRet.end()[-4], 4) != 0)
195 vchRet.resize(vchRet.size()-4);
199 // Decode a base58-encoded string str that includes a checksum, into byte vector vchRet
200 // returns true if decoding is successful
201 bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet)
203 return DecodeBase58Check(str.c_str(), vchRet);
206 CBase58Data::CBase58Data()
212 CBase58Data::~CBase58Data()
214 // zero the memory, as it may contain sensitive data
215 if (!vchData.empty())
216 OPENSSL_cleanse(&vchData[0], vchData.size());
219 void CBase58Data::SetData(int nVersionIn, const void* pdata, size_t nSize)
221 nVersion = nVersionIn;
222 vchData.resize(nSize);
223 if (!vchData.empty())
224 memcpy(&vchData[0], pdata, nSize);
227 const std::vector<unsigned char> &CBase58Data::GetData() const
232 void CBase58Data::SetData(int nVersionIn, const unsigned char *pbegin, const unsigned char *pend)
234 SetData(nVersionIn, (void*)pbegin, pend - pbegin);
237 bool CBase58Data::SetString(const char* psz)
239 std::vector<unsigned char> vchTemp;
240 DecodeBase58Check(psz, vchTemp);
247 nVersion = vchTemp[0];
248 vchData.resize(vchTemp.size() - 1);
249 if (!vchData.empty())
250 memcpy(&vchData[0], &vchTemp[1], vchData.size());
251 OPENSSL_cleanse(&vchTemp[0], vchData.size());
255 bool CBase58Data::SetString(const std::string& str)
257 return SetString(str.c_str());
260 std::string CBase58Data::ToString() const
262 std::vector<unsigned char> vch(1, nVersion);
263 vch.insert(vch.end(), vchData.begin(), vchData.end());
264 return EncodeBase58Check(vch);
267 int CBase58Data::CompareTo(const CBase58Data& b58) const
269 if (nVersion < b58.nVersion) return -1;
270 if (nVersion > b58.nVersion) return 1;
271 if (vchData < b58.vchData) return -1;
272 if (vchData > b58.vchData) return 1;
277 class CBitcoinAddressVisitor {
279 CBitcoinAddress *addr;
281 explicit CBitcoinAddressVisitor(CBitcoinAddress *addrIn) : addr(addrIn) { }
283 bool operator()(const CKeyID &id) const { return addr->Set(id); }
284 bool operator()(const CScriptID &id) const { return addr->Set(id); }
285 bool operator()(const CMalleablePubKey &mpk) const { return addr->Set(mpk); }
286 bool operator()([[maybe_unused]] const CNoDestination &no) const { return false; }
290 bool CBitcoinAddress::Set(const CKeyID &id) {
291 SetData(fTestNet ? PUBKEY_ADDRESS_TEST : PUBKEY_ADDRESS, &id, 20);
295 bool CBitcoinAddress::Set(const CScriptID &id) {
296 SetData(fTestNet ? SCRIPT_ADDRESS_TEST : SCRIPT_ADDRESS, &id, 20);
300 bool CBitcoinAddress::Set(const CTxDestination &dest)
302 return std::visit(CBitcoinAddressVisitor(this), dest);
305 bool CBitcoinAddress::Set(const CMalleablePubKey &mpk) {
306 std::vector<unsigned char> vchPubkeyPair = mpk.Raw();
307 SetData(fTestNet ? PUBKEY_PAIR_ADDRESS_TEST : PUBKEY_PAIR_ADDRESS, &vchPubkeyPair[0], 68);
311 bool CBitcoinAddress::Set(const CBitcoinAddress &dest)
313 nVersion = dest.nVersion;
314 vchData = dest.vchData;
318 bool CBitcoinAddress::IsValid() const
320 unsigned int nExpectedSize = 20;
321 bool fExpectTestNet = false;
325 case PUBKEY_PAIR_ADDRESS:
326 nExpectedSize = 68; // Serialized pair of public keys
327 fExpectTestNet = false;
331 nExpectedSize = 20; // Hash of public key
332 fExpectTestNet = false;
335 nExpectedSize = 20; // Hash of CScript
336 fExpectTestNet = false;
339 case PUBKEY_PAIR_ADDRESS_TEST:
341 fExpectTestNet = true;
344 case PUBKEY_ADDRESS_TEST:
346 fExpectTestNet = true;
348 case SCRIPT_ADDRESS_TEST:
350 fExpectTestNet = true;
357 // Basic format sanity check
358 bool fSeemsSane = (fExpectTestNet == fTestNet && vchData.size() == nExpectedSize);
360 if (fSeemsSane && !fSimple)
362 // Perform additional checking
363 // for pubkey pair addresses
364 CMalleablePubKey mpk;
366 return mpk.IsValid();
372 CTxDestination CBitcoinAddress::Get() const {
374 return CNoDestination();
377 case PUBKEY_ADDRESS_TEST: {
379 memcpy(&id, &vchData[0], 20);
383 case SCRIPT_ADDRESS_TEST: {
385 memcpy(&id, &vchData[0], 20);
386 return CScriptID(id);
389 return CNoDestination();
392 bool CBitcoinAddress::GetKeyID(CKeyID &keyID) const {
397 case PUBKEY_ADDRESS_TEST: {
399 memcpy(&id, &vchData[0], 20);
403 case PUBKEY_PAIR_ADDRESS:
404 case PUBKEY_PAIR_ADDRESS_TEST:
406 CMalleablePubKey mPubKey;
407 mPubKey.setvch(vchData);
408 keyID = mPubKey.GetID();
411 default: return false;
415 bool CBitcoinAddress::IsScript() const {
420 case SCRIPT_ADDRESS_TEST: {
423 default: return false;
427 bool CBitcoinAddress::IsPubKey() const {
432 case PUBKEY_ADDRESS_TEST: {
435 default: return false;
439 bool CBitcoinAddress::IsPair() const {
443 case PUBKEY_PAIR_ADDRESS:
444 case PUBKEY_PAIR_ADDRESS_TEST: {
447 default: return false;
451 void CBitcoinSecret::SetSecret(const CSecret& vchSecret, bool fCompressed)
453 assert(vchSecret.size() == 32);
454 SetData(128 + (fTestNet ? CBitcoinAddress::PUBKEY_ADDRESS_TEST : CBitcoinAddress::PUBKEY_ADDRESS), &vchSecret[0], vchSecret.size());
456 vchData.push_back(1);
459 CSecret CBitcoinSecret::GetSecret(bool &fCompressedOut)
462 vchSecret.resize(32);
463 memcpy(&vchSecret[0], &vchData[0], 32);
464 fCompressedOut = vchData.size() == 33;
468 bool CBitcoinSecret::IsValid() const
470 bool fExpectTestNet = false;
473 case (128 + CBitcoinAddress::PUBKEY_ADDRESS):
476 case (128 + CBitcoinAddress::PUBKEY_ADDRESS_TEST):
477 fExpectTestNet = true;
483 return fExpectTestNet == fTestNet && (vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1));
486 bool CBitcoinSecret::SetString(const char* pszSecret)
488 return CBase58Data::SetString(pszSecret) && IsValid();
491 bool CBitcoinSecret::SetString(const std::string& strSecret)
493 return SetString(strSecret.c_str());
496 CBitcoinSecret::CBitcoinSecret(const CSecret& vchSecret, bool fCompressed)
498 SetSecret(vchSecret, fCompressed);