/src/key_io.cpp

https://github.com/vertcoin-project/vertcoin-core · C++ · 234 lines · 201 code · 23 blank · 10 comment · 54 complexity · 0644f57f9596dd4128c4bbb27f827087 MD5 · raw file

  1. // Copyright (c) 2014-2019 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 <key_io.h>
  5. #include <base58.h>
  6. #include <bech32.h>
  7. #include <util/strencodings.h>
  8. #include <boost/variant/apply_visitor.hpp>
  9. #include <boost/variant/static_visitor.hpp>
  10. #include <assert.h>
  11. #include <string.h>
  12. #include <algorithm>
  13. namespace
  14. {
  15. class DestinationEncoder : public boost::static_visitor<std::string>
  16. {
  17. private:
  18. const CChainParams& m_params;
  19. public:
  20. explicit DestinationEncoder(const CChainParams& params) : m_params(params) {}
  21. std::string operator()(const PKHash& id) const
  22. {
  23. std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
  24. data.insert(data.end(), id.begin(), id.end());
  25. return EncodeBase58Check(data);
  26. }
  27. std::string operator()(const ScriptHash& id) const
  28. {
  29. std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
  30. data.insert(data.end(), id.begin(), id.end());
  31. return EncodeBase58Check(data);
  32. }
  33. std::string operator()(const WitnessV0KeyHash& id) const
  34. {
  35. std::vector<unsigned char> data = {0};
  36. data.reserve(33);
  37. ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, id.begin(), id.end());
  38. return bech32::Encode(bech32::Encoding::BECH32, m_params.Bech32HRP(), data);
  39. }
  40. std::string operator()(const WitnessV0ScriptHash& id) const
  41. {
  42. std::vector<unsigned char> data = {0};
  43. data.reserve(53);
  44. ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, id.begin(), id.end());
  45. return bech32::Encode(bech32::Encoding::BECH32, m_params.Bech32HRP(), data);
  46. }
  47. std::string operator()(const WitnessUnknown& id) const
  48. {
  49. if (id.version < 1 || id.version > 16 || id.length < 2 || id.length > 40) {
  50. return {};
  51. }
  52. std::vector<unsigned char> data = {(unsigned char)id.version};
  53. data.reserve(1 + (id.length * 8 + 4) / 5);
  54. ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, id.program, id.program + id.length);
  55. return bech32::Encode(bech32::Encoding::BECH32M, m_params.Bech32HRP(), data);
  56. }
  57. std::string operator()(const CNoDestination& no) const { return {}; }
  58. };
  59. CTxDestination DecodeDestination(const std::string& str, const CChainParams& params)
  60. {
  61. std::vector<unsigned char> data;
  62. uint160 hash;
  63. if (DecodeBase58Check(str, data, 21)) {
  64. // base58-encoded Bitcoin addresses.
  65. // Public-key-hash-addresses have version 0 (or 111 testnet).
  66. // The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key.
  67. const std::vector<unsigned char>& pubkey_prefix = params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
  68. if (data.size() == hash.size() + pubkey_prefix.size() && std::equal(pubkey_prefix.begin(), pubkey_prefix.end(), data.begin())) {
  69. std::copy(data.begin() + pubkey_prefix.size(), data.end(), hash.begin());
  70. return PKHash(hash);
  71. }
  72. // Script-hash-addresses have version 5 (or 196 testnet).
  73. // The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script.
  74. const std::vector<unsigned char>& script_prefix = params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
  75. if (data.size() == hash.size() + script_prefix.size() && std::equal(script_prefix.begin(), script_prefix.end(), data.begin())) {
  76. std::copy(data.begin() + script_prefix.size(), data.end(), hash.begin());
  77. return ScriptHash(hash);
  78. }
  79. }
  80. data.clear();
  81. const auto dec = bech32::Decode(str);
  82. if ((dec.encoding == bech32::Encoding::BECH32 || dec.encoding == bech32::Encoding::BECH32M) && dec.data.size() > 0 && dec.hrp == params.Bech32HRP()) {
  83. // Bech32 decoding
  84. int version = dec.data[0]; // The first 5 bit symbol is the witness version (0-16)
  85. if (version == 0 && dec.encoding != bech32::Encoding::BECH32) {
  86. return CNoDestination();
  87. }
  88. if (version != 0 && dec.encoding != bech32::Encoding::BECH32M) {
  89. return CNoDestination();
  90. }
  91. // The rest of the symbols are converted witness program bytes.
  92. data.reserve(((dec.data.size() - 1) * 5) / 8);
  93. if (ConvertBits<5, 8, false>([&](unsigned char c) { data.push_back(c); }, dec.data.begin() + 1, dec.data.end())) {
  94. if (version == 0) {
  95. {
  96. WitnessV0KeyHash keyid;
  97. if (data.size() == keyid.size()) {
  98. std::copy(data.begin(), data.end(), keyid.begin());
  99. return keyid;
  100. }
  101. }
  102. {
  103. WitnessV0ScriptHash scriptid;
  104. if (data.size() == scriptid.size()) {
  105. std::copy(data.begin(), data.end(), scriptid.begin());
  106. return scriptid;
  107. }
  108. }
  109. return CNoDestination();
  110. }
  111. if (version > 16 || data.size() < 2 || data.size() > 40) {
  112. return CNoDestination();
  113. }
  114. WitnessUnknown unk;
  115. unk.version = version;
  116. std::copy(data.begin(), data.end(), unk.program);
  117. unk.length = data.size();
  118. return unk;
  119. }
  120. }
  121. return CNoDestination();
  122. }
  123. } // namespace
  124. CKey DecodeSecret(const std::string& str)
  125. {
  126. CKey key;
  127. std::vector<unsigned char> data;
  128. if (DecodeBase58Check(str, data, 34)) {
  129. const std::vector<unsigned char>& privkey_prefix = Params().Base58Prefix(CChainParams::SECRET_KEY);
  130. if ((data.size() == 32 + privkey_prefix.size() || (data.size() == 33 + privkey_prefix.size() && data.back() == 1)) &&
  131. std::equal(privkey_prefix.begin(), privkey_prefix.end(), data.begin())) {
  132. bool compressed = data.size() == 33 + privkey_prefix.size();
  133. key.Set(data.begin() + privkey_prefix.size(), data.begin() + privkey_prefix.size() + 32, compressed);
  134. }
  135. }
  136. if (!data.empty()) {
  137. memory_cleanse(data.data(), data.size());
  138. }
  139. return key;
  140. }
  141. std::string EncodeSecret(const CKey& key)
  142. {
  143. assert(key.IsValid());
  144. std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::SECRET_KEY);
  145. data.insert(data.end(), key.begin(), key.end());
  146. if (key.IsCompressed()) {
  147. data.push_back(1);
  148. }
  149. std::string ret = EncodeBase58Check(data);
  150. memory_cleanse(data.data(), data.size());
  151. return ret;
  152. }
  153. CExtPubKey DecodeExtPubKey(const std::string& str)
  154. {
  155. CExtPubKey key;
  156. std::vector<unsigned char> data;
  157. if (DecodeBase58Check(str, data, 78)) {
  158. const std::vector<unsigned char>& prefix = Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY);
  159. if (data.size() == BIP32_EXTKEY_SIZE + prefix.size() && std::equal(prefix.begin(), prefix.end(), data.begin())) {
  160. key.Decode(data.data() + prefix.size());
  161. }
  162. }
  163. return key;
  164. }
  165. std::string EncodeExtPubKey(const CExtPubKey& key)
  166. {
  167. std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY);
  168. size_t size = data.size();
  169. data.resize(size + BIP32_EXTKEY_SIZE);
  170. key.Encode(data.data() + size);
  171. std::string ret = EncodeBase58Check(data);
  172. return ret;
  173. }
  174. CExtKey DecodeExtKey(const std::string& str)
  175. {
  176. CExtKey key;
  177. std::vector<unsigned char> data;
  178. if (DecodeBase58Check(str, data, 78)) {
  179. const std::vector<unsigned char>& prefix = Params().Base58Prefix(CChainParams::EXT_SECRET_KEY);
  180. if (data.size() == BIP32_EXTKEY_SIZE + prefix.size() && std::equal(prefix.begin(), prefix.end(), data.begin())) {
  181. key.Decode(data.data() + prefix.size());
  182. }
  183. }
  184. return key;
  185. }
  186. std::string EncodeExtKey(const CExtKey& key)
  187. {
  188. std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::EXT_SECRET_KEY);
  189. size_t size = data.size();
  190. data.resize(size + BIP32_EXTKEY_SIZE);
  191. key.Encode(data.data() + size);
  192. std::string ret = EncodeBase58Check(data);
  193. memory_cleanse(data.data(), data.size());
  194. return ret;
  195. }
  196. std::string EncodeDestination(const CTxDestination& dest)
  197. {
  198. return boost::apply_visitor(DestinationEncoder(Params()), dest);
  199. }
  200. CTxDestination DecodeDestination(const std::string& str)
  201. {
  202. return DecodeDestination(str, Params());
  203. }
  204. bool IsValidDestinationString(const std::string& str, const CChainParams& params)
  205. {
  206. return IsValidDestination(DecodeDestination(str, params));
  207. }
  208. bool IsValidDestinationString(const std::string& str)
  209. {
  210. return IsValidDestinationString(str, Params());
  211. }