Bitcoin Core 22.99.0
P2P Digital Currency
key_io.cpp
Go to the documentation of this 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
5#include <key_io.h>
6
7#include <base58.h>
8#include <bech32.h>
9#include <util/strencodings.h>
10
11#include <algorithm>
12#include <assert.h>
13#include <string.h>
14
16static constexpr std::size_t BECH32_WITNESS_PROG_MAX_LEN = 40;
17
18namespace {
19class DestinationEncoder
20{
21private:
22 const CChainParams& m_params;
23
24public:
25 explicit DestinationEncoder(const CChainParams& params) : m_params(params) {}
26
27 std::string operator()(const PKHash& id) const
28 {
29 std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
30 data.insert(data.end(), id.begin(), id.end());
31 return EncodeBase58Check(data);
32 }
33
34 std::string operator()(const ScriptHash& id) const
35 {
36 std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
37 data.insert(data.end(), id.begin(), id.end());
38 return EncodeBase58Check(data);
39 }
40
41 std::string operator()(const WitnessV0KeyHash& id) const
42 {
43 std::vector<unsigned char> data = {0};
44 data.reserve(33);
45 ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, id.begin(), id.end());
46 return bech32::Encode(bech32::Encoding::BECH32, m_params.Bech32HRP(), data);
47 }
48
49 std::string operator()(const WitnessV0ScriptHash& id) const
50 {
51 std::vector<unsigned char> data = {0};
52 data.reserve(53);
53 ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, id.begin(), id.end());
54 return bech32::Encode(bech32::Encoding::BECH32, m_params.Bech32HRP(), data);
55 }
56
57 std::string operator()(const WitnessV1Taproot& tap) const
58 {
59 std::vector<unsigned char> data = {1};
60 data.reserve(53);
61 ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, tap.begin(), tap.end());
62 return bech32::Encode(bech32::Encoding::BECH32M, m_params.Bech32HRP(), data);
63 }
64
65 std::string operator()(const WitnessUnknown& id) const
66 {
67 if (id.version < 1 || id.version > 16 || id.length < 2 || id.length > 40) {
68 return {};
69 }
70 std::vector<unsigned char> data = {(unsigned char)id.version};
71 data.reserve(1 + (id.length * 8 + 4) / 5);
72 ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, id.program, id.program + id.length);
73 return bech32::Encode(bech32::Encoding::BECH32M, m_params.Bech32HRP(), data);
74 }
75
76 std::string operator()(const CNoDestination& no) const { return {}; }
77};
78
79CTxDestination DecodeDestination(const std::string& str, const CChainParams& params, std::string& error_str)
80{
81 std::vector<unsigned char> data;
82 uint160 hash;
83 error_str = "";
84 if (DecodeBase58Check(str, data, 21)) {
85 // base58-encoded Bitcoin addresses.
86 // Public-key-hash-addresses have version 0 (or 111 testnet).
87 // The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key.
88 const std::vector<unsigned char>& pubkey_prefix = params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
89 if (data.size() == hash.size() + pubkey_prefix.size() && std::equal(pubkey_prefix.begin(), pubkey_prefix.end(), data.begin())) {
90 std::copy(data.begin() + pubkey_prefix.size(), data.end(), hash.begin());
91 return PKHash(hash);
92 }
93 // Script-hash-addresses have version 5 (or 196 testnet).
94 // The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script.
95 const std::vector<unsigned char>& script_prefix = params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
96 if (data.size() == hash.size() + script_prefix.size() && std::equal(script_prefix.begin(), script_prefix.end(), data.begin())) {
97 std::copy(data.begin() + script_prefix.size(), data.end(), hash.begin());
98 return ScriptHash(hash);
99 }
100
101 // Set potential error message.
102 // This message may be changed if the address can also be interpreted as a Bech32 address.
103 error_str = "Invalid prefix for Base58-encoded address";
104 }
105 data.clear();
106 const auto dec = bech32::Decode(str);
107 if ((dec.encoding == bech32::Encoding::BECH32 || dec.encoding == bech32::Encoding::BECH32M) && dec.data.size() > 0) {
108 // Bech32 decoding
109 error_str = "";
110 if (dec.hrp != params.Bech32HRP()) {
111 error_str = "Invalid prefix for Bech32 address";
112 return CNoDestination();
113 }
114 int version = dec.data[0]; // The first 5 bit symbol is the witness version (0-16)
115 if (version == 0 && dec.encoding != bech32::Encoding::BECH32) {
116 error_str = "Version 0 witness address must use Bech32 checksum";
117 return CNoDestination();
118 }
119 if (version != 0 && dec.encoding != bech32::Encoding::BECH32M) {
120 error_str = "Version 1+ witness address must use Bech32m checksum";
121 return CNoDestination();
122 }
123 // The rest of the symbols are converted witness program bytes.
124 data.reserve(((dec.data.size() - 1) * 5) / 8);
125 if (ConvertBits<5, 8, false>([&](unsigned char c) { data.push_back(c); }, dec.data.begin() + 1, dec.data.end())) {
126 if (version == 0) {
127 {
128 WitnessV0KeyHash keyid;
129 if (data.size() == keyid.size()) {
130 std::copy(data.begin(), data.end(), keyid.begin());
131 return keyid;
132 }
133 }
134 {
135 WitnessV0ScriptHash scriptid;
136 if (data.size() == scriptid.size()) {
137 std::copy(data.begin(), data.end(), scriptid.begin());
138 return scriptid;
139 }
140 }
141
142 error_str = "Invalid Bech32 v0 address data size";
143 return CNoDestination();
144 }
145
146 if (version == 1 && data.size() == WITNESS_V1_TAPROOT_SIZE) {
149 std::copy(data.begin(), data.end(), tap.begin());
150 return tap;
151 }
152
153 if (version > 16) {
154 error_str = "Invalid Bech32 address witness version";
155 return CNoDestination();
156 }
157
158 if (data.size() < 2 || data.size() > BECH32_WITNESS_PROG_MAX_LEN) {
159 error_str = "Invalid Bech32 address data size";
160 return CNoDestination();
161 }
162
163 WitnessUnknown unk;
164 unk.version = version;
165 std::copy(data.begin(), data.end(), unk.program);
166 unk.length = data.size();
167 return unk;
168 }
169 }
170
171 // Set error message if address can't be interpreted as Base58 or Bech32.
172 if (error_str.empty()) error_str = "Invalid address format";
173
174 return CNoDestination();
175}
176} // namespace
177
178CKey DecodeSecret(const std::string& str)
179{
180 CKey key;
181 std::vector<unsigned char> data;
182 if (DecodeBase58Check(str, data, 34)) {
183 const std::vector<unsigned char>& privkey_prefix = Params().Base58Prefix(CChainParams::SECRET_KEY);
184 if ((data.size() == 32 + privkey_prefix.size() || (data.size() == 33 + privkey_prefix.size() && data.back() == 1)) &&
185 std::equal(privkey_prefix.begin(), privkey_prefix.end(), data.begin())) {
186 bool compressed = data.size() == 33 + privkey_prefix.size();
187 key.Set(data.begin() + privkey_prefix.size(), data.begin() + privkey_prefix.size() + 32, compressed);
188 }
189 }
190 if (!data.empty()) {
191 memory_cleanse(data.data(), data.size());
192 }
193 return key;
194}
195
196std::string EncodeSecret(const CKey& key)
197{
198 assert(key.IsValid());
199 std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::SECRET_KEY);
200 data.insert(data.end(), key.begin(), key.end());
201 if (key.IsCompressed()) {
202 data.push_back(1);
203 }
204 std::string ret = EncodeBase58Check(data);
205 memory_cleanse(data.data(), data.size());
206 return ret;
207}
208
209CExtPubKey DecodeExtPubKey(const std::string& str)
210{
211 CExtPubKey key;
212 std::vector<unsigned char> data;
213 if (DecodeBase58Check(str, data, 78)) {
214 const std::vector<unsigned char>& prefix = Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY);
215 if (data.size() == BIP32_EXTKEY_SIZE + prefix.size() && std::equal(prefix.begin(), prefix.end(), data.begin())) {
216 key.Decode(data.data() + prefix.size());
217 }
218 }
219 return key;
220}
221
222std::string EncodeExtPubKey(const CExtPubKey& key)
223{
224 std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY);
225 size_t size = data.size();
226 data.resize(size + BIP32_EXTKEY_SIZE);
227 key.Encode(data.data() + size);
228 std::string ret = EncodeBase58Check(data);
229 return ret;
230}
231
232CExtKey DecodeExtKey(const std::string& str)
233{
234 CExtKey key;
235 std::vector<unsigned char> data;
236 if (DecodeBase58Check(str, data, 78)) {
237 const std::vector<unsigned char>& prefix = Params().Base58Prefix(CChainParams::EXT_SECRET_KEY);
238 if (data.size() == BIP32_EXTKEY_SIZE + prefix.size() && std::equal(prefix.begin(), prefix.end(), data.begin())) {
239 key.Decode(data.data() + prefix.size());
240 }
241 }
242 return key;
243}
244
245std::string EncodeExtKey(const CExtKey& key)
246{
247 std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::EXT_SECRET_KEY);
248 size_t size = data.size();
249 data.resize(size + BIP32_EXTKEY_SIZE);
250 key.Encode(data.data() + size);
251 std::string ret = EncodeBase58Check(data);
252 memory_cleanse(data.data(), data.size());
253 return ret;
254}
255
256std::string EncodeDestination(const CTxDestination& dest)
257{
258 return std::visit(DestinationEncoder(Params()), dest);
259}
260
261CTxDestination DecodeDestination(const std::string& str, std::string& error_msg)
262{
263 return DecodeDestination(str, Params(), error_msg);
264}
265
266CTxDestination DecodeDestination(const std::string& str)
267{
268 std::string error_msg;
269 return DecodeDestination(str, error_msg);
270}
271
272bool IsValidDestinationString(const std::string& str, const CChainParams& params)
273{
274 std::string error_msg;
275 return IsValidDestination(DecodeDestination(str, params, error_msg));
276}
277
278bool IsValidDestinationString(const std::string& str)
279{
280 return IsValidDestinationString(str, Params());
281}
std::string EncodeBase58Check(Span< const unsigned char > input)
Encode a byte span into a base58-encoded string, including checksum.
Definition: base58.cpp:135
static bool DecodeBase58Check(const char *psz, std::vector< unsigned char > &vchRet, int max_ret_len)
Definition: base58.cpp:144
const CChainParams & Params()
Return the currently selected parameters.
size_t size() const
Definition: hash_type.h:63
unsigned char * begin()
Definition: hash_type.h:18
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
Definition: chainparams.h:70
const std::vector< unsigned char > & Base58Prefix(Base58Type type) const
Definition: chainparams.h:115
const std::string & Bech32HRP() const
Definition: chainparams.h:116
An encapsulated private key.
Definition: key.h:27
const unsigned char * begin() const
Definition: key.h:89
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:93
const unsigned char * end() const
Definition: key.h:90
bool IsCompressed() const
Check whether the public key corresponding to this private key is (to be) compressed.
Definition: key.h:96
void Set(const T pbegin, const T pend, bool fCompressedIn)
Initialize using begin and end iterators to byte data.
Definition: key.h:73
const unsigned char * end() const
Definition: pubkey.h:279
const unsigned char * begin() const
Definition: pubkey.h:278
static constexpr size_t size()
Definition: pubkey.h:277
static constexpr unsigned int size()
Definition: uint256.h:78
unsigned char * begin()
Definition: uint256.h:58
160-bit opaque blob.
Definition: uint256.h:113
void memory_cleanse(void *ptr, size_t len)
Secure overwrite a buffer (possibly containing secret data) with zero-bytes.
Definition: cleanse.cpp:14
static constexpr size_t WITNESS_V1_TAPROOT_SIZE
Definition: interpreter.h:223
static constexpr std::size_t BECH32_WITNESS_PROG_MAX_LEN
Maximum witness length for Bech32 addresses.
Definition: key_io.cpp:16
bool IsValidDestinationString(const std::string &str, const CChainParams &params)
Definition: key_io.cpp:272
std::string EncodeExtKey(const CExtKey &key)
Definition: key_io.cpp:245
CExtPubKey DecodeExtPubKey(const std::string &str)
Definition: key_io.cpp:209
std::string EncodeSecret(const CKey &key)
Definition: key_io.cpp:196
std::string EncodeDestination(const CTxDestination &dest)
Definition: key_io.cpp:256
CKey DecodeSecret(const std::string &str)
Definition: key_io.cpp:178
std::string EncodeExtPubKey(const CExtPubKey &key)
Definition: key_io.cpp:222
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg)
Definition: key_io.cpp:261
CExtKey DecodeExtKey(const std::string &str)
Definition: key_io.cpp:232
@ BECH32
Bech32 encoding as defined in BIP173.
@ BECH32M
Bech32m encoding as defined in BIP350.
std::string Encode(Encoding encoding, const std::string &hrp, const data &values)
Encode a Bech32 or Bech32m string.
Definition: bech32.cpp:182
DecodeResult Decode(const std::string &str)
Decode a Bech32 or Bech32m string.
Definition: bech32.cpp:198
const unsigned int BIP32_EXTKEY_SIZE
Definition: pubkey.h:19
const char * prefix
Definition: rest.cpp:714
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:332
std::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:157
Definition: key.h:161
void Decode(const unsigned char code[BIP32_EXTKEY_SIZE])
Definition: key.cpp:354
void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const
Definition: key.cpp:344
void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const
Definition: pubkey.cpp:337
void Decode(const unsigned char code[BIP32_EXTKEY_SIZE])
Definition: pubkey.cpp:346
CTxDestination subtype to encode any future Witness version.
Definition: standard.h:126
unsigned char program[40]
Definition: standard.h:129
unsigned int length
Definition: standard.h:128
unsigned int version
Definition: standard.h:127
assert(!tx.IsCoinBase())