BSHA3  0.17.99
P2P Blockchain, based on Bitcoin
key_io.cpp
Go to the documentation of this file.
1 // Copyright (c) 2014-2017 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 <utilstrencodings.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 CKeyID& 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 CScriptID& 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 BSHA3 addresses.
79  // Public-key-hash-addresses have version 0 (or 111 testnet).
80  // The data vector contains RIPEMD360(SHA3(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 CKeyID(hash);
85  }
86  // Script-hash-addresses have version 5 (or 196 testnet).
87  // The data vector contains RIPEMD360(SHA3(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 CScriptID(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  memory_cleanse(data.data(), data.size());
146  return key;
147 }
148 
149 std::string EncodeSecret(const CKey& key)
150 {
151  assert(key.IsValid());
152  std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::SECRET_KEY);
153  data.insert(data.end(), key.begin(), key.end());
154  if (key.IsCompressed()) {
155  data.push_back(1);
156  }
157  std::string ret = EncodeBase58Check(data);
158  memory_cleanse(data.data(), data.size());
159  return ret;
160 }
161 
162 CExtPubKey DecodeExtPubKey(const std::string& str)
163 {
164  CExtPubKey key;
165  std::vector<unsigned char> data;
166  if (DecodeBase58Check(str, data)) {
167  const std::vector<unsigned char>& prefix = Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY);
168  if (data.size() == BIP32_EXTKEY_SIZE + prefix.size() && std::equal(prefix.begin(), prefix.end(), data.begin())) {
169  key.Decode(data.data() + prefix.size());
170  }
171  }
172  return key;
173 }
174 
175 std::string EncodeExtPubKey(const CExtPubKey& key)
176 {
177  std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY);
178  size_t size = data.size();
179  data.resize(size + BIP32_EXTKEY_SIZE);
180  key.Encode(data.data() + size);
181  std::string ret = EncodeBase58Check(data);
182  return ret;
183 }
184 
185 CExtKey DecodeExtKey(const std::string& str)
186 {
187  CExtKey key;
188  std::vector<unsigned char> data;
189  if (DecodeBase58Check(str, data)) {
190  const std::vector<unsigned char>& prefix = Params().Base58Prefix(CChainParams::EXT_SECRET_KEY);
191  if (data.size() == BIP32_EXTKEY_SIZE + prefix.size() && std::equal(prefix.begin(), prefix.end(), data.begin())) {
192  key.Decode(data.data() + prefix.size());
193  }
194  }
195  return key;
196 }
197 
198 std::string EncodeExtKey(const CExtKey& key)
199 {
200  std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::EXT_SECRET_KEY);
201  size_t size = data.size();
202  data.resize(size + BIP32_EXTKEY_SIZE);
203  key.Encode(data.data() + size);
204  std::string ret = EncodeBase58Check(data);
205  memory_cleanse(data.data(), data.size());
206  return ret;
207 }
208 
209 std::string EncodeDestination(const CTxDestination& dest)
210 {
211  return boost::apply_visitor(DestinationEncoder(Params()), dest);
212 }
213 
214 CTxDestination DecodeDestination(const std::string& str)
215 {
216  return DecodeDestination(str, Params());
217 }
218 
219 bool IsValidDestinationString(const std::string& str, const CChainParams& params)
220 {
221  return IsValidDestination(DecodeDestination(str, params));
222 }
223 
224 bool IsValidDestinationString(const std::string& str)
225 {
226  return IsValidDestinationString(str, Params());
227 }
unsigned char program[40]
Definition: standard.h:96
bool IsValidDestinationString(const std::string &str, const CChainParams &params)
Definition: key_io.cpp:219
const std::string & Bech32HRP() const
Definition: chainparams.h:80
CExtKey DecodeExtKey(const std::string &str)
Definition: key_io.cpp:185
UniValue ret(UniValue::VARR)
Definition: rpcwallet.cpp:1140
const char * prefix
Definition: rest.cpp:581
Definition: key.h:141
void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const
Definition: key.cpp:317
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:324
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system...
Definition: chainparams.h:47
unsigned int version
Definition: standard.h:94
unsigned int length
Definition: standard.h:95
const unsigned char * begin() const
Definition: key.h:89
unsigned char * begin()
Definition: uint256.h:56
CExtPubKey DecodeExtPubKey(const std::string &str)
Definition: key_io.cpp:162
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
boost::variant< CNoDestination, CKeyID, CScriptID, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:123
CTxDestination subtype to encode any future Witness version.
Definition: standard.h:92
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:76
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:328
CTxDestination DecodeDestination(const std::string &str)
Definition: key_io.cpp:214
std::string EncodeExtPubKey(const CExtPubKey &key)
Definition: key_io.cpp:175
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
A reference to a CKey: the Hash360 of its serialized public key.
Definition: pubkey.h:20
160-bit opaque blob.
Definition: uint256.h:111
A reference to a CScript: the Hash360 of its serialization (see script.h)
Definition: standard.h:22
std::string EncodeDestination(const CTxDestination &dest)
Definition: key_io.cpp:209
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
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:149
std::string EncodeExtKey(const CExtKey &key)
Definition: key_io.cpp:198
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:79