/root/bitcoin/src/key_io.cpp
Line | Count | Source |
1 | | // Copyright (c) 2014-present 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 <script/interpreter.h> |
10 | | #include <script/solver.h> |
11 | | #include <tinyformat.h> |
12 | | #include <util/overflow.h> |
13 | | #include <util/strencodings.h> |
14 | | |
15 | | #include <algorithm> |
16 | | #include <cassert> |
17 | | #include <cstring> |
18 | | |
19 | | /// Maximum witness length for Bech32 addresses. |
20 | | static constexpr std::size_t BECH32_WITNESS_PROG_MAX_LEN = 40; |
21 | | |
22 | | namespace { |
23 | | class DestinationEncoder |
24 | | { |
25 | | private: |
26 | | const CChainParams& m_params; |
27 | | |
28 | | public: |
29 | 0 | explicit DestinationEncoder(const CChainParams& params) : m_params(params) {} |
30 | | |
31 | | std::string operator()(const PKHash& id) const |
32 | 0 | { |
33 | 0 | std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::PUBKEY_ADDRESS); |
34 | 0 | data.insert(data.end(), id.begin(), id.end()); |
35 | 0 | return EncodeBase58Check(data); |
36 | 0 | } |
37 | | |
38 | | std::string operator()(const ScriptHash& id) const |
39 | 0 | { |
40 | 0 | std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::SCRIPT_ADDRESS); |
41 | 0 | data.insert(data.end(), id.begin(), id.end()); |
42 | 0 | return EncodeBase58Check(data); |
43 | 0 | } |
44 | | |
45 | | std::string operator()(const WitnessV0KeyHash& id) const |
46 | 0 | { |
47 | 0 | std::vector<unsigned char> data = {0}; |
48 | 0 | data.reserve(33); |
49 | 0 | ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, id.begin(), id.end()); |
50 | 0 | return bech32::Encode(bech32::Encoding::BECH32, m_params.Bech32HRP(), data); |
51 | 0 | } |
52 | | |
53 | | std::string operator()(const WitnessV0ScriptHash& id) const |
54 | 0 | { |
55 | 0 | std::vector<unsigned char> data = {0}; |
56 | 0 | data.reserve(53); |
57 | 0 | ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, id.begin(), id.end()); |
58 | 0 | return bech32::Encode(bech32::Encoding::BECH32, m_params.Bech32HRP(), data); |
59 | 0 | } |
60 | | |
61 | | std::string operator()(const WitnessV1Taproot& tap) const |
62 | 0 | { |
63 | 0 | std::vector<unsigned char> data = {1}; |
64 | 0 | data.reserve(53); |
65 | 0 | ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, tap.begin(), tap.end()); |
66 | 0 | return bech32::Encode(bech32::Encoding::BECH32M, m_params.Bech32HRP(), data); |
67 | 0 | } |
68 | | |
69 | | std::string operator()(const WitnessUnknown& id) const |
70 | 0 | { |
71 | 0 | const std::vector<unsigned char>& program = id.GetWitnessProgram(); |
72 | 0 | if (id.GetWitnessVersion() < 1 || id.GetWitnessVersion() > 16 || program.size() < 2 || program.size() > 40) { |
73 | 0 | return {}; |
74 | 0 | } |
75 | 0 | std::vector<unsigned char> data = {(unsigned char)id.GetWitnessVersion()}; |
76 | 0 | data.reserve(1 + CeilDiv(program.size() * 8, 5u)); |
77 | 0 | ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, program.begin(), program.end()); |
78 | 0 | return bech32::Encode(bech32::Encoding::BECH32M, m_params.Bech32HRP(), data); |
79 | 0 | } |
80 | | |
81 | 0 | std::string operator()(const CNoDestination& no) const { return {}; } |
82 | 0 | std::string operator()(const PubKeyDestination& pk) const { return {}; } |
83 | | }; |
84 | | |
85 | | CTxDestination DecodeDestination(const std::string& str, const CChainParams& params, std::string& error_str, std::vector<int>* error_locations) |
86 | 0 | { |
87 | 0 | std::vector<unsigned char> data; |
88 | 0 | uint160 hash; |
89 | 0 | error_str = ""; |
90 | | |
91 | | // Note this will be false if it is a valid Bech32 address for a different network |
92 | 0 | bool is_bech32 = (ToLower(str.substr(0, params.Bech32HRP().size())) == params.Bech32HRP()); |
93 | |
|
94 | 0 | if (!is_bech32 && DecodeBase58Check(str, data, 21)) { |
95 | | // base58-encoded Bitcoin addresses. |
96 | | // Public-key-hash-addresses have version 0 (or 111 testnet). |
97 | | // The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key. |
98 | 0 | const std::vector<unsigned char>& pubkey_prefix = params.Base58Prefix(CChainParams::PUBKEY_ADDRESS); |
99 | 0 | if (data.size() == hash.size() + pubkey_prefix.size() && std::equal(pubkey_prefix.begin(), pubkey_prefix.end(), data.begin())) { |
100 | 0 | std::copy(data.begin() + pubkey_prefix.size(), data.end(), hash.begin()); |
101 | 0 | return PKHash(hash); |
102 | 0 | } |
103 | | // Script-hash-addresses have version 5 (or 196 testnet). |
104 | | // The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script. |
105 | 0 | const std::vector<unsigned char>& script_prefix = params.Base58Prefix(CChainParams::SCRIPT_ADDRESS); |
106 | 0 | if (data.size() == hash.size() + script_prefix.size() && std::equal(script_prefix.begin(), script_prefix.end(), data.begin())) { |
107 | 0 | std::copy(data.begin() + script_prefix.size(), data.end(), hash.begin()); |
108 | 0 | return ScriptHash(hash); |
109 | 0 | } |
110 | | |
111 | | // If the prefix of data matches either the script or pubkey prefix, the length must have been wrong |
112 | 0 | if ((data.size() >= script_prefix.size() && |
113 | 0 | std::equal(script_prefix.begin(), script_prefix.end(), data.begin())) || |
114 | 0 | (data.size() >= pubkey_prefix.size() && |
115 | 0 | std::equal(pubkey_prefix.begin(), pubkey_prefix.end(), data.begin()))) { |
116 | 0 | error_str = "Invalid length for Base58 address (P2PKH or P2SH)"; |
117 | 0 | } else { |
118 | 0 | error_str = "Invalid or unsupported Base58-encoded address."; |
119 | 0 | } |
120 | 0 | return CNoDestination(); |
121 | 0 | } else if (!is_bech32) { |
122 | | // Try Base58 decoding without the checksum, using a much larger max length |
123 | 0 | if (!DecodeBase58(str, data, 100)) { |
124 | 0 | error_str = "Invalid or unsupported Segwit (Bech32) or Base58 encoding."; |
125 | 0 | } else { |
126 | 0 | error_str = "Invalid checksum or length of Base58 address (P2PKH or P2SH)"; |
127 | 0 | } |
128 | 0 | return CNoDestination(); |
129 | 0 | } |
130 | | |
131 | 0 | data.clear(); |
132 | 0 | const auto dec = bech32::Decode(str); |
133 | 0 | if (dec.encoding == bech32::Encoding::BECH32 || dec.encoding == bech32::Encoding::BECH32M) { |
134 | 0 | if (dec.data.empty()) { |
135 | 0 | error_str = "Empty Bech32 data section"; |
136 | 0 | return CNoDestination(); |
137 | 0 | } |
138 | | // Bech32 decoding |
139 | 0 | if (dec.hrp != params.Bech32HRP()) { |
140 | 0 | error_str = strprintf("Invalid or unsupported prefix for Segwit (Bech32) address (expected %s, got %s).", params.Bech32HRP(), dec.hrp);Line | Count | Source | 1172 | 0 | #define strprintf tfm::format |
|
141 | 0 | return CNoDestination(); |
142 | 0 | } |
143 | 0 | int version = dec.data[0]; // The first 5 bit symbol is the witness version (0-16) |
144 | 0 | if (version == 0 && dec.encoding != bech32::Encoding::BECH32) { |
145 | 0 | error_str = "Version 0 witness address must use Bech32 checksum"; |
146 | 0 | return CNoDestination(); |
147 | 0 | } |
148 | 0 | if (version != 0 && dec.encoding != bech32::Encoding::BECH32M) { |
149 | 0 | error_str = "Version 1+ witness address must use Bech32m checksum"; |
150 | 0 | return CNoDestination(); |
151 | 0 | } |
152 | | // The rest of the symbols are converted witness program bytes. |
153 | 0 | data.reserve(((dec.data.size() - 1) * 5) / 8); |
154 | 0 | if (ConvertBits<5, 8, false>([&](unsigned char c) { data.push_back(c); }, dec.data.begin() + 1, dec.data.end())) { |
155 | |
|
156 | 0 | std::string_view byte_str{data.size() == 1 ? "byte" : "bytes"}; |
157 | |
|
158 | 0 | if (version == 0) { |
159 | 0 | { |
160 | 0 | WitnessV0KeyHash keyid; |
161 | 0 | if (data.size() == keyid.size()) { |
162 | 0 | std::copy(data.begin(), data.end(), keyid.begin()); |
163 | 0 | return keyid; |
164 | 0 | } |
165 | 0 | } |
166 | 0 | { |
167 | 0 | WitnessV0ScriptHash scriptid; |
168 | 0 | if (data.size() == scriptid.size()) { |
169 | 0 | std::copy(data.begin(), data.end(), scriptid.begin()); |
170 | 0 | return scriptid; |
171 | 0 | } |
172 | 0 | } |
173 | | |
174 | 0 | error_str = strprintf("Invalid Bech32 v0 address program size (%d %s), per BIP141", data.size(), byte_str);Line | Count | Source | 1172 | 0 | #define strprintf tfm::format |
|
175 | 0 | return CNoDestination(); |
176 | 0 | } |
177 | | |
178 | 0 | if (version == 1 && data.size() == WITNESS_V1_TAPROOT_SIZE) { |
179 | 0 | static_assert(WITNESS_V1_TAPROOT_SIZE == WitnessV1Taproot::size()); |
180 | 0 | WitnessV1Taproot tap; |
181 | 0 | std::copy(data.begin(), data.end(), tap.begin()); |
182 | 0 | return tap; |
183 | 0 | } |
184 | | |
185 | 0 | if (CScript::IsPayToAnchor(version, data)) { |
186 | 0 | return PayToAnchor(); |
187 | 0 | } |
188 | | |
189 | 0 | if (version > 16) { |
190 | 0 | error_str = "Invalid Bech32 address witness version"; |
191 | 0 | return CNoDestination(); |
192 | 0 | } |
193 | | |
194 | 0 | if (data.size() < 2 || data.size() > BECH32_WITNESS_PROG_MAX_LEN) { |
195 | 0 | error_str = strprintf("Invalid Bech32 address program size (%d %s)", data.size(), byte_str);Line | Count | Source | 1172 | 0 | #define strprintf tfm::format |
|
196 | 0 | return CNoDestination(); |
197 | 0 | } |
198 | | |
199 | 0 | return WitnessUnknown{version, data}; |
200 | 0 | } else { |
201 | 0 | error_str = strprintf("Invalid padding in Bech32 data section");Line | Count | Source | 1172 | 0 | #define strprintf tfm::format |
|
202 | 0 | return CNoDestination(); |
203 | 0 | } |
204 | 0 | } |
205 | | |
206 | | // Perform Bech32 error location |
207 | 0 | auto res = bech32::LocateErrors(str); |
208 | 0 | error_str = res.first; |
209 | 0 | if (error_locations) *error_locations = std::move(res.second); |
210 | 0 | return CNoDestination(); |
211 | 0 | } |
212 | | } // namespace |
213 | | |
214 | | CKey DecodeSecret(const std::string& str) |
215 | 0 | { |
216 | 0 | CKey key; |
217 | 0 | std::vector<unsigned char> data; |
218 | 0 | if (DecodeBase58Check(str, data, 34)) { |
219 | 0 | const std::vector<unsigned char>& privkey_prefix = Params().Base58Prefix(CChainParams::SECRET_KEY); |
220 | 0 | if ((data.size() == 32 + privkey_prefix.size() || (data.size() == 33 + privkey_prefix.size() && data.back() == 1)) && |
221 | 0 | std::equal(privkey_prefix.begin(), privkey_prefix.end(), data.begin())) { |
222 | 0 | bool compressed = data.size() == 33 + privkey_prefix.size(); |
223 | 0 | key.Set(data.begin() + privkey_prefix.size(), data.begin() + privkey_prefix.size() + 32, compressed); |
224 | 0 | } |
225 | 0 | } |
226 | 0 | if (!data.empty()) { |
227 | 0 | memory_cleanse(data.data(), data.size()); |
228 | 0 | } |
229 | 0 | return key; |
230 | 0 | } |
231 | | |
232 | | std::string EncodeSecret(const CKey& key) |
233 | 0 | { |
234 | 0 | assert(key.IsValid()); |
235 | 0 | std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::SECRET_KEY); |
236 | 0 | data.insert(data.end(), UCharCast(key.begin()), UCharCast(key.end())); |
237 | 0 | if (key.IsCompressed()) { |
238 | 0 | data.push_back(1); |
239 | 0 | } |
240 | 0 | std::string ret = EncodeBase58Check(data); |
241 | 0 | memory_cleanse(data.data(), data.size()); |
242 | 0 | return ret; |
243 | 0 | } |
244 | | |
245 | | CExtPubKey DecodeExtPubKey(const std::string& str) |
246 | 0 | { |
247 | 0 | CExtPubKey key; |
248 | 0 | std::vector<unsigned char> data; |
249 | 0 | if (DecodeBase58Check(str, data, 78)) { |
250 | 0 | const std::vector<unsigned char>& prefix = Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY); |
251 | 0 | if (data.size() == BIP32_EXTKEY_SIZE + prefix.size() && std::equal(prefix.begin(), prefix.end(), data.begin())) { |
252 | 0 | key.Decode(data.data() + prefix.size()); |
253 | 0 | } |
254 | 0 | } |
255 | 0 | return key; |
256 | 0 | } |
257 | | |
258 | | std::string EncodeExtPubKey(const CExtPubKey& key) |
259 | 0 | { |
260 | 0 | std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY); |
261 | 0 | size_t size = data.size(); |
262 | 0 | data.resize(size + BIP32_EXTKEY_SIZE); |
263 | 0 | key.Encode(data.data() + size); |
264 | 0 | std::string ret = EncodeBase58Check(data); |
265 | 0 | return ret; |
266 | 0 | } |
267 | | |
268 | | CExtKey DecodeExtKey(const std::string& str) |
269 | 0 | { |
270 | 0 | CExtKey key; |
271 | 0 | std::vector<unsigned char> data; |
272 | 0 | if (DecodeBase58Check(str, data, 78)) { |
273 | 0 | const std::vector<unsigned char>& prefix = Params().Base58Prefix(CChainParams::EXT_SECRET_KEY); |
274 | 0 | if (data.size() == BIP32_EXTKEY_SIZE + prefix.size() && std::equal(prefix.begin(), prefix.end(), data.begin())) { |
275 | 0 | key.Decode(data.data() + prefix.size()); |
276 | 0 | } |
277 | 0 | } |
278 | 0 | if (!data.empty()) { |
279 | 0 | memory_cleanse(data.data(), data.size()); |
280 | 0 | } |
281 | 0 | return key; |
282 | 0 | } |
283 | | |
284 | | std::string EncodeExtKey(const CExtKey& key) |
285 | 0 | { |
286 | 0 | std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::EXT_SECRET_KEY); |
287 | 0 | size_t size = data.size(); |
288 | 0 | data.resize(size + BIP32_EXTKEY_SIZE); |
289 | 0 | key.Encode(data.data() + size); |
290 | 0 | std::string ret = EncodeBase58Check(data); |
291 | 0 | memory_cleanse(data.data(), data.size()); |
292 | 0 | return ret; |
293 | 0 | } |
294 | | |
295 | | std::string EncodeDestination(const CTxDestination& dest) |
296 | 0 | { |
297 | 0 | return std::visit(DestinationEncoder(Params()), dest); |
298 | 0 | } |
299 | | |
300 | | CTxDestination DecodeDestination(const std::string& str, std::string& error_msg, std::vector<int>* error_locations) |
301 | 0 | { |
302 | 0 | return DecodeDestination(str, Params(), error_msg, error_locations); |
303 | 0 | } |
304 | | |
305 | | CTxDestination DecodeDestination(const std::string& str) |
306 | 0 | { |
307 | 0 | std::string error_msg; |
308 | 0 | return DecodeDestination(str, error_msg); |
309 | 0 | } |
310 | | |
311 | | bool IsValidDestinationString(const std::string& str, const CChainParams& params) |
312 | 0 | { |
313 | 0 | std::string error_msg; |
314 | 0 | return IsValidDestination(DecodeDestination(str, params, error_msg, nullptr)); |
315 | 0 | } |
316 | | |
317 | | bool IsValidDestinationString(const std::string& str) |
318 | 0 | { |
319 | 0 | return IsValidDestinationString(str, Params()); |
320 | 0 | } |