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