密钥存储测试示例
Bitcoin(0.06.0)中密钥存储keystore类定义如下:
/** A virtual base class for key stores */
class CKeyStore
{
protected:
//mutable CCriticalSection cs_KeyStore;
public:
virtual ~CKeyStore() {}
//! Add a key to the store.
virtual bool AddKeyPubKey(const CKey &key, const CPubKey &pubkey) =0;
virtual bool AddKey(const CKey &key);
//! Check whether a key corresponding to a given address is present in the store.
virtual bool HaveKey(const CKeyID &address) const =0;
virtual bool GetKey(const CKeyID &address, CKey& keyOut) const =0;
virtual std::set<CKeyID> GetKeys() const =0;
virtual bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const =0;
//! Support for BIP 0013 : see https://github.com/bitcoin/bips/blob/master/bip-0013.mediawiki
virtual bool AddCScript(const CScript& redeemScript) =0;
virtual bool HaveCScript(const CScriptID &hash) const =0;
virtual std::set<CScriptID> GetCScripts() const =0;
virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const =0;
//! Support for Watch-only addresses
virtual bool AddWatchOnly(const CScript &dest) =0;
virtual bool RemoveWatchOnly(const CScript &dest) =0;
virtual bool HaveWatchOnly(const CScript &dest) const =0;
virtual bool HaveWatchOnly() const =0;
};
typedef std::map<CKeyID, CKey> KeyMap;
typedef std::map<CKeyID, CPubKey> WatchKeyMap;
typedef std::map<CScriptID, CScript > ScriptMap;
typedef std::set<CScript> WatchOnlySet;
此类为虚类,添加密钥实现方法类为CBasicKeyStore:
/** Basic key store, that keeps keys in an address->secret map */
class CBasicKeyStore : public CKeyStore
{
protected:
KeyMap mapKeys;
WatchKeyMap mapWatchKeys;
ScriptMap mapScripts;
WatchOnlySet setWatchOnly;
void ImplicitlyLearnRelatedKeyScripts(const CPubKey& pubkey);
public:
bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey) override;
bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const override;
bool HaveKey(const CKeyID &address) const override;
std::set<CKeyID> GetKeys() const override;
bool GetKey(const CKeyID &address, CKey &keyOut) const override;
bool AddCScript(const CScript& redeemScript) override;
bool HaveCScript(const CScriptID &hash) const override;
std::set<CScriptID> GetCScripts() const override;
bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const override;
bool AddWatchOnly(const CScript &dest) override;
bool RemoveWatchOnly(const CScript &dest) override;
bool HaveWatchOnly(const CScript &dest) const override;
bool HaveWatchOnly() const override;
};
//typedef std::vector<unsigned char, secure_allocator<unsigned char> > CKeyingMaterial;
typedef std::vector<unsigned char> CKeyingMaterial;
typedef std::map<CKeyID, std::pair<CPubKey, std::vector<unsigned char> > > CryptedKeyMap;
/** Return the CKeyID of the key involved in a script (if there is a unique one). */
CKeyID GetKeyForDestination(const CKeyStore& store, const CTxDestination& dest);
密钥对添加方法为:
// 添加公钥对应的脚本
void CBasicKeyStore::ImplicitlyLearnRelatedKeyScripts(const CPubKey& pubkey)
{
//AssertLockHeld(cs_KeyStore);
CKeyID key_id = pubkey.GetID();
// We must actually know about this key already.
assert(HaveKey(key_id) || mapWatchKeys.count(key_id));
// This adds the redeemscripts necessary to detect P2WPKH and P2SH-P2WPKH
// outputs. Technically P2WPKH outputs don't have a redeemscript to be
// spent. However, our current IsMine logic requires the corresponding
// P2SH-P2WPKH redeemscript to be present in the wallet in order to accept
// payment even to P2WPKH outputs.
// Also note that having superfluous scripts in the keystore never hurts.
// They're only used to guide recursion in signing and IsMine logic - if
// a script is present but we can't do anything with it, it has no effect.
// "Implicitly" refers to fact that scripts are derived automatically from
// existing keys, and are present in memory, even without being explicitly
// loaded (e.g. from a file).
if (pubkey.IsCompressed()) {
CScript script = GetScriptForDestination(WitnessV0KeyHash(key_id));
// This does not use AddCScript, as it may be overridden.
CScriptID id(script);
mapScripts[id] = std::move(script);
}
}
bool CBasicKeyStore::AddKeyPubKey(const CKey& key, const CPubKey &pubkey)
{
//LOCK(cs_KeyStore);
mapKeys[pubkey.GetID()] = key; // 将公钥的Hash160值添加到std::map中
ImplicitlyLearnRelatedKeyScripts(pubkey); //将公钥对应的脚本存储
return true;
}
测试主函数如下:
// 密钥存储测试程序
int main_keystoretest(){
ECCVerifyHandle eccVerifyHandle ;
ECC_Start();
// 创建一个密钥存储
CBasicKeyStore keystore;
CKey priKey;
CPubKey pubKey;
// 添加一个密钥对
priKey.Set(TestPriKey.begin(), TestPriKey.end(), true);
pubKey.Set(TestPubKey.begin(), TestPubKey.end());
keystore.AddKeyPubKey(priKey, pubKey);
priKey.Set(TestPriKeyA.begin(), TestPriKeyA.end(), true);
pubKey.Set(TestPubKeyA.begin(), TestPubKeyA.end());
keystore.AddKeyPubKey(priKey, pubKey);
priKey.Set(TestPriKeyB.begin(), TestPriKeyB.end(), true);
pubKey.Set(TestPubKeyB.begin(), TestPubKeyB.end());
keystore.AddKeyPubKey(priKey, pubKey);
// 获取所有密钥对
CKey priKey1;
CPubKey pubKey1;
int count = 0;
std::set<CKeyID> keys = keystore.GetKeys();
for(std::set<CKeyID>::iterator it = keys.begin(); it != keys.end(); it++){
std::cout<<"**** Key "<<count++<<std::endl;
if(keystore.GetKey(*it, priKey1)){
std::cout<<"Private key:";
print_vector(priKey1.begin(), priKey1.size());
}
if(keystore.GetPubKey(*it, pubKey1)){
std::cout<<"Public key:";
print_vector(pubKey1, pubKey.size());
}
}
pubKey.Set(TestPubKey.begin(), TestPubKey.end());
CKeyID address = pubKey.GetID();
// 添加脚本
CScript script = GetScriptForDestination(Witnes0sV0KeyHash(address));
CScriptID hash(script);
// 根据脚本获取key
address = GetKeyForDestination(keystore, script);
std::cout<<"**** Address: ";
print_vector(address.begin(), address.size());
// 添加密钥对时已添加对应得脚本,所以存储中已存在脚本
if(keystore.HaveCScript(hash)){
std::cout<<"**** Have script: ";
print_vector(hash.begin(), hash.size());
}
// 通过脚本哈希值获取脚本
if(keystore.GetCScript(hash, script)){
std::cout<<"**** Get script: ";
print_vector(script, script.size());
}
// 只看脚本
if(!keystore.HaveWatchOnly(script)){
keystore.AddWatchOnly(script);
if(keystore.HaveWatchOnly(script)){
std::cout<<"**** Watch:";
print_vector(script, script.size());
}
}
ECC_Stop();
return 0;
}
主函数输出:
===================================================================================================
Keystore
===================================================================================================
**** Key 0
Private key:9a9a6539856be209b8ea2adbd155c0919646d108515b60b7b13d6a79f1ae5174
-------------------
Public key:0340a609475afa1f9a784cad0db5d5ba7dbaab2147a5d7b9bbde4d1334a0e40a5e
-------------------
**** Key 1
Private key:3e46c724c8e9728379a9cab2ec46030563f06d7e0ace2b734b5861b8f64b6f2f
-------------------
Public key:020e80933a750e84b4c35c10bc797ca34d1c885e4e65531a7499170a1c78ffdd97
-------------------
**** Key 2
Private key:6bce49ff84094382d822178de357a435f85e8ad8fdfa39bd58aa2e5192267198
-------------------
Public key:03e3bd2f408e4415aa57c747f6550937823a8605706c358facdc6325b4a99f2161
-------------------
**** Address: 154de7cabbb5822075e92c57a27ca3ef3e8be50c
-------------------
**** Have script: c596906f342478ca56707f7bb1bda659cb3cef98
-------------------
**** Get script: 0014154de7cabbb5822075e92c57a27ca3ef3e8be50c
-------------------
**** Watch:0014154de7cabbb5822075e92c57a27ca3ef3e8be50c
-------------------
===================================================================================================
源代码:
https://github.com/babylco0/bitcoin_code_examples/tree/master/TestKey-1.1.0