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