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.
22 static const std::array<char, 58> digits = {
23 '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
24 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
25 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm',
26 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
29 static const std::array<signed char, 128> characterMap = {
30 -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,
32 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
33 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8,-1,-1,-1,-1,-1,-1,
34 -1, 9,10,11,12,13,14,15,16,-1,17,18,19,20,21,-1,
35 22,23,24,25,26,27,28,29,30,31,32,-1,-1,-1,-1,-1,
36 -1,33,34,35,36,37,38,39,40,41,42,43,-1,44,45,46,
37 47,48,49,50,51,52,53,54,55,56,57,-1,-1,-1,-1,-1,
40 // Encode a byte sequence as a base58-encoded string
41 std::string EncodeBase58(const unsigned char* begin, const unsigned char* end)
43 // Skip & count leading zeroes.
46 while (begin != end && *begin == 0) {
51 // Allocate enough space in big-endian base58 representation.
52 auto base58Size = (end - begin) * 138 / 100 + 1; // log(256) / log(58), rounded up.
53 std::vector<unsigned char> b58(base58Size);
55 while (begin != end) {
58 // Apply "b58 = b58 * 256 + ch".
59 for (auto b58it = b58.rbegin(); (carry != 0 || i < length) && (b58it != b58.rend());
61 carry += 256 * (*b58it);
71 // Skip leading zeroes in base58 result.
72 auto it = b58.begin() + (base58Size - length);
73 while (it != b58.end() && *it == 0) {
77 // Translate the result into a string.
79 str.reserve(zeroes + (b58.end() - it));
80 str.assign(zeroes, digits[0]);
81 while (it != b58.end()) {
88 // Encode a byte vector as a base58-encoded string
89 std::string EncodeBase58(const std::vector<unsigned char>& vch)
91 return EncodeBase58(&vch[0], &vch[0] + vch.size());
94 // Decode a base58-encoded string psz into byte vector vchRet
95 // returns true if decoding is successful
96 bool DecodeBase58(const char* psz, std::vector<unsigned char>& vchRet)
99 const char* end = it + strlen(psz);
101 // Skip leading spaces.
102 it = std::find_if_not(it, end, [](char c) { return std::isspace(c);});
104 // Skip and count leading zeros.
105 std::size_t zeroes = 0;
106 std::size_t length = 0;
107 while (it != end && *it == digits[0]) {
112 // Allocate enough space in big-endian base256 representation.
113 std::size_t base258Size = (end - it) * 733 / 1000 + 1; // log(58) / log(256), rounded up.
114 std::vector<unsigned char> b256(base258Size);
116 // Process the characters.
117 while (it != end && !std::isspace(*it)) {
118 if (static_cast<unsigned char>(*it) >= 128) {
119 // Invalid b58 character
123 // Decode base58 character
124 int carry = characterMap[static_cast<unsigned char>(*it)];
126 // Invalid b58 character
131 for (auto b256it = b256.rbegin(); (carry != 0 || i < length) && (b256it != b256.rend());
133 carry += 58 * (*b256it);
134 *b256it = static_cast<uint8_t>(carry % 256);
142 // Skip trailing spaces.
143 it = std::find_if_not(it, end, [](char c) { return std::isspace(c);});
145 // Extra charaters at the end
149 // Skip leading zeroes in b256.
150 auto b256it = b256.begin() + (base258Size - length);
151 while (b256it != b256.end() && *b256it == 0) {
155 // Copy result into output vector.
156 vchRet.reserve(zeroes + (b256.end() - b256it));
157 vchRet.assign(zeroes, 0x00);
158 std::copy(b256it, b256.end(), std::back_inserter(vchRet));
163 // Decode a base58-encoded string str into byte vector vchRet
164 // returns true if decoding is successful
165 bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet)
167 return DecodeBase58(str.c_str(), vchRet);
170 // Encode a byte vector to a base58-encoded string, including checksum
171 std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
173 // add 4-byte hash check to the end
174 std::vector<unsigned char> vch(vchIn);
175 uint256 hash = Hash(vch.begin(), vch.end());
176 vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
177 return EncodeBase58(vch);
180 // Decode a base58-encoded string psz that includes a checksum, into byte vector vchRet
181 // returns true if decoding is successful
182 bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet)
184 if (!DecodeBase58(psz, vchRet))
186 if (vchRet.size() < 4)
191 uint256 hash = Hash(vchRet.begin(), vchRet.end()-4);
192 if (memcmp(&hash, &vchRet.end()[-4], 4) != 0)
197 vchRet.resize(vchRet.size()-4);
201 // Decode a base58-encoded string str that includes a checksum, into byte vector vchRet
202 // returns true if decoding is successful
203 bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet)
205 return DecodeBase58Check(str.c_str(), vchRet);
208 CBase58Data::CBase58Data()
214 CBase58Data::~CBase58Data()
216 // zero the memory, as it may contain sensitive data
217 if (!vchData.empty())
218 OPENSSL_cleanse(&vchData[0], vchData.size());
221 void CBase58Data::SetData(int nVersionIn, const void* pdata, size_t nSize)
223 nVersion = nVersionIn;
224 vchData.resize(nSize);
225 if (!vchData.empty())
226 memcpy(&vchData[0], pdata, nSize);
229 const std::vector<unsigned char> &CBase58Data::GetData() const
234 void CBase58Data::SetData(int nVersionIn, const unsigned char *pbegin, const unsigned char *pend)
236 SetData(nVersionIn, (void*)pbegin, pend - pbegin);
239 bool CBase58Data::SetString(const char* psz)
241 std::vector<unsigned char> vchTemp;
242 DecodeBase58Check(psz, vchTemp);
249 nVersion = vchTemp[0];
250 vchData.resize(vchTemp.size() - 1);
251 if (!vchData.empty())
252 memcpy(&vchData[0], &vchTemp[1], vchData.size());
253 OPENSSL_cleanse(&vchTemp[0], vchData.size());
257 bool CBase58Data::SetString(const std::string& str)
259 return SetString(str.c_str());
262 std::string CBase58Data::ToString() const
264 std::vector<unsigned char> vch(1, nVersion);
265 vch.insert(vch.end(), vchData.begin(), vchData.end());
266 return EncodeBase58Check(vch);
269 int CBase58Data::CompareTo(const CBase58Data& b58) const
271 if (nVersion < b58.nVersion) return -1;
272 if (nVersion > b58.nVersion) return 1;
273 if (vchData < b58.vchData) return -1;
274 if (vchData > b58.vchData) return 1;
278 bool CBitcoinAddress::Set(const CKeyID &id) {
279 SetData(fTestNet ? PUBKEY_ADDRESS_TEST : PUBKEY_ADDRESS, &id, 20);
283 bool CBitcoinAddress::Set(const CScriptID &id) {
284 SetData(fTestNet ? SCRIPT_ADDRESS_TEST : SCRIPT_ADDRESS, &id, 20);
288 bool CBitcoinAddress::Set(const CTxDestination &dest)
290 return boost::apply_visitor(CBitcoinAddressVisitor(this), dest);
293 bool CBitcoinAddress::Set(const CMalleablePubKey &mpk) {
294 std::vector<unsigned char> vchPubkeyPair = mpk.Raw();
295 SetData(fTestNet ? PUBKEY_PAIR_ADDRESS_TEST : PUBKEY_PAIR_ADDRESS, &vchPubkeyPair[0], 68);
299 bool CBitcoinAddress::Set(const CBitcoinAddress &dest)
301 nVersion = dest.nVersion;
302 vchData = dest.vchData;
306 bool CBitcoinAddress::IsValid() const
308 unsigned int nExpectedSize = 20;
309 bool fExpectTestNet = false;
313 case PUBKEY_PAIR_ADDRESS:
314 nExpectedSize = 68; // Serialized pair of public keys
315 fExpectTestNet = false;
319 nExpectedSize = 20; // Hash of public key
320 fExpectTestNet = false;
323 nExpectedSize = 20; // Hash of CScript
324 fExpectTestNet = false;
327 case PUBKEY_PAIR_ADDRESS_TEST:
329 fExpectTestNet = true;
332 case PUBKEY_ADDRESS_TEST:
334 fExpectTestNet = true;
336 case SCRIPT_ADDRESS_TEST:
338 fExpectTestNet = true;
345 // Basic format sanity check
346 bool fSeemsSane = (fExpectTestNet == fTestNet && vchData.size() == nExpectedSize);
348 if (fSeemsSane && !fSimple)
350 // Perform dditional checking
351 // for pubkey pair addresses
352 CMalleablePubKey mpk;
354 return mpk.IsValid();
360 CTxDestination CBitcoinAddress::Get() const {
362 return CNoDestination();
365 case PUBKEY_ADDRESS_TEST: {
367 memcpy(&id, &vchData[0], 20);
371 case SCRIPT_ADDRESS_TEST: {
373 memcpy(&id, &vchData[0], 20);
374 return CScriptID(id);
377 return CNoDestination();
380 bool CBitcoinAddress::GetKeyID(CKeyID &keyID) const {
385 case PUBKEY_ADDRESS_TEST: {
387 memcpy(&id, &vchData[0], 20);
391 case PUBKEY_PAIR_ADDRESS:
392 case PUBKEY_PAIR_ADDRESS_TEST:
394 CMalleablePubKey mPubKey;
395 mPubKey.setvch(vchData);
396 keyID = mPubKey.GetID();
399 default: return false;
403 bool CBitcoinAddress::IsScript() const {
408 case SCRIPT_ADDRESS_TEST: {
411 default: return false;
415 bool CBitcoinAddress::IsPubKey() const {
420 case PUBKEY_ADDRESS_TEST: {
423 default: return false;
427 bool CBitcoinAddress::IsPair() const {
431 case PUBKEY_PAIR_ADDRESS:
432 case PUBKEY_PAIR_ADDRESS_TEST: {
435 default: return false;
439 void CBitcoinSecret::SetSecret(const CSecret& vchSecret, bool fCompressed)
441 assert(vchSecret.size() == 32);
442 SetData(128 + (fTestNet ? CBitcoinAddress::PUBKEY_ADDRESS_TEST : CBitcoinAddress::PUBKEY_ADDRESS), &vchSecret[0], vchSecret.size());
444 vchData.push_back(1);
447 CSecret CBitcoinSecret::GetSecret(bool &fCompressedOut)
450 vchSecret.resize(32);
451 memcpy(&vchSecret[0], &vchData[0], 32);
452 fCompressedOut = vchData.size() == 33;
456 bool CBitcoinSecret::IsValid() const
458 bool fExpectTestNet = false;
461 case (128 + CBitcoinAddress::PUBKEY_ADDRESS):
464 case (128 + CBitcoinAddress::PUBKEY_ADDRESS_TEST):
465 fExpectTestNet = true;
471 return fExpectTestNet == fTestNet && (vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1));
474 bool CBitcoinSecret::SetString(const char* pszSecret)
476 return CBase58Data::SetString(pszSecret) && IsValid();
479 bool CBitcoinSecret::SetString(const std::string& strSecret)
481 return SetString(strSecret.c_str());
484 CBitcoinSecret::CBitcoinSecret(const CSecret& vchSecret, bool fCompressed)
486 SetSecret(vchSecret, fCompressed);