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.
19 static const std::array<char, 58> digits = {
20 '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
21 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
22 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm',
23 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
26 static const std::array<signed char, 128> characterMap = {
27 -1,-1,-1,-1,-1,-1,-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,
29 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
30 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8,-1,-1,-1,-1,-1,-1,
31 -1, 9,10,11,12,13,14,15,16,-1,17,18,19,20,21,-1,
32 22,23,24,25,26,27,28,29,30,31,32,-1,-1,-1,-1,-1,
33 -1,33,34,35,36,37,38,39,40,41,42,43,-1,44,45,46,
34 47,48,49,50,51,52,53,54,55,56,57,-1,-1,-1,-1,-1,
37 // Encode a byte sequence as a base58-encoded string
38 std::string EncodeBase58(const unsigned char* begin, const unsigned char* end)
40 // Skip & count leading zeroes.
43 while (begin != end && *begin == 0) {
48 // Allocate enough space in big-endian base58 representation.
49 auto base58Size = (end - begin) * 138 / 100 + 1; // log(256) / log(58), rounded up.
50 std::vector<unsigned char> b58(base58Size);
52 while (begin != end) {
55 // Apply "b58 = b58 * 256 + ch".
56 for (auto b58it = b58.rbegin(); (carry != 0 || i < length) && (b58it != b58.rend());
58 carry += 256 * (*b58it);
68 // Skip leading zeroes in base58 result.
69 auto it = b58.begin() + (base58Size - length);
70 while (it != b58.end() && *it == 0) {
74 // Translate the result into a string.
76 str.reserve(zeroes + (b58.end() - it));
77 str.assign(zeroes, digits[0]);
78 while (it != b58.end()) {
85 // Encode a byte vector as a base58-encoded string
86 std::string EncodeBase58(const std::vector<unsigned char>& vch)
88 return EncodeBase58(&vch[0], &vch[0] + vch.size());
91 // Decode a base58-encoded string psz into byte vector vchRet
92 // returns true if decoding is successful
93 bool DecodeBase58(const char* psz, std::vector<unsigned char>& vchRet)
96 const char* end = it + strlen(psz);
98 // Skip leading spaces.
99 it = std::find_if_not(it, end, [](char c) { return std::isspace(c);});
101 // Skip and count leading zeros.
102 std::size_t zeroes = 0;
103 std::size_t length = 0;
104 while (it != end && *it == digits[0]) {
109 // Allocate enough space in big-endian base256 representation.
110 std::size_t base258Size = (end - it) * 733 / 1000 + 1; // log(58) / log(256), rounded up.
111 std::vector<unsigned char> b256(base258Size);
113 // Process the characters.
114 while (it != end && !std::isspace(*it)) {
115 if (static_cast<unsigned char>(*it) >= 128) {
116 // Invalid b58 character
120 // Decode base58 character
121 int carry = characterMap[static_cast<unsigned char>(*it)];
123 // Invalid b58 character
128 for (auto b256it = b256.rbegin(); (carry != 0 || i < length) && (b256it != b256.rend());
130 carry += 58 * (*b256it);
131 *b256it = static_cast<uint8_t>(carry % 256);
139 // Skip trailing spaces.
140 it = std::find_if_not(it, end, [](char c) { return std::isspace(c);});
142 // Extra charaters at the end
146 // Skip leading zeroes in b256.
147 auto b256it = b256.begin() + (base258Size - length);
148 while (b256it != b256.end() && *b256it == 0) {
152 // Copy result into output vector.
153 vchRet.reserve(zeroes + (b256.end() - b256it));
154 vchRet.assign(zeroes, 0x00);
155 std::copy(b256it, b256.end(), std::back_inserter(vchRet));
160 // Decode a base58-encoded string str into byte vector vchRet
161 // returns true if decoding is successful
162 bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet)
164 return DecodeBase58(str.c_str(), vchRet);
167 // Encode a byte vector to a base58-encoded string, including checksum
168 std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
170 // add 4-byte hash check to the end
171 std::vector<unsigned char> vch(vchIn);
172 uint256 hash = Hash(vch.begin(), vch.end());
173 vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
174 return EncodeBase58(vch);
177 // Decode a base58-encoded string psz that includes a checksum, into byte vector vchRet
178 // returns true if decoding is successful
179 bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet)
181 if (!DecodeBase58(psz, vchRet))
183 if (vchRet.size() < 4)
188 uint256 hash = Hash(vchRet.begin(), vchRet.end()-4);
189 if (memcmp(&hash, &vchRet.end()[-4], 4) != 0)
194 vchRet.resize(vchRet.size()-4);
198 // Decode a base58-encoded string str that includes a checksum, into byte vector vchRet
199 // returns true if decoding is successful
200 bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet)
202 return DecodeBase58Check(str.c_str(), vchRet);
205 CBase58Data::CBase58Data()
211 CBase58Data::~CBase58Data()
213 // zero the memory, as it may contain sensitive data
214 if (!vchData.empty())
215 OPENSSL_cleanse(&vchData[0], vchData.size());
218 void CBase58Data::SetData(int nVersionIn, const void* pdata, size_t nSize)
220 nVersion = nVersionIn;
221 vchData.resize(nSize);
222 if (!vchData.empty())
223 memcpy(&vchData[0], pdata, nSize);
226 const std::vector<unsigned char> &CBase58Data::GetData() const
231 void CBase58Data::SetData(int nVersionIn, const unsigned char *pbegin, const unsigned char *pend)
233 SetData(nVersionIn, (void*)pbegin, pend - pbegin);
236 bool CBase58Data::SetString(const char* psz)
238 std::vector<unsigned char> vchTemp;
239 DecodeBase58Check(psz, vchTemp);
246 nVersion = vchTemp[0];
247 vchData.resize(vchTemp.size() - 1);
248 if (!vchData.empty())
249 memcpy(&vchData[0], &vchTemp[1], vchData.size());
250 OPENSSL_cleanse(&vchTemp[0], vchData.size());
254 bool CBase58Data::SetString(const std::string& str)
256 return SetString(str.c_str());
259 std::string CBase58Data::ToString() const
261 std::vector<unsigned char> vch(1, nVersion);
262 vch.insert(vch.end(), vchData.begin(), vchData.end());
263 return EncodeBase58Check(vch);
266 int CBase58Data::CompareTo(const CBase58Data& b58) const
268 if (nVersion < b58.nVersion) return -1;
269 if (nVersion > b58.nVersion) return 1;
270 if (vchData < b58.vchData) return -1;
271 if (vchData > b58.vchData) return 1;
276 class CBitcoinAddressVisitor {
278 CBitcoinAddress *addr;
280 explicit CBitcoinAddressVisitor(CBitcoinAddress *addrIn) : addr(addrIn) { }
282 bool operator()(const CKeyID &id) const { return addr->Set(id); }
283 bool operator()(const CScriptID &id) const { return addr->Set(id); }
284 bool operator()(const CMalleablePubKey &mpk) const { return addr->Set(mpk); }
285 bool operator()([[maybe_unused]] const CNoDestination &no) const { return false; }
289 bool CBitcoinAddress::Set(const CKeyID &id) {
290 SetData(fTestNet ? PUBKEY_ADDRESS_TEST : PUBKEY_ADDRESS, &id, 20);
294 bool CBitcoinAddress::Set(const CScriptID &id) {
295 SetData(fTestNet ? SCRIPT_ADDRESS_TEST : SCRIPT_ADDRESS, &id, 20);
299 bool CBitcoinAddress::Set(const CTxDestination &dest)
301 return std::visit(CBitcoinAddressVisitor(this), dest);
304 bool CBitcoinAddress::Set(const CMalleablePubKey &mpk) {
305 std::vector<unsigned char> vchPubkeyPair = mpk.Raw();
306 SetData(fTestNet ? PUBKEY_PAIR_ADDRESS_TEST : PUBKEY_PAIR_ADDRESS, &vchPubkeyPair[0], 68);
310 bool CBitcoinAddress::Set(const CBitcoinAddress &dest)
312 nVersion = dest.nVersion;
313 vchData = dest.vchData;
317 bool CBitcoinAddress::IsValid() const
319 unsigned int nExpectedSize = 20;
320 bool fExpectTestNet = false;
324 case PUBKEY_PAIR_ADDRESS:
325 nExpectedSize = 68; // Serialized pair of public keys
326 fExpectTestNet = false;
330 nExpectedSize = 20; // Hash of public key
331 fExpectTestNet = false;
334 nExpectedSize = 20; // Hash of CScript
335 fExpectTestNet = false;
338 case PUBKEY_PAIR_ADDRESS_TEST:
340 fExpectTestNet = true;
343 case PUBKEY_ADDRESS_TEST:
345 fExpectTestNet = true;
347 case SCRIPT_ADDRESS_TEST:
349 fExpectTestNet = true;
356 // Basic format sanity check
357 bool fSeemsSane = (fExpectTestNet == fTestNet && vchData.size() == nExpectedSize);
359 if (fSeemsSane && !fSimple)
361 // Perform additional checking
362 // for pubkey pair addresses
363 CMalleablePubKey mpk;
365 return mpk.IsValid();
371 CTxDestination CBitcoinAddress::Get() const {
373 return CNoDestination();
376 case PUBKEY_ADDRESS_TEST: {
378 memcpy(&id, &vchData[0], 20);
382 case SCRIPT_ADDRESS_TEST: {
384 memcpy(&id, &vchData[0], 20);
385 return CScriptID(id);
388 return CNoDestination();
391 bool CBitcoinAddress::GetKeyID(CKeyID &keyID) const {
396 case PUBKEY_ADDRESS_TEST: {
398 memcpy(&id, &vchData[0], 20);
402 case PUBKEY_PAIR_ADDRESS:
403 case PUBKEY_PAIR_ADDRESS_TEST:
405 CMalleablePubKey mPubKey;
406 mPubKey.setvch(vchData);
407 keyID = mPubKey.GetID();
410 default: return false;
414 bool CBitcoinAddress::IsScript() const {
419 case SCRIPT_ADDRESS_TEST: {
422 default: return false;
426 bool CBitcoinAddress::IsPubKey() const {
431 case PUBKEY_ADDRESS_TEST: {
434 default: return false;
438 bool CBitcoinAddress::IsPair() const {
442 case PUBKEY_PAIR_ADDRESS:
443 case PUBKEY_PAIR_ADDRESS_TEST: {
446 default: return false;
450 void CBitcoinSecret::SetSecret(const CSecret& vchSecret, bool fCompressed)
452 assert(vchSecret.size() == 32);
453 SetData(128 + (fTestNet ? CBitcoinAddress::PUBKEY_ADDRESS_TEST : CBitcoinAddress::PUBKEY_ADDRESS), &vchSecret[0], vchSecret.size());
455 vchData.push_back(1);
458 CSecret CBitcoinSecret::GetSecret(bool &fCompressedOut)
461 vchSecret.resize(32);
462 memcpy(&vchSecret[0], &vchData[0], 32);
463 fCompressedOut = vchData.size() == 33;
467 bool CBitcoinSecret::IsValid() const
469 bool fExpectTestNet = false;
472 case (128 + CBitcoinAddress::PUBKEY_ADDRESS):
475 case (128 + CBitcoinAddress::PUBKEY_ADDRESS_TEST):
476 fExpectTestNet = true;
482 return fExpectTestNet == fTestNet && (vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1));
485 bool CBitcoinSecret::SetString(const char* pszSecret)
487 return CBase58Data::SetString(pszSecret) && IsValid();
490 bool CBitcoinSecret::SetString(const std::string& strSecret)
492 return SetString(strSecret.c_str());
495 CBitcoinSecret::CBitcoinSecret(const CSecret& vchSecret, bool fCompressed)
497 SetSecret(vchSecret, fCompressed);