Bitcoin Core  0.20.99
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 <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:
26  explicit DestinationEncoder(const CChainParams& params) : m_params(params) {}
27 
28  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 
35  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 
42  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 
50  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 
58  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 
69  std::string operator()(const CNoDestination& no) const { return {}; }
70 };
71 
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 
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 
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 
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 
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 
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 
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 
210 std::string EncodeDestination(const CTxDestination& dest)
211 {
212  return boost::apply_visitor(DestinationEncoder(Params()), dest);
213 }
214 
215 CTxDestination DecodeDestination(const std::string& str)
216 {
217  return DecodeDestination(str, Params());
218 }
219 
220 bool IsValidDestinationString(const std::string& str, const CChainParams& params)
221 {
222  return IsValidDestination(DecodeDestination(str, params));
223 }
224 
225 bool IsValidDestinationString(const std::string& str)
226 {
227  return IsValidDestinationString(str, Params());
228 }
unsigned char program[40]
Definition: standard.h:116
bool IsValidDestinationString(const std::string &str, const CChainParams &params)
Definition: key_io.cpp:220
const std::string & Bech32HRP() const
Definition: chainparams.h:85
CExtKey DecodeExtKey(const std::string &str)
Definition: key_io.cpp:186
const char * prefix
Definition: rest.cpp:648
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:325
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system...
Definition: chainparams.h:47
unsigned int version
Definition: standard.h:114
unsigned int length
Definition: standard.h:115
const unsigned char * begin() const
Definition: key.h:89
unsigned char * begin()
Definition: uint256.h:54
CExtPubKey DecodeExtPubKey(const std::string &str)
Definition: key_io.cpp:163
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:253
void Decode(const unsigned char code[BIP32_EXTKEY_SIZE])
Definition: pubkey.cpp:263
CTxDestination subtype to encode any future Witness version.
Definition: standard.h:112
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:74
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
CTxDestination DecodeDestination(const std::string &str)
Definition: key_io.cpp:215
std::string EncodeExtPubKey(const CExtPubKey &key)
Definition: key_io.cpp:176
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:17
160-bit opaque blob.
Definition: uint256.h:109
std::string EncodeDestination(const CTxDestination &dest)
Definition: key_io.cpp:210
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:132
boost::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:143
std::string EncodeBase58Check(const std::vector< unsigned char > &vchIn)
Encode a byte vector into a base58-encoded string, including checksum.
Definition: base58.cpp:140
bool DecodeBase58Check(const char *psz, std::vector< unsigned char > &vchRet, int max_ret_len)
Decode a base58-encoded string (psz) that includes a checksum into a byte vector (vchRet), return true if decoding is successful.
Definition: base58.cpp:149
std::string EncodeSecret(const CKey &key)
Definition: key_io.cpp:150
std::string EncodeExtKey(const CExtKey &key)
Definition: key_io.cpp:199
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:84