base58.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. // Copyright (c) 2014 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. #include "base58.h"
  5. #include "hash.h"
  6. #include "uint256.h"
  7. #include "version.h"
  8. #include "streams.h"
  9. #include <assert.h>
  10. #include <stdint.h>
  11. #include <string.h>
  12. #include <vector>
  13. #include <string>
  14. #include <boost/variant/apply_visitor.hpp>
  15. #include <boost/variant/static_visitor.hpp>
  16. /** All alphanumeric characters except for "0", "I", "O", and "l" */
  17. static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
  18. bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch)
  19. {
  20. // Skip leading spaces.
  21. while (*psz && isspace(*psz))
  22. psz++;
  23. // Skip and count leading '1's.
  24. int zeroes = 0;
  25. while (*psz == '1') {
  26. zeroes++;
  27. psz++;
  28. }
  29. // Allocate enough space in big-endian base256 representation.
  30. std::vector<unsigned char> b256(strlen(psz) * 733 / 1000 + 1); // log(58) / log(256), rounded up.
  31. // Process the characters.
  32. while (*psz && !isspace(*psz)) {
  33. // Decode base58 character
  34. const char* ch = strchr(pszBase58, *psz);
  35. if (ch == NULL)
  36. return false;
  37. // Apply "b256 = b256 * 58 + ch".
  38. int carry = ch - pszBase58;
  39. for (std::vector<unsigned char>::reverse_iterator it = b256.rbegin(); it != b256.rend(); it++) {
  40. carry += 58 * (*it);
  41. *it = carry % 256;
  42. carry /= 256;
  43. }
  44. assert(carry == 0);
  45. psz++;
  46. }
  47. // Skip trailing spaces.
  48. while (isspace(*psz))
  49. psz++;
  50. if (*psz != 0)
  51. return false;
  52. // Skip leading zeroes in b256.
  53. std::vector<unsigned char>::iterator it = b256.begin();
  54. while (it != b256.end() && *it == 0)
  55. it++;
  56. // Copy result into output vector.
  57. vch.reserve(zeroes + (b256.end() - it));
  58. vch.assign(zeroes, 0x00);
  59. while (it != b256.end())
  60. vch.push_back(*(it++));
  61. return true;
  62. }
  63. std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend)
  64. {
  65. // Skip & count leading zeroes.
  66. int zeroes = 0;
  67. while (pbegin != pend && *pbegin == 0) {
  68. pbegin++;
  69. zeroes++;
  70. }
  71. // Allocate enough space in big-endian base58 representation.
  72. std::vector<unsigned char> b58((pend - pbegin) * 138 / 100 + 1); // log(256) / log(58), rounded up.
  73. // Process the bytes.
  74. while (pbegin != pend) {
  75. int carry = *pbegin;
  76. // Apply "b58 = b58 * 256 + ch".
  77. for (std::vector<unsigned char>::reverse_iterator it = b58.rbegin(); it != b58.rend(); it++) {
  78. carry += 256 * (*it);
  79. *it = carry % 58;
  80. carry /= 58;
  81. }
  82. assert(carry == 0);
  83. pbegin++;
  84. }
  85. // Skip leading zeroes in base58 result.
  86. std::vector<unsigned char>::iterator it = b58.begin();
  87. while (it != b58.end() && *it == 0)
  88. it++;
  89. // Translate the result into a string.
  90. std::string str;
  91. str.reserve(zeroes + (b58.end() - it));
  92. str.assign(zeroes, '1');
  93. while (it != b58.end())
  94. str += pszBase58[*(it++)];
  95. return str;
  96. }
  97. std::string EncodeBase58(const std::vector<unsigned char>& vch)
  98. {
  99. return EncodeBase58(&vch[0], &vch[0] + vch.size());
  100. }
  101. bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet)
  102. {
  103. return DecodeBase58(str.c_str(), vchRet);
  104. }
  105. std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
  106. {
  107. // add 4-byte hash check to the end
  108. std::vector<unsigned char> vch(vchIn);
  109. uint256 hash = Hash(vch.begin(), vch.end());
  110. vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
  111. return EncodeBase58(vch);
  112. }
  113. bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet)
  114. {
  115. if (!DecodeBase58(psz, vchRet) ||
  116. (vchRet.size() < 4)) {
  117. vchRet.clear();
  118. return false;
  119. }
  120. // re-calculate the checksum, insure it matches the included 4-byte checksum
  121. uint256 hash = Hash(vchRet.begin(), vchRet.end() - 4);
  122. if (memcmp(&hash, &vchRet.end()[-4], 4) != 0) {
  123. vchRet.clear();
  124. return false;
  125. }
  126. vchRet.resize(vchRet.size() - 4);
  127. return true;
  128. }
  129. bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet)
  130. {
  131. return DecodeBase58Check(str.c_str(), vchRet);
  132. }
  133. CBase58Data::CBase58Data()
  134. {
  135. vchVersion.clear();
  136. vchData.clear();
  137. }
  138. void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const void* pdata, size_t nSize)
  139. {
  140. vchVersion = vchVersionIn;
  141. vchData.resize(nSize);
  142. if (!vchData.empty())
  143. memcpy(&vchData[0], pdata, nSize);
  144. }
  145. void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const unsigned char* pbegin, const unsigned char* pend)
  146. {
  147. SetData(vchVersionIn, (void*)pbegin, pend - pbegin);
  148. }
  149. bool CBase58Data::SetString(const char* psz, unsigned int nVersionBytes)
  150. {
  151. std::vector<unsigned char> vchTemp;
  152. bool rc58 = DecodeBase58Check(psz, vchTemp);
  153. if ((!rc58) || (vchTemp.size() < nVersionBytes)) {
  154. vchData.clear();
  155. vchVersion.clear();
  156. return false;
  157. }
  158. vchVersion.assign(vchTemp.begin(), vchTemp.begin() + nVersionBytes);
  159. vchData.resize(vchTemp.size() - nVersionBytes);
  160. if (!vchData.empty())
  161. memcpy(&vchData[0], &vchTemp[nVersionBytes], vchData.size());
  162. memory_cleanse(&vchTemp[0], vchData.size());
  163. return true;
  164. }
  165. bool CBase58Data::SetString(const std::string& str, unsigned int nVersionBytes)
  166. {
  167. return SetString(str.c_str(), nVersionBytes);
  168. }
  169. std::string CBase58Data::ToString() const
  170. {
  171. std::vector<unsigned char> vch = vchVersion;
  172. vch.insert(vch.end(), vchData.begin(), vchData.end());
  173. return EncodeBase58Check(vch);
  174. }
  175. int CBase58Data::CompareTo(const CBase58Data& b58) const
  176. {
  177. if (vchVersion < b58.vchVersion)
  178. return -1;
  179. if (vchVersion > b58.vchVersion)
  180. return 1;
  181. if (vchData < b58.vchData)
  182. return -1;
  183. if (vchData > b58.vchData)
  184. return 1;
  185. return 0;
  186. }
  187. namespace
  188. {
  189. class CBitcoinAddressVisitor : public boost::static_visitor<bool>
  190. {
  191. private:
  192. CBitcoinAddress* addr;
  193. public:
  194. CBitcoinAddressVisitor(CBitcoinAddress* addrIn) : addr(addrIn) {}
  195. bool operator()(const CKeyID& id) const { return addr->Set(id); }
  196. bool operator()(const CScriptID& id) const { return addr->Set(id); }
  197. bool operator()(const CNoDestination& no) const { return false; }
  198. };
  199. } // anon namespace
  200. bool CBitcoinAddress::Set(const CKeyID& id)
  201. {
  202. SetData(Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS), &id, 20);
  203. return true;
  204. }
  205. bool CBitcoinAddress::Set(const CScriptID& id)
  206. {
  207. SetData(Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS), &id, 20);
  208. return true;
  209. }
  210. bool CBitcoinAddress::Set(const CTxDestination& dest)
  211. {
  212. return boost::apply_visitor(CBitcoinAddressVisitor(this), dest);
  213. }
  214. bool CBitcoinAddress::IsValid() const
  215. {
  216. return IsValid(Params());
  217. }
  218. bool CBitcoinAddress::IsValid(const CChainParams& params) const
  219. {
  220. bool fCorrectSize = vchData.size() == 20;
  221. bool fKnownVersion = vchVersion == params.Base58Prefix(CChainParams::PUBKEY_ADDRESS) ||
  222. vchVersion == params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
  223. return fCorrectSize && fKnownVersion;
  224. }
  225. bool CBitcoinAddress::SetString(const char* pszAddress)
  226. {
  227. return CBase58Data::SetString(pszAddress, 2);
  228. }
  229. bool CBitcoinAddress::SetString(const std::string& strAddress)
  230. {
  231. return SetString(strAddress.c_str());
  232. }
  233. CTxDestination CBitcoinAddress::Get() const
  234. {
  235. if (!IsValid())
  236. return CNoDestination();
  237. uint160 id;
  238. memcpy(&id, &vchData[0], 20);
  239. if (vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
  240. return CKeyID(id);
  241. else if (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS))
  242. return CScriptID(id);
  243. else
  244. return CNoDestination();
  245. }
  246. bool CBitcoinAddress::GetKeyID(CKeyID& keyID) const
  247. {
  248. if (!IsValid() || vchVersion != Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
  249. return false;
  250. uint160 id;
  251. memcpy(&id, &vchData[0], 20);
  252. keyID = CKeyID(id);
  253. return true;
  254. }
  255. bool CBitcoinAddress::IsScript() const
  256. {
  257. return IsValid() && vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS);
  258. }
  259. void CBitcoinSecret::SetKey(const CKey& vchSecret)
  260. {
  261. assert(vchSecret.IsValid());
  262. SetData(Params().Base58Prefix(CChainParams::SECRET_KEY), vchSecret.begin(), vchSecret.size());
  263. if (vchSecret.IsCompressed())
  264. vchData.push_back(1);
  265. }
  266. CKey CBitcoinSecret::GetKey()
  267. {
  268. CKey ret;
  269. assert(vchData.size() >= 32);
  270. ret.Set(vchData.begin(), vchData.begin() + 32, vchData.size() > 32 && vchData[32] == 1);
  271. return ret;
  272. }
  273. bool CBitcoinSecret::IsValid() const
  274. {
  275. bool fExpectedFormat = vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1);
  276. bool fCorrectVersion = vchVersion == Params().Base58Prefix(CChainParams::SECRET_KEY);
  277. return fExpectedFormat && fCorrectVersion;
  278. }
  279. bool CBitcoinSecret::SetString(const char* pszSecret)
  280. {
  281. return CBase58Data::SetString(pszSecret, 1) && IsValid();
  282. }
  283. bool CBitcoinSecret::SetString(const std::string& strSecret)
  284. {
  285. return SetString(strSecret.c_str());
  286. }
  287. bool CZCPaymentAddress::Set(const libzcash::PaymentAddress& addr)
  288. {
  289. CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
  290. ss << addr;
  291. std::vector<unsigned char> addrSerialized(ss.begin(), ss.end());
  292. assert(addrSerialized.size() == libzcash::SerializedPaymentAddressSize);
  293. SetData(Params().Base58Prefix(CChainParams::ZCPAYMENT_ADDRRESS), &addrSerialized[0], libzcash::SerializedPaymentAddressSize);
  294. return true;
  295. }
  296. libzcash::PaymentAddress CZCPaymentAddress::Get() const
  297. {
  298. if (vchData.size() != libzcash::SerializedPaymentAddressSize) {
  299. throw std::runtime_error(
  300. "payment address is invalid"
  301. );
  302. }
  303. if (vchVersion != Params().Base58Prefix(CChainParams::ZCPAYMENT_ADDRRESS)) {
  304. throw std::runtime_error(
  305. "payment address is for wrong network type"
  306. );
  307. }
  308. std::vector<unsigned char> serialized(vchData.begin(), vchData.end());
  309. CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION);
  310. libzcash::PaymentAddress ret;
  311. ss >> ret;
  312. return ret;
  313. }
  314. bool CZCSpendingKey::Set(const libzcash::SpendingKey& addr)
  315. {
  316. CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
  317. ss << addr;
  318. std::vector<unsigned char> addrSerialized(ss.begin(), ss.end());
  319. assert(addrSerialized.size() == libzcash::SerializedSpendingKeySize);
  320. SetData(Params().Base58Prefix(CChainParams::ZCSPENDING_KEY), &addrSerialized[0], libzcash::SerializedSpendingKeySize);
  321. return true;
  322. }
  323. libzcash::SpendingKey CZCSpendingKey::Get() const
  324. {
  325. if (vchData.size() != libzcash::SerializedSpendingKeySize) {
  326. throw std::runtime_error(
  327. "spending key is invalid"
  328. );
  329. }
  330. if (vchVersion != Params().Base58Prefix(CChainParams::ZCSPENDING_KEY)) {
  331. throw std::runtime_error(
  332. "spending key is for wrong network type"
  333. );
  334. }
  335. std::vector<unsigned char> serialized(vchData.begin(), vchData.end());
  336. CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION);
  337. libzcash::SpendingKey ret;
  338. ss >> ret;
  339. return ret;
  340. }