1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2013 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
7 // Why base-58 instead of standard base-64 encoding?
8 // - Don't want 0OIl characters that look the same in some fonts and
9 // could be used to create visually identical looking account numbers.
10 // - A string with non-alphanumeric characters is not as easily accepted as an account number.
11 // - E-mail usually won't line-break if there's no punctuation to break at.
12 // - Double-clicking selects the whole number as one word if it's all alphanumeric.
14 #ifndef BITCOIN_BASE58_H
15 #define BITCOIN_BASE58_H
17 #include "chainparams.h"
26 #include <boost/variant/apply_visitor.hpp>
27 #include <boost/variant/static_visitor.hpp>
30 * Encode a byte sequence as a base58-encoded string.
31 * pbegin and pend cannot be NULL, unless both are.
33 std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend);
36 * Encode a byte vector as a base58-encoded string
38 inline std::string EncodeBase58(const std::vector<unsigned char>& vch)
40 return EncodeBase58(&vch[0], &vch[0] + vch.size());
44 * Decode a base58-encoded string (psz) into a byte vector (vchRet).
45 * return true if decoding is successful.
48 bool DecodeBase58(const char* psz, std::vector<unsigned char>& vchRet);
51 * Decode a base58-encoded string (str) into a byte vector (vchRet).
52 * return true if decoding is successful.
54 inline bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet)
56 return DecodeBase58(str.c_str(), vchRet);
60 * Encode a byte vector into a base58-encoded string, including checksum
62 inline std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
64 // add 4-byte hash check to the end
65 std::vector<unsigned char> vch(vchIn);
66 uint256 hash = Hash(vch.begin(), vch.end());
67 vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
68 return EncodeBase58(vch);
72 * Decode a base58-encoded string (psz) that includes a checksum into a byte
73 * vector (vchRet), return true if decoding is successful
75 inline bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet)
77 if (!DecodeBase58(psz, vchRet))
79 if (vchRet.size() < 4)
84 // re-calculate the checksum, insure it matches the included 4-byte checksum
85 uint256 hash = Hash(vchRet.begin(), vchRet.end()-4);
86 if (memcmp(&hash, &vchRet.end()[-4], 4) != 0)
91 vchRet.resize(vchRet.size()-4);
96 * Decode a base58-encoded string (str) that includes a checksum into a byte
97 * vector (vchRet), return true if decoding is successful
99 inline bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet)
101 return DecodeBase58Check(str.c_str(), vchRet);
105 * Base class for all base58-encoded data
110 // the version byte(s)
111 std::vector<unsigned char> vchVersion;
113 // the actually encoded data
114 typedef std::vector<unsigned char, zero_after_free_allocator<unsigned char> > vector_uchar;
115 vector_uchar vchData;
123 void SetData(const std::vector<unsigned char> &vchVersionIn, const void* pdata, size_t nSize)
125 vchVersion = vchVersionIn;
126 vchData.resize(nSize);
127 if (!vchData.empty())
128 memcpy(&vchData[0], pdata, nSize);
131 void SetData(const std::vector<unsigned char> &vchVersionIn, const unsigned char *pbegin, const unsigned char *pend)
133 SetData(vchVersionIn, (void*)pbegin, pend - pbegin);
137 bool SetString(const char* psz, unsigned int nVersionBytes = 1)
139 std::vector<unsigned char> vchTemp;
140 DecodeBase58Check(psz, vchTemp);
141 if (vchTemp.size() < nVersionBytes)
147 vchVersion.assign(vchTemp.begin(), vchTemp.begin() + nVersionBytes);
148 vchData.resize(vchTemp.size() - nVersionBytes);
149 if (!vchData.empty())
150 memcpy(&vchData[0], &vchTemp[nVersionBytes], vchData.size());
151 OPENSSL_cleanse(&vchTemp[0], vchData.size());
155 bool SetString(const std::string& str)
157 return SetString(str.c_str());
160 std::string ToString() const
162 std::vector<unsigned char> vch = vchVersion;
163 vch.insert(vch.end(), vchData.begin(), vchData.end());
164 return EncodeBase58Check(vch);
167 int CompareTo(const CBase58Data& b58) const
169 if (vchVersion < b58.vchVersion) return -1;
170 if (vchVersion > b58.vchVersion) return 1;
171 if (vchData < b58.vchData) return -1;
172 if (vchData > b58.vchData) return 1;
176 bool operator==(const CBase58Data& b58) const { return CompareTo(b58) == 0; }
177 bool operator<=(const CBase58Data& b58) const { return CompareTo(b58) <= 0; }
178 bool operator>=(const CBase58Data& b58) const { return CompareTo(b58) >= 0; }
179 bool operator< (const CBase58Data& b58) const { return CompareTo(b58) < 0; }
180 bool operator> (const CBase58Data& b58) const { return CompareTo(b58) > 0; }
183 /** base58-encoded Bitcoin addresses.
184 * Public-key-hash-addresses have version 0 (or 111 testnet).
185 * The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key.
186 * Script-hash-addresses have version 5 (or 196 testnet).
187 * The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script.
189 class CBitcoinAddress;
190 class CBitcoinAddressVisitor : public boost::static_visitor<bool>
193 CBitcoinAddress *addr;
195 CBitcoinAddressVisitor(CBitcoinAddress *addrIn) : addr(addrIn) { }
196 bool operator()(const CKeyID &id) const;
197 bool operator()(const CScriptID &id) const;
198 bool operator()(const CNoDestination &no) const;
201 class CBitcoinAddress : public CBase58Data
204 bool Set(const CKeyID &id) {
205 SetData(Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS), &id, 20);
209 bool Set(const CScriptID &id) {
210 SetData(Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS), &id, 20);
214 bool Set(const CTxDestination &dest)
216 return boost::apply_visitor(CBitcoinAddressVisitor(this), dest);
221 bool fCorrectSize = vchData.size() == 20;
222 bool fKnownVersion = vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS) ||
223 vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS);
224 return fCorrectSize && fKnownVersion;
231 CBitcoinAddress(const CTxDestination &dest)
236 CBitcoinAddress(const std::string& strAddress)
238 SetString(strAddress);
241 CBitcoinAddress(const char* pszAddress)
243 SetString(pszAddress);
246 CTxDestination Get() const {
248 return CNoDestination();
250 memcpy(&id, &vchData[0], 20);
251 if (vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
253 else if (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS))
254 return CScriptID(id);
256 return CNoDestination();
259 bool GetKeyID(CKeyID &keyID) const {
260 if (!IsValid() || vchVersion != Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
263 memcpy(&id, &vchData[0], 20);
268 bool IsScript() const {
269 return IsValid() && vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS);
273 bool inline CBitcoinAddressVisitor::operator()(const CKeyID &id) const { return addr->Set(id); }
274 bool inline CBitcoinAddressVisitor::operator()(const CScriptID &id) const { return addr->Set(id); }
275 bool inline CBitcoinAddressVisitor::operator()(const CNoDestination &id) const { return false; }
278 * A base58-encoded secret key
280 class CBitcoinSecret : public CBase58Data
283 void SetKey(const CKey& vchSecret)
285 assert(vchSecret.IsValid());
286 SetData(Params().Base58Prefix(CChainParams::SECRET_KEY), vchSecret.begin(), vchSecret.size());
287 if (vchSecret.IsCompressed())
288 vchData.push_back(1);
294 ret.Set(&vchData[0], &vchData[32], vchData.size() > 32 && vchData[32] == 1);
300 bool fExpectedFormat = vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1);
301 bool fCorrectVersion = vchVersion == Params().Base58Prefix(CChainParams::SECRET_KEY);
302 return fExpectedFormat && fCorrectVersion;
305 bool SetString(const char* pszSecret)
307 return CBase58Data::SetString(pszSecret) && IsValid();
310 bool SetString(const std::string& strSecret)
312 return SetString(strSecret.c_str());
315 CBitcoinSecret(const CKey& vchSecret)
325 template<typename K, int Size, CChainParams::Base58Type Type> class CBitcoinExtKeyBase : public CBase58Data
328 void SetKey(const K &key) {
329 unsigned char vch[Size];
331 SetData(Params().Base58Prefix(Type), vch, vch+Size);
336 ret.Decode(&vchData[0], &vchData[Size]);
340 CBitcoinExtKeyBase(const K &key) {
344 CBitcoinExtKeyBase() {}
347 typedef CBitcoinExtKeyBase<CExtKey, 74, CChainParams::EXT_SECRET_KEY> CBitcoinExtKey;
348 typedef CBitcoinExtKeyBase<CExtPubKey, 74, CChainParams::EXT_PUBLIC_KEY> CBitcoinExtPubKey;
350 #endif // BITCOIN_BASE58_H