Bitcoin ABC  0.26.3
P2P Digital Currency
key_io.cpp
Go to the documentation of this file.
1 // Copyright (c) 2014-2016 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 <cashaddrenc.h>
9 #include <chainparams.h>
10 #include <config.h>
11 #include <util/strencodings.h>
12 
13 #include <boost/variant/apply_visitor.hpp>
14 #include <boost/variant/static_visitor.hpp>
15 
16 #include <algorithm>
17 #include <cassert>
18 #include <cstring>
19 
20 namespace {
21 class DestinationEncoder : public boost::static_visitor<std::string> {
22 private:
23  const CChainParams &m_params;
24 
25 public:
26  explicit DestinationEncoder(const CChainParams &params)
27  : m_params(params) {}
28 
29  std::string operator()(const PKHash &id) const {
30  std::vector<uint8_t> data =
32  data.insert(data.end(), id.begin(), id.end());
33  return EncodeBase58Check(data);
34  }
35 
36  std::string operator()(const ScriptHash &id) const {
37  std::vector<uint8_t> data =
39  data.insert(data.end(), id.begin(), id.end());
40  return EncodeBase58Check(data);
41  }
42 
43  std::string operator()(const CNoDestination &no) const { return {}; }
44 };
45 
46 CTxDestination DecodeLegacyDestination(const std::string &str,
47  const CChainParams &params) {
48  std::vector<uint8_t> data;
49  uint160 hash;
50  if (!DecodeBase58Check(str, data, 21)) {
51  return CNoDestination();
52  }
53  // base58-encoded Bitcoin addresses.
54  // Public-key-hash-addresses have version 0 (or 111 testnet).
55  // The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is
56  // the serialized public key.
57  const std::vector<uint8_t> &pubkey_prefix =
59  if (data.size() == hash.size() + pubkey_prefix.size() &&
60  std::equal(pubkey_prefix.begin(), pubkey_prefix.end(), data.begin())) {
61  std::copy(data.begin() + pubkey_prefix.size(), data.end(),
62  hash.begin());
63  return PKHash(hash);
64  }
65  // Script-hash-addresses have version 5 (or 196 testnet).
66  // The data vector contains RIPEMD160(SHA256(cscript)), where cscript is
67  // the serialized redemption script.
68  const std::vector<uint8_t> &script_prefix =
70  if (data.size() == hash.size() + script_prefix.size() &&
71  std::equal(script_prefix.begin(), script_prefix.end(), data.begin())) {
72  std::copy(data.begin() + script_prefix.size(), data.end(),
73  hash.begin());
74  return ScriptHash(hash);
75  }
76  return CNoDestination();
77 }
78 } // namespace
79 
80 CKey DecodeSecret(const std::string &str) {
81  return DecodeSecret(str, Params());
82 }
83 
84 CKey DecodeSecret(const std::string &str, const CChainParams &params) {
85  CKey key;
86  std::vector<uint8_t> data;
87  if (DecodeBase58Check(str, data, 34)) {
88  const std::vector<uint8_t> &privkey_prefix =
90  if ((data.size() == 32 + privkey_prefix.size() ||
91  (data.size() == 33 + privkey_prefix.size() && data.back() == 1)) &&
92  std::equal(privkey_prefix.begin(), privkey_prefix.end(),
93  data.begin())) {
94  bool compressed = data.size() == 33 + privkey_prefix.size();
95  key.Set(data.begin() + privkey_prefix.size(),
96  data.begin() + privkey_prefix.size() + 32, compressed);
97  }
98  }
99  if (!data.empty()) {
100  memory_cleanse(data.data(), data.size());
101  }
102  return key;
103 }
104 
105 std::string EncodeSecret(const CKey &key) {
106  return EncodeSecret(key, Params());
107 }
108 
109 std::string EncodeSecret(const CKey &key, const CChainParams &params) {
110  assert(key.IsValid());
111  std::vector<uint8_t> data = params.Base58Prefix(CChainParams::SECRET_KEY);
112  data.insert(data.end(), key.begin(), key.end());
113  if (key.IsCompressed()) {
114  data.push_back(1);
115  }
116  std::string ret = EncodeBase58Check(data);
117  memory_cleanse(data.data(), data.size());
118  return ret;
119 }
120 
121 CExtPubKey DecodeExtPubKey(const std::string &str) {
122  CExtPubKey key;
123  std::vector<uint8_t> data;
124  if (DecodeBase58Check(str, data, 78)) {
125  const std::vector<uint8_t> &prefix =
127  if (data.size() == BIP32_EXTKEY_SIZE + prefix.size() &&
128  std::equal(prefix.begin(), prefix.end(), data.begin())) {
129  key.Decode(data.data() + prefix.size());
130  }
131  }
132  return key;
133 }
134 
135 std::string EncodeExtPubKey(const CExtPubKey &key) {
136  std::vector<uint8_t> data =
138  size_t size = data.size();
139  data.resize(size + BIP32_EXTKEY_SIZE);
140  key.Encode(data.data() + size);
141  std::string ret = EncodeBase58Check(data);
142  return ret;
143 }
144 
145 CExtKey DecodeExtKey(const std::string &str) {
146  CExtKey key;
147  std::vector<uint8_t> data;
148  if (DecodeBase58Check(str, data, 78)) {
149  const std::vector<uint8_t> &prefix =
151  if (data.size() == BIP32_EXTKEY_SIZE + prefix.size() &&
152  std::equal(prefix.begin(), prefix.end(), data.begin())) {
153  key.Decode(data.data() + prefix.size());
154  }
155  }
156  return key;
157 }
158 
159 std::string EncodeExtKey(const CExtKey &key) {
160  std::vector<uint8_t> data =
162  size_t size = data.size();
163  data.resize(size + BIP32_EXTKEY_SIZE);
164  key.Encode(data.data() + size);
165  std::string ret = EncodeBase58Check(data);
166  memory_cleanse(data.data(), data.size());
167  return ret;
168 }
169 
170 std::string EncodeDestination(const CTxDestination &dest,
171  const Config &config) {
172  const CChainParams &params = config.GetChainParams();
173  return config.UseCashAddrEncoding() ? EncodeCashAddr(dest, params)
174  : EncodeLegacyAddr(dest, params);
175 }
176 
177 CTxDestination DecodeDestination(const std::string &addr,
178  const CChainParams &params) {
179  CTxDestination dst = DecodeCashAddr(addr, params);
180  if (IsValidDestination(dst)) {
181  return dst;
182  }
183  return DecodeLegacyAddr(addr, params);
184 }
185 
186 bool IsValidDestinationString(const std::string &str,
187  const CChainParams &params) {
188  return IsValidDestination(DecodeDestination(str, params));
189 }
190 
191 std::string EncodeLegacyAddr(const CTxDestination &dest,
192  const CChainParams &params) {
193  return boost::apply_visitor(DestinationEncoder(params), dest);
194 }
195 
196 CTxDestination DecodeLegacyAddr(const std::string &str,
197  const CChainParams &params) {
198  return DecodeLegacyDestination(str, params);
199 }
bool DecodeBase58Check(const char *psz, std::vector< uint8_t > &vchRet, int max_ret_len)
Decode a base58-encoded string (psz) that includes a checksum into a byte vector (vchRet),...
Definition: base58.cpp:159
std::string EncodeBase58Check(Span< const uint8_t > input)
Encode a byte span into a base58-encoded string, including checksum.
Definition: base58.cpp:151
std::string EncodeCashAddr(const CTxDestination &dst, const CChainParams &params)
Definition: cashaddrenc.cpp:91
CTxDestination DecodeCashAddr(const std::string &addr, const CChainParams &params)
const CChainParams & Params()
Return the currently selected parameters.
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
Definition: chainparams.h:74
const std::vector< uint8_t > & Base58Prefix(Base58Type type) const
Return the list of hostnames to look up for DNS seeds.
Definition: chainparams.h:123
An encapsulated secp256k1 private key.
Definition: key.h:28
const uint8_t * begin() const
Definition: key.h:90
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:94
bool IsCompressed() const
Check whether the public key corresponding to this private key is (to be) compressed.
Definition: key.h:98
void Set(const T pbegin, const T pend, bool fCompressedIn)
Initialize using begin and end iterators to byte data.
Definition: key.h:76
const uint8_t * end() const
Definition: key.h:91
Definition: config.h:17
virtual bool UseCashAddrEncoding() const =0
virtual const CChainParams & GetChainParams() const =0
unsigned int size() const
Definition: uint256.h:91
uint8_t * begin()
Definition: uint256.h:83
160-bit opaque blob.
Definition: uint256.h:115
void memory_cleanse(void *ptr, size_t len)
Secure overwrite a buffer (possibly containing secret data) with zero-bytes.
Definition: cleanse.cpp:14
std::string EncodeDestination(const CTxDestination &dest, const Config &config)
Definition: key_io.cpp:170
bool IsValidDestinationString(const std::string &str, const CChainParams &params)
Definition: key_io.cpp:186
std::string EncodeExtKey(const CExtKey &key)
Definition: key_io.cpp:159
CExtPubKey DecodeExtPubKey(const std::string &str)
Definition: key_io.cpp:121
std::string EncodeSecret(const CKey &key)
Definition: key_io.cpp:105
CTxDestination DecodeDestination(const std::string &addr, const CChainParams &params)
Definition: key_io.cpp:177
CKey DecodeSecret(const std::string &str)
Definition: key_io.cpp:80
std::string EncodeExtPubKey(const CExtPubKey &key)
Definition: key_io.cpp:135
CTxDestination DecodeLegacyAddr(const std::string &str, const CChainParams &params)
Definition: key_io.cpp:196
std::string EncodeLegacyAddr(const CTxDestination &dest, const CChainParams &params)
Definition: key_io.cpp:191
CExtKey DecodeExtKey(const std::string &str)
Definition: key_io.cpp:145
const CChainParams & m_params
Definition: interfaces.cpp:769
const unsigned int BIP32_EXTKEY_SIZE
Definition: pubkey.h:19
const char * prefix
Definition: rest.cpp:821
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:263
boost::variant< CNoDestination, PKHash, ScriptHash > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:93
Definition: key.h:164
void Encode(uint8_t code[BIP32_EXTKEY_SIZE]) const
Definition: key.cpp:406
void Decode(const uint8_t code[BIP32_EXTKEY_SIZE])
Definition: key.cpp:419
void Encode(uint8_t code[BIP32_EXTKEY_SIZE]) const
Definition: pubkey.cpp:313
void Decode(const uint8_t code[BIP32_EXTKEY_SIZE])
Definition: pubkey.cpp:325
assert(!tx.IsCoinBase())