Bitcoin ABC  0.28.12
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 <algorithm>
14 #include <cassert>
15 #include <cstring>
16 
17 namespace {
18 class DestinationEncoder {
19 private:
20  const CChainParams &m_params;
21 
22 public:
23  explicit DestinationEncoder(const CChainParams &params)
24  : m_params(params) {}
25 
26  std::string operator()(const PKHash &id) const {
27  std::vector<uint8_t> data =
29  data.insert(data.end(), id.begin(), id.end());
30  return EncodeBase58Check(data);
31  }
32 
33  std::string operator()(const ScriptHash &id) const {
34  std::vector<uint8_t> data =
36  data.insert(data.end(), id.begin(), id.end());
37  return EncodeBase58Check(data);
38  }
39 
40  std::string operator()(const CNoDestination &no) const { return {}; }
41 };
42 
43 CTxDestination DecodeLegacyDestination(const std::string &str,
44  const CChainParams &params) {
45  std::vector<uint8_t> data;
46  uint160 hash;
47  if (!DecodeBase58Check(str, data, 21)) {
48  return CNoDestination();
49  }
50  // base58-encoded Bitcoin addresses.
51  // Public-key-hash-addresses have version 0 (or 111 testnet).
52  // The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is
53  // the serialized public key.
54  const std::vector<uint8_t> &pubkey_prefix =
56  if (data.size() == hash.size() + pubkey_prefix.size() &&
57  std::equal(pubkey_prefix.begin(), pubkey_prefix.end(), data.begin())) {
58  std::copy(data.begin() + pubkey_prefix.size(), data.end(),
59  hash.begin());
60  return PKHash(hash);
61  }
62  // Script-hash-addresses have version 5 (or 196 testnet).
63  // The data vector contains RIPEMD160(SHA256(cscript)), where cscript is
64  // the serialized redemption script.
65  const std::vector<uint8_t> &script_prefix =
67  if (data.size() == hash.size() + script_prefix.size() &&
68  std::equal(script_prefix.begin(), script_prefix.end(), data.begin())) {
69  std::copy(data.begin() + script_prefix.size(), data.end(),
70  hash.begin());
71  return ScriptHash(hash);
72  }
73  return CNoDestination();
74 }
75 } // namespace
76 
77 CKey DecodeSecret(const std::string &str) {
78  return DecodeSecret(str, Params());
79 }
80 
81 CKey DecodeSecret(const std::string &str, const CChainParams &params) {
82  CKey key;
83  std::vector<uint8_t> data;
84  if (DecodeBase58Check(str, data, 34)) {
85  const std::vector<uint8_t> &privkey_prefix =
87  if ((data.size() == 32 + privkey_prefix.size() ||
88  (data.size() == 33 + privkey_prefix.size() && data.back() == 1)) &&
89  std::equal(privkey_prefix.begin(), privkey_prefix.end(),
90  data.begin())) {
91  bool compressed = data.size() == 33 + privkey_prefix.size();
92  key.Set(data.begin() + privkey_prefix.size(),
93  data.begin() + privkey_prefix.size() + 32, compressed);
94  }
95  }
96  if (!data.empty()) {
97  memory_cleanse(data.data(), data.size());
98  }
99  return key;
100 }
101 
102 std::string EncodeSecret(const CKey &key) {
103  return EncodeSecret(key, Params());
104 }
105 
106 std::string EncodeSecret(const CKey &key, const CChainParams &params) {
107  assert(key.IsValid());
108  std::vector<uint8_t> data = params.Base58Prefix(CChainParams::SECRET_KEY);
109  data.insert(data.end(), key.begin(), key.end());
110  if (key.IsCompressed()) {
111  data.push_back(1);
112  }
113  std::string ret = EncodeBase58Check(data);
114  memory_cleanse(data.data(), data.size());
115  return ret;
116 }
117 
118 CExtPubKey DecodeExtPubKey(const std::string &str) {
119  CExtPubKey key;
120  std::vector<uint8_t> data;
121  if (DecodeBase58Check(str, data, 78)) {
122  const std::vector<uint8_t> &prefix =
124  if (data.size() == BIP32_EXTKEY_SIZE + prefix.size() &&
125  std::equal(prefix.begin(), prefix.end(), data.begin())) {
126  key.Decode(data.data() + prefix.size());
127  }
128  }
129  return key;
130 }
131 
132 std::string EncodeExtPubKey(const CExtPubKey &key) {
133  std::vector<uint8_t> data =
135  size_t size = data.size();
136  data.resize(size + BIP32_EXTKEY_SIZE);
137  key.Encode(data.data() + size);
138  std::string ret = EncodeBase58Check(data);
139  return ret;
140 }
141 
142 CExtKey DecodeExtKey(const std::string &str) {
143  CExtKey key;
144  std::vector<uint8_t> data;
145  if (DecodeBase58Check(str, data, 78)) {
146  const std::vector<uint8_t> &prefix =
148  if (data.size() == BIP32_EXTKEY_SIZE + prefix.size() &&
149  std::equal(prefix.begin(), prefix.end(), data.begin())) {
150  key.Decode(data.data() + prefix.size());
151  }
152  }
153  return key;
154 }
155 
156 std::string EncodeExtKey(const CExtKey &key) {
157  std::vector<uint8_t> data =
159  size_t size = data.size();
160  data.resize(size + BIP32_EXTKEY_SIZE);
161  key.Encode(data.data() + size);
162  std::string ret = EncodeBase58Check(data);
163  memory_cleanse(data.data(), data.size());
164  return ret;
165 }
166 
167 std::string EncodeDestination(const CTxDestination &dest,
168  const Config &config) {
169  const CChainParams &params = config.GetChainParams();
170  return config.UseCashAddrEncoding() ? EncodeCashAddr(dest, params)
171  : EncodeLegacyAddr(dest, params);
172 }
173 
174 CTxDestination DecodeDestination(const std::string &addr,
175  const CChainParams &params) {
176  CTxDestination dst = DecodeCashAddr(addr, params);
177  if (IsValidDestination(dst)) {
178  return dst;
179  }
180  return DecodeLegacyAddr(addr, params);
181 }
182 
183 bool IsValidDestinationString(const std::string &str,
184  const CChainParams &params) {
185  return IsValidDestination(DecodeDestination(str, params));
186 }
187 
188 std::string EncodeLegacyAddr(const CTxDestination &dest,
189  const CChainParams &params) {
190  return std::visit(DestinationEncoder(params), dest);
191 }
192 
193 CTxDestination DecodeLegacyAddr(const std::string &str,
194  const CChainParams &params) {
195  return DecodeLegacyDestination(str, params);
196 }
std::string EncodeBase58Check(Span< const uint8_t > input)
Encode a byte span into a base58-encoded string, including checksum.
Definition: base58.cpp:152
static bool DecodeBase58Check(const char *psz, std::vector< uint8_t > &vchRet, int max_ret_len)
Definition: base58.cpp:160
std::string EncodeCashAddr(const CTxDestination &dst, const CChainParams &params)
Definition: cashaddrenc.cpp:90
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:167
bool IsValidDestinationString(const std::string &str, const CChainParams &params)
Definition: key_io.cpp:183
std::string EncodeExtKey(const CExtKey &key)
Definition: key_io.cpp:156
CExtPubKey DecodeExtPubKey(const std::string &str)
Definition: key_io.cpp:118
std::string EncodeSecret(const CKey &key)
Definition: key_io.cpp:102
CTxDestination DecodeDestination(const std::string &addr, const CChainParams &params)
Definition: key_io.cpp:174
CKey DecodeSecret(const std::string &str)
Definition: key_io.cpp:77
std::string EncodeExtPubKey(const CExtPubKey &key)
Definition: key_io.cpp:132
CTxDestination DecodeLegacyAddr(const std::string &str, const CChainParams &params)
Definition: key_io.cpp:193
std::string EncodeLegacyAddr(const CTxDestination &dest, const CChainParams &params)
Definition: key_io.cpp:188
CExtKey DecodeExtKey(const std::string &str)
Definition: key_io.cpp:142
const CChainParams & m_params
Definition: interfaces.cpp:779
const unsigned int BIP32_EXTKEY_SIZE
Definition: pubkey.h:19
const char * prefix
Definition: rest.cpp:819
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:260
std::variant< CNoDestination, PKHash, ScriptHash > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:85
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())