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
5 #include <key_io.h>
6
7 #include <base58.h>
8 #include <bech32.h>
9 #include <util/strencodings.h>
10
11 #include <boost/variant/apply_visitor.hpp>
12 #include <boost/variant/static_visitor.hpp>
13
14 #include <assert.h>
15 #include <string.h>
16 #include <algorithm>
17
18 namespace
19 {
20 class DestinationEncoder : public boost::static_visitor<std::string>
21 {
22 private:
23 const CChainParams& m_params;
24
25 public:
DestinationEncoder(const CChainParams & params)26 explicit DestinationEncoder(const CChainParams& params) : m_params(params) {}
27
operator ()(const PKHash & id) const28 std::string operator()(const PKHash& id) const
29 {
30 std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
31 data.insert(data.end(), id.begin(), id.end());
32 return EncodeBase58Check(data);
33 }
34
operator ()(const ScriptHash & id) const35 std::string operator()(const ScriptHash& id) const
36 {
37 std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
38 data.insert(data.end(), id.begin(), id.end());
39 return EncodeBase58Check(data);
40 }
41
operator ()(const WitnessV0KeyHash & id) const42 std::string operator()(const WitnessV0KeyHash& id) const
43 {
44 std::vector<unsigned char> data = {0};
45 data.reserve(33);
46 ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, id.begin(), id.end());
47 return bech32::Encode(m_params.Bech32HRP(), data);
48 }
49
operator ()(const WitnessV0ScriptHash & id) const50 std::string operator()(const WitnessV0ScriptHash& id) const
51 {
52 std::vector<unsigned char> data = {0};
53 data.reserve(53);
54 ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, id.begin(), id.end());
55 return bech32::Encode(m_params.Bech32HRP(), data);
56 }
57
operator ()(const WitnessUnknown & id) const58 std::string operator()(const WitnessUnknown& id) const
59 {
60 if (id.version < 1 || id.version > 16 || id.length < 2 || id.length > 40) {
61 return {};
62 }
63 std::vector<unsigned char> data = {(unsigned char)id.version};
64 data.reserve(1 + (id.length * 8 + 4) / 5);
65 ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, id.program, id.program + id.length);
66 return bech32::Encode(m_params.Bech32HRP(), data);
67 }
68
operator ()(const CNoDestination & no) const69 std::string operator()(const CNoDestination& no) const { return {}; }
70 };
71
DecodeDestination(const std::string & str,const CChainParams & params)72 CTxDestination DecodeDestination(const std::string& str, const CChainParams& params)
73 {
74 std::vector<unsigned char> data;
75 uint160 hash;
76 if (DecodeBase58Check(str, data, 21)) {
77 // base58-encoded Bitcoin addresses.
78 // Public-key-hash-addresses have version 0 (or 111 testnet).
79 // The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key.
80 const std::vector<unsigned char>& pubkey_prefix = params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
81 if (data.size() == hash.size() + pubkey_prefix.size() && std::equal(pubkey_prefix.begin(), pubkey_prefix.end(), data.begin())) {
82 std::copy(data.begin() + pubkey_prefix.size(), data.end(), hash.begin());
83 return PKHash(hash);
84 }
85 // Script-hash-addresses have version 5 (or 196 testnet).
86 // The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script.
87 const std::vector<unsigned char>& script_prefix = params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
88 if (data.size() == hash.size() + script_prefix.size() && std::equal(script_prefix.begin(), script_prefix.end(), data.begin())) {
89 std::copy(data.begin() + script_prefix.size(), data.end(), hash.begin());
90 return ScriptHash(hash);
91 }
92 }
93 data.clear();
94 auto bech = bech32::Decode(str);
95 if (bech.second.size() > 0 && bech.first == params.Bech32HRP()) {
96 // Bech32 decoding
97 int version = bech.second[0]; // The first 5 bit symbol is the witness version (0-16)
98 // The rest of the symbols are converted witness program bytes.
99 data.reserve(((bech.second.size() - 1) * 5) / 8);
100 if (ConvertBits<5, 8, false>([&](unsigned char c) { data.push_back(c); }, bech.second.begin() + 1, bech.second.end())) {
101 if (version == 0) {
102 {
103 WitnessV0KeyHash keyid;
104 if (data.size() == keyid.size()) {
105 std::copy(data.begin(), data.end(), keyid.begin());
106 return keyid;
107 }
108 }
109 {
110 WitnessV0ScriptHash scriptid;
111 if (data.size() == scriptid.size()) {
112 std::copy(data.begin(), data.end(), scriptid.begin());
113 return scriptid;
114 }
115 }
116 return CNoDestination();
117 }
118 if (version > 16 || data.size() < 2 || data.size() > 40) {
119 return CNoDestination();
120 }
121 WitnessUnknown unk;
122 unk.version = version;
123 std::copy(data.begin(), data.end(), unk.program);
124 unk.length = data.size();
125 return unk;
126 }
127 }
128 return CNoDestination();
129 }
130 } // namespace
131
DecodeSecret(const std::string & str)132 CKey DecodeSecret(const std::string& str)
133 {
134 CKey key;
135 std::vector<unsigned char> data;
136 if (DecodeBase58Check(str, data, 34)) {
137 const std::vector<unsigned char>& privkey_prefix = Params().Base58Prefix(CChainParams::SECRET_KEY);
138 if ((data.size() == 32 + privkey_prefix.size() || (data.size() == 33 + privkey_prefix.size() && data.back() == 1)) &&
139 std::equal(privkey_prefix.begin(), privkey_prefix.end(), data.begin())) {
140 bool compressed = data.size() == 33 + privkey_prefix.size();
141 key.Set(data.begin() + privkey_prefix.size(), data.begin() + privkey_prefix.size() + 32, compressed);
142 }
143 }
144 if (!data.empty()) {
145 memory_cleanse(data.data(), data.size());
146 }
147 return key;
148 }
149
EncodeSecret(const CKey & key)150 std::string EncodeSecret(const CKey& key)
151 {
152 assert(key.IsValid());
153 std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::SECRET_KEY);
154 data.insert(data.end(), key.begin(), key.end());
155 if (key.IsCompressed()) {
156 data.push_back(1);
157 }
158 std::string ret = EncodeBase58Check(data);
159 memory_cleanse(data.data(), data.size());
160 return ret;
161 }
162
DecodeExtPubKey(const std::string & str)163 CExtPubKey DecodeExtPubKey(const std::string& str)
164 {
165 CExtPubKey key;
166 std::vector<unsigned char> data;
167 if (DecodeBase58Check(str, data, 78)) {
168 const std::vector<unsigned char>& prefix = Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY);
169 if (data.size() == BIP32_EXTKEY_SIZE + prefix.size() && std::equal(prefix.begin(), prefix.end(), data.begin())) {
170 key.Decode(data.data() + prefix.size());
171 }
172 }
173 return key;
174 }
175
EncodeExtPubKey(const CExtPubKey & key)176 std::string EncodeExtPubKey(const CExtPubKey& key)
177 {
178 std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY);
179 size_t size = data.size();
180 data.resize(size + BIP32_EXTKEY_SIZE);
181 key.Encode(data.data() + size);
182 std::string ret = EncodeBase58Check(data);
183 return ret;
184 }
185
DecodeExtKey(const std::string & str)186 CExtKey DecodeExtKey(const std::string& str)
187 {
188 CExtKey key;
189 std::vector<unsigned char> data;
190 if (DecodeBase58Check(str, data, 78)) {
191 const std::vector<unsigned char>& prefix = Params().Base58Prefix(CChainParams::EXT_SECRET_KEY);
192 if (data.size() == BIP32_EXTKEY_SIZE + prefix.size() && std::equal(prefix.begin(), prefix.end(), data.begin())) {
193 key.Decode(data.data() + prefix.size());
194 }
195 }
196 return key;
197 }
198
EncodeExtKey(const CExtKey & key)199 std::string EncodeExtKey(const CExtKey& key)
200 {
201 std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::EXT_SECRET_KEY);
202 size_t size = data.size();
203 data.resize(size + BIP32_EXTKEY_SIZE);
204 key.Encode(data.data() + size);
205 std::string ret = EncodeBase58Check(data);
206 memory_cleanse(data.data(), data.size());
207 return ret;
208 }
209
EncodeDestination(const CTxDestination & dest)210 std::string EncodeDestination(const CTxDestination& dest)
211 {
212 return boost::apply_visitor(DestinationEncoder(Params()), dest);
213 }
214
DecodeDestination(const std::string & str)215 CTxDestination DecodeDestination(const std::string& str)
216 {
217 return DecodeDestination(str, Params());
218 }
219
IsValidDestinationString(const std::string & str,const CChainParams & params)220 bool IsValidDestinationString(const std::string& str, const CChainParams& params)
221 {
222 return IsValidDestination(DecodeDestination(str, params));
223 }
224
IsValidDestinationString(const std::string & str)225 bool IsValidDestinationString(const std::string& str)
226 {
227 return IsValidDestinationString(str, Params());
228 }
229
IsValidContractSenderAddressString(const std::string & str)230 bool IsValidContractSenderAddressString(const std::string& str)
231 {
232 return IsValidContractSenderAddress(DecodeDestination(str));
233 }
234
DecodeIndexKey(const std::string & str,uint256 & hashBytes,int & type)235 bool DecodeIndexKey(const std::string &str, uint256 &hashBytes, int &type)
236 {
237 CTxDestination dest = DecodeDestination(str);
238 if (IsValidDestination(dest))
239 {
240 const PKHash *keyID = boost::get<PKHash>(&dest);
241 if(keyID)
242 {
243 memcpy(&hashBytes, keyID, 20);
244 type = 1;
245 return true;
246 }
247
248 const ScriptHash *scriptID = boost::get<ScriptHash>(&dest);
249 if(scriptID)
250 {
251 memcpy(&hashBytes, scriptID, 20);
252 type = 2;
253 return true;
254 }
255
256 const WitnessV0ScriptHash *witnessV0ScriptID = boost::get<WitnessV0ScriptHash>(&dest);
257 if (witnessV0ScriptID) {
258 memcpy(&hashBytes, witnessV0ScriptID, 32);
259 type = 3;
260 return true;
261 }
262
263 const WitnessV0KeyHash *witnessV0KeyID = boost::get<WitnessV0KeyHash>(&dest);
264 if (witnessV0KeyID) {
265 memcpy(&hashBytes, witnessV0KeyID, 20);
266 type = 4;
267 return true;
268 }
269 }
270
271 return false;
272 }
273