Bitcoin Core  21.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 
15 namespace {
16 class DestinationEncoder
17 {
18 private:
19  const CChainParams& m_params;
20 
21 public:
22  explicit DestinationEncoder(const CChainParams& params) : m_params(params) {}
23 
24  std::string operator()(const PKHash& id) const
25  {
26  std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
27  data.insert(data.end(), id.begin(), id.end());
28  return EncodeBase58Check(data);
29  }
30 
31  std::string operator()(const ScriptHash& id) const
32  {
33  std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
34  data.insert(data.end(), id.begin(), id.end());
35  return EncodeBase58Check(data);
36  }
37 
38  std::string operator()(const WitnessV0KeyHash& id) const
39  {
40  std::vector<unsigned char> data = {0};
41  data.reserve(33);
42  ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, id.begin(), id.end());
43  return bech32::Encode(m_params.Bech32HRP(), data);
44  }
45 
46  std::string operator()(const WitnessV0ScriptHash& id) const
47  {
48  std::vector<unsigned char> data = {0};
49  data.reserve(53);
50  ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, id.begin(), id.end());
51  return bech32::Encode(m_params.Bech32HRP(), data);
52  }
53 
54  std::string operator()(const WitnessUnknown& id) const
55  {
56  if (id.version < 1 || id.version > 16 || id.length < 2 || id.length > 40) {
57  return {};
58  }
59  std::vector<unsigned char> data = {(unsigned char)id.version};
60  data.reserve(1 + (id.length * 8 + 4) / 5);
61  ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, id.program, id.program + id.length);
62  return bech32::Encode(m_params.Bech32HRP(), data);
63  }
64 
65  std::string operator()(const CNoDestination& no) const { return {}; }
66 };
67 
68 CTxDestination DecodeDestination(const std::string& str, const CChainParams& params)
69 {
70  std::vector<unsigned char> data;
71  uint160 hash;
72  if (DecodeBase58Check(str, data, 21)) {
73  // base58-encoded Bitcoin addresses.
74  // Public-key-hash-addresses have version 0 (or 111 testnet).
75  // The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key.
76  const std::vector<unsigned char>& pubkey_prefix = params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
77  if (data.size() == hash.size() + pubkey_prefix.size() && std::equal(pubkey_prefix.begin(), pubkey_prefix.end(), data.begin())) {
78  std::copy(data.begin() + pubkey_prefix.size(), data.end(), hash.begin());
79  return PKHash(hash);
80  }
81  // Script-hash-addresses have version 5 (or 196 testnet).
82  // The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script.
83  const std::vector<unsigned char>& script_prefix = params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
84  if (data.size() == hash.size() + script_prefix.size() && std::equal(script_prefix.begin(), script_prefix.end(), data.begin())) {
85  std::copy(data.begin() + script_prefix.size(), data.end(), hash.begin());
86  return ScriptHash(hash);
87  }
88  }
89  data.clear();
90  auto bech = bech32::Decode(str);
91  if (bech.second.size() > 0 && bech.first == params.Bech32HRP()) {
92  // Bech32 decoding
93  int version = bech.second[0]; // The first 5 bit symbol is the witness version (0-16)
94  // The rest of the symbols are converted witness program bytes.
95  data.reserve(((bech.second.size() - 1) * 5) / 8);
96  if (ConvertBits<5, 8, false>([&](unsigned char c) { data.push_back(c); }, bech.second.begin() + 1, bech.second.end())) {
97  if (version == 0) {
98  {
99  WitnessV0KeyHash keyid;
100  if (data.size() == keyid.size()) {
101  std::copy(data.begin(), data.end(), keyid.begin());
102  return keyid;
103  }
104  }
105  {
106  WitnessV0ScriptHash scriptid;
107  if (data.size() == scriptid.size()) {
108  std::copy(data.begin(), data.end(), scriptid.begin());
109  return scriptid;
110  }
111  }
112  return CNoDestination();
113  }
114  if (version > 16 || data.size() < 2 || data.size() > 40) {
115  return CNoDestination();
116  }
117  WitnessUnknown unk;
118  unk.version = version;
119  std::copy(data.begin(), data.end(), unk.program);
120  unk.length = data.size();
121  return unk;
122  }
123  }
124  return CNoDestination();
125 }
126 } // namespace
127 
128 CKey DecodeSecret(const std::string& str)
129 {
130  CKey key;
131  std::vector<unsigned char> data;
132  if (DecodeBase58Check(str, data, 34)) {
133  const std::vector<unsigned char>& privkey_prefix = Params().Base58Prefix(CChainParams::SECRET_KEY);
134  if ((data.size() == 32 + privkey_prefix.size() || (data.size() == 33 + privkey_prefix.size() && data.back() == 1)) &&
135  std::equal(privkey_prefix.begin(), privkey_prefix.end(), data.begin())) {
136  bool compressed = data.size() == 33 + privkey_prefix.size();
137  key.Set(data.begin() + privkey_prefix.size(), data.begin() + privkey_prefix.size() + 32, compressed);
138  }
139  }
140  if (!data.empty()) {
141  memory_cleanse(data.data(), data.size());
142  }
143  return key;
144 }
145 
146 std::string EncodeSecret(const CKey& key)
147 {
148  assert(key.IsValid());
149  std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::SECRET_KEY);
150  data.insert(data.end(), key.begin(), key.end());
151  if (key.IsCompressed()) {
152  data.push_back(1);
153  }
154  std::string ret = EncodeBase58Check(data);
155  memory_cleanse(data.data(), data.size());
156  return ret;
157 }
158 
159 CExtPubKey DecodeExtPubKey(const std::string& str)
160 {
161  CExtPubKey key;
162  std::vector<unsigned char> data;
163  if (DecodeBase58Check(str, data, 78)) {
164  const std::vector<unsigned char>& prefix = Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY);
165  if (data.size() == BIP32_EXTKEY_SIZE + prefix.size() && std::equal(prefix.begin(), prefix.end(), data.begin())) {
166  key.Decode(data.data() + prefix.size());
167  }
168  }
169  return key;
170 }
171 
172 std::string EncodeExtPubKey(const CExtPubKey& key)
173 {
174  std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY);
175  size_t size = data.size();
176  data.resize(size + BIP32_EXTKEY_SIZE);
177  key.Encode(data.data() + size);
178  std::string ret = EncodeBase58Check(data);
179  return ret;
180 }
181 
182 CExtKey DecodeExtKey(const std::string& str)
183 {
184  CExtKey key;
185  std::vector<unsigned char> data;
186  if (DecodeBase58Check(str, data, 78)) {
187  const std::vector<unsigned char>& prefix = Params().Base58Prefix(CChainParams::EXT_SECRET_KEY);
188  if (data.size() == BIP32_EXTKEY_SIZE + prefix.size() && std::equal(prefix.begin(), prefix.end(), data.begin())) {
189  key.Decode(data.data() + prefix.size());
190  }
191  }
192  return key;
193 }
194 
195 std::string EncodeExtKey(const CExtKey& key)
196 {
197  std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::EXT_SECRET_KEY);
198  size_t size = data.size();
199  data.resize(size + BIP32_EXTKEY_SIZE);
200  key.Encode(data.data() + size);
201  std::string ret = EncodeBase58Check(data);
202  memory_cleanse(data.data(), data.size());
203  return ret;
204 }
205 
206 std::string EncodeDestination(const CTxDestination& dest)
207 {
208  return std::visit(DestinationEncoder(Params()), dest);
209 }
210 
211 CTxDestination DecodeDestination(const std::string& str)
212 {
213  return DecodeDestination(str, Params());
214 }
215 
216 bool IsValidDestinationString(const std::string& str, const CChainParams& params)
217 {
218  return IsValidDestination(DecodeDestination(str, params));
219 }
220 
221 bool IsValidDestinationString(const std::string& str)
222 {
223  return IsValidDestinationString(str, Params());
224 }
unsigned char * begin()
Definition: standard.h:31
assert(!tx.IsCoinBase())
unsigned char program[40]
Definition: standard.h:184
bool IsValidDestinationString(const std::string &str, const CChainParams &params)
Definition: key_io.cpp:216
const std::string & Bech32HRP() const
Definition: chainparams.h:90
CExtKey DecodeExtKey(const std::string &str)
Definition: key_io.cpp:182
const char * prefix
Definition: rest.cpp:670
Definition: key.h:144
void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const
Definition: key.cpp:322
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:321
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system...
Definition: chainparams.h:52
unsigned int version
Definition: standard.h:182
std::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:212
unsigned int length
Definition: standard.h:183
const unsigned char * begin() const
Definition: key.h:89
unsigned char * begin()
Definition: uint256.h:58
CExtPubKey DecodeExtPubKey(const std::string &str)
Definition: key_io.cpp:159
void memory_cleanse(void *ptr, size_t len)
Secure overwrite a buffer (possibly containing secret data) with zero-bytes.
Definition: cleanse.cpp:14
void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const
Definition: pubkey.cpp:275
void Decode(const unsigned char code[BIP32_EXTKEY_SIZE])
Definition: pubkey.cpp:285
CTxDestination subtype to encode any future Witness version.
Definition: standard.h:180
bool IsCompressed() const
Check whether the public key corresponding to this private key is (to be) compressed.
Definition: key.h:96
unsigned int size() const
Definition: uint256.h:78
void Set(const T pbegin, const T pend, bool fCompressedIn)
Initialize using begin and end iterators to byte data.
Definition: key.h:74
std::pair< std::string, data > Decode(const std::string &str)
Decode a Bech32 string.
Definition: bech32.cpp:159
void Decode(const unsigned char code[BIP32_EXTKEY_SIZE])
Definition: key.cpp:333
std::string EncodeBase58Check(Span< const unsigned char > input)
Encode a byte span into a base58-encoded string, including checksum.
Definition: base58.cpp:135
CTxDestination DecodeDestination(const std::string &str)
Definition: key_io.cpp:211
std::string EncodeExtPubKey(const CExtPubKey &key)
Definition: key_io.cpp:172
const CChainParams & Params()
Return the currently selected parameters.
const unsigned char * end() const
Definition: key.h:90
const unsigned int BIP32_EXTKEY_SIZE
Definition: pubkey.h:18
size_t size() const
Definition: standard.h:76
160-bit opaque blob.
Definition: uint256.h:113
static bool DecodeBase58Check(const char *psz, std::vector< unsigned char > &vchRet, int max_ret_len)
Definition: base58.cpp:144
std::string EncodeDestination(const CTxDestination &dest)
Definition: key_io.cpp:206
An encapsulated private key.
Definition: key.h:27
std::string Encode(const std::string &hrp, const data &values)
Encode a Bech32 string.
Definition: bech32.cpp:143
CKey DecodeSecret(const std::string &str)
Definition: key_io.cpp:128
std::string EncodeSecret(const CKey &key)
Definition: key_io.cpp:146
std::string EncodeExtKey(const CExtKey &key)
Definition: key_io.cpp:195
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:93
const std::vector< unsigned char > & Base58Prefix(Base58Type type) const
Definition: chainparams.h:89