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