Bicoint(0.16.0)私钥定义:
/**
* secure_allocator is defined in allocators.h
* CPrivKey is a serialized private key, with all parameters included
* (PRIVATE_KEY_SIZE bytes)
*/
//typedef std::vector > CPrivKey;
// 为测试方便,将容器存储分配修改为系统默认方式
typedef std::vector<unsigned char> CPrivKey;
/** An encapsulated private key. */
class CKey
{
public:
/**
* secp256k1:
*/
static const unsigned int PRIVATE_KEY_SIZE = 279;// 私钥长度
static const unsigned int COMPRESSED_PRIVATE_KEY_SIZE = 214;// 压缩私钥长度
/**
* see www.keylength.com
* script supports up to 75 for single byte push
*/
static_assert(
PRIVATE_KEY_SIZE >= COMPRESSED_PRIVATE_KEY_SIZE,
"COMPRESSED_PRIVATE_KEY_SIZE is larger than PRIVATE_KEY_SIZE");
private:
//! Whether this private key is valid. We check for correctness when modifying the key
//! data, so fValid should always correspond to the actual state.
bool fValid;//私钥有效标识
//! Whether the public key corresponding to this private key is (to be) compressed.
bool fCompressed;//私钥压缩标识
//! The actual byte data
//std::vector > keydata;
std::vector<unsigned char> keydata;//私钥数据
//! Check whether the 32-byte array pointed to by vch is valid keydata.
bool static Check(const unsigned char* vch);//检测vch中的数据是否为有效私钥
public:
//! Construct an invalid private key.
// 构造一个无效的私钥
CKey() : fValid(false), fCompressed(false)
{
// Important: vch must be 32 bytes in length to not break serialization
keydata.resize(32);
}
friend bool operator==(const CKey& a, const CKey& b)
{
return a.fCompressed == b.fCompressed &&
a.size() == b.size() &&
memcmp(a.keydata.data(), b.keydata.data(), a.size()) == 0;
}
//! Initialize using begin and end iterators to byte data.
// 使用迭代器初始化私钥数据
template <typename T>
void Set(const T pbegin, const T pend, bool fCompressedIn)
{
if (size_t(pend - pbegin) != keydata.size()) {
fValid = false;
} else if (Check(&pbegin[0])) {
memcpy(keydata.data(), (unsigned char*)&pbegin[0], keydata.size());
fValid = true;
fCompressed = fCompressedIn;
} else {
fValid = false;
}
}
//! Simple read-only vector-like interface.
unsigned int size() const { return (fValid ? keydata.size() : 0); }
const unsigned char* begin() const { return keydata.data(); }
const unsigned char* end() const { return keydata.data() + size(); }
//! Check whether this private key is valid.
bool IsValid() const { return fValid; }
//! Check whether the public key corresponding to this private key is (to be) compressed.
bool IsCompressed() const { return fCompressed; }
//! Generate a new private key using a cryptographic PRNG.
// 生成一个随机私钥
void MakeNewKey(bool fCompressed);
/**
* Convert the private key to a CPrivKey (serialized OpenSSL private key data).
* This is expensive.
*/
CPrivKey GetPrivKey() const;
/**
* Compute the public key from a private key.
* This is expensive.
*/
// 获取公钥
CPubKey GetPubKey() const;
/**
* Create a DER-serialized signature.
* The test_case parameter tweaks the deterministic nonce.
*/
// 生成一个DER签名
bool Sign(const uint256& hash, std::vector<unsigned char>& vchSig, uint32_t test_case = 0) const;
/**
* Create a compact signature (65 bytes), which allows reconstructing the used public key.
* The format is one header byte, followed by two times 32 bytes for the serialized r and s values.
* The header byte: 0x1B = first key with even y, 0x1C = first key with odd y,
* 0x1D = second key with even y, 0x1E = second key with odd y,
* add 0x04 for compressed keys.
*/
// 生成一个协议签名,可用来重构建公钥
bool SignCompact(const uint256& hash, std::vector<unsigned char>& vchSig) const;
//! Derive BIP32 child key.
// 派生BIP32子私钥
bool Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const;
/**
* Verify thoroughly whether a private key and a public key match.
* This is done using a different mechanism than just regenerating it.
*/
// 验证公钥和私钥是否匹配
bool VerifyPubKey(const CPubKey& vchPubKey) const;
//! Load private key and check that public key matches.
// 从CPrivKey数据中导入私钥
bool Load(const CPrivKey& privkey, const CPubKey& vchPubKey, bool fSkipCheck);
};
Bicoint(0.16.0)公钥定义:
const unsigned int BIP32_EXTKEY_SIZE = 74;
/** A reference to a CKey: the Hash160 of its serialized public key */
// 公钥的Hash-160值(SHA-256+RIPEMD-160)
class CKeyID : public uint160
{
public:
CKeyID() : uint160() {}
explicit CKeyID(const uint160& in) : uint160(in) {}
};
// 链码,用于派生子私(公)钥
typedef uint256 ChainCode;
/** An encapsulated public key. */
class CPubKey
{
public:
/**
* secp256k1:
*/
static const unsigned int PUBLIC_KEY_SIZE = 65;//公钥长度
static const unsigned int COMPRESSED_PUBLIC_KEY_SIZE = 33;//压缩公钥长度
static const unsigned int SIGNATURE_SIZE = 72;//签名长度
static const unsigned int COMPACT_SIGNATURE_SIZE = 65;//协议签名长度
/**
* see www.keylength.com
* script supports up to 75 for single byte push
*/
static_assert(
PUBLIC_KEY_SIZE >= COMPRESSED_PUBLIC_KEY_SIZE,
"COMPRESSED_PUBLIC_KEY_SIZE is larger than PUBLIC_KEY_SIZE");
private:
/**
* Just store the serialized data.
* Its length can very cheaply be computed from the first byte.
*/
// 公钥数据
unsigned char vch[PUBLIC_KEY_SIZE];
//! Compute the length of a pubkey with a given first byte.
unsigned int static GetLen(unsigned char chHeader)
{
if (chHeader == 2 || chHeader == 3)
return COMPRESSED_PUBLIC_KEY_SIZE;
if (chHeader == 4 || chHeader == 6 || chHeader == 7)
return PUBLIC_KEY_SIZE;
return 0;
}
//! Set this key data to be invalid
// 设置公钥无效
void Invalidate()
{
vch[0] = 0xFF;
}
public:
//! Construct an invalid public key.
// 构造一个无效公钥
CPubKey()
{
Invalidate();
}
//! Initialize a public key using begin/end iterators to byte data.
// 使用容器初始化公钥数据
template <typename T>
void Set(const T pbegin, const T pend)
{
int len = pend == pbegin ? 0 : GetLen(pbegin[0]);
if (len && len == (pend - pbegin))
memcpy(vch, (unsigned char*)&pbegin[0], len);
else
Invalidate();
}
//! Construct a public key using begin/end iterators to byte data.
// 使用容器构造一个公钥
template <typename T>
CPubKey(const T pbegin, const T pend)
{
Set(pbegin, pend);
}
//! Construct a public key from a byte vector.
// 使用字节数组构造公钥
explicit CPubKey(const std::vector<unsigned char>& _vch)
{
Set(_vch.begin(), _vch.end());
}
//! Simple read-only vector-like interface to the pubkey data.
unsigned int size() const { return GetLen(vch[0]); }
const unsigned char* begin() const { return vch; }
const unsigned char* end() const { return vch + size(); }
const unsigned char& operator[](unsigned int pos) const { return vch[pos]; }
//! Comparator implementation.
friend bool operator==(const CPubKey& a, const CPubKey& b)
{
return a.vch[0] == b.vch[0] &&
memcmp(a.vch, b.vch, a.size()) == 0;
}
friend bool operator!=(const CPubKey& a, const CPubKey& b)
{
return !(a == b);
}
friend bool operator<(const CPubKey& a, const CPubKey& b)
{
return a.vch[0] < b.vch[0] ||
(a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) < 0);
}
// 序列化操作未测试
// //! Implement serialization, as if this was a byte vector.
// template
// void Serialize(Stream& s) const
// {
// unsigned int len = size();
// ::WriteCompactSize(s, len);
// s.write((char*)vch, len);
// }
// template
// void Unserialize(Stream& s)
// {
// unsigned int len = ::ReadCompactSize(s);
// if (len <= PUBLIC_KEY_SIZE) {
// s.read((char*)vch, len);
// } else {
// // invalid pubkey, skip available data
// char dummy;
// while (len--)
// s.read(&dummy, 1);
// Invalidate();
// }
// }
//! Get the KeyID of this public key (hash of its serialization)
// 获取公钥的Hash160哈希值(SHA-256+RIPEMD-160哈希值)
CKeyID GetID() const
{
return CKeyID(Hash160(vch, vch + size()));
}
//! Get the 256-bit hash of this public key.
// 获取公钥Hash256值(两次SHA-256哈希值)
uint256 GetHash() const
{
return Hash(vch, vch + size());
}
/*
* Check syntactic correctness.
*
* Note that this is consensus critical as CheckSig() calls it!
*/
bool IsValid() const
{
return size() > 0;
}
//! fully validate whether this is a valid public key (more expensive than IsValid())
bool IsFullyValid() const;
//! Check whether this is a compressed public key.
bool IsCompressed() const
{
return size() == COMPRESSED_PUBLIC_KEY_SIZE;
}
/**
* Verify a DER signature (~72 bytes).
* If this public key is not fully valid, the return value will be false.
*/
// 验证DER签名是否正确
bool Verify(const uint256& hash, const std::vector<unsigned char>& vchSig) const;
/**
* Check whether a signature is normalized (lower-S).
*/
static bool CheckLowS(const std::vector<unsigned char>& vchSig);
//! Recover a public key from a compact signature.
// 从协议签名中恢复公钥,见私钥SignCompact
bool RecoverCompact(const uint256& hash, const std::vector<unsigned char>& vchSig);
//! Turn this public key into an uncompressed public key.
bool Decompress();
//! Derive BIP32 child pubkey.
// 派生BIP32子公钥
bool Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const;
};
测试程序主函数:(Dev-C++(4.9.9.2))
int main(int argc, char** argv) {
// 测试私钥数据
//9a9a6539856be209b8ea2adbd155c0919646d108515b60b7b13d6a79f1ae5174
unsigned char testPriKey[32] = {0x9a, 0x9a, 0x65, 0x39, 0x85, 0x6b, 0xe2, 0x09,
0xb8, 0xea, 0x2a, 0xdb, 0xd1, 0x55, 0xc0, 0x91,
0x96, 0x46, 0xd1, 0x08, 0x51, 0x5b, 0x60, 0xb7,
0xb1, 0x3d, 0x6a, 0x79, 0xf1, 0xae, 0x51, 0x74};
// 测试公钥数据
//0340a609475afa1f9a784cad0db5d5ba7dbaab2147a5d7b9bbde4d1334a0e40a5e
std::vector<unsigned char> testPubKey = {0x03, 0x40, 0xa6, 0x09, 0x47, 0x5a, 0xfa, 0x1f, 0x9a,
0x78, 0x4c, 0xad, 0x0d, 0xb5, 0xd5, 0xba, 0x7d,
0xba, 0xab, 0x21, 0x47, 0xa5, 0xd7, 0xb9, 0xbb,
0xde, 0x4d, 0x13, 0x34, 0xa0, 0xe4, 0x0a, 0x5e};
CPrivKey LoadPriKey;
CKey priKey;
//priKey.MakeNewKey(true);
ECCVerifyHandle eccVerifyHandle ;//必须定义一个ECCVerifyHandle
ECC_Start();//初始化椭圆加密上下文结构体
// 设置私钥数据
priKey.Set(testPriKey, testPriKey+sizeof(testPriKey), true);
LoadPriKey = priKey.GetPrivKey();
std::cout<<std::setw(2)<<std::hex;
std::cout<<std::setfill('0');
// 打印私钥
std::cout<<"Private key [0x"<"]:";
for(int ii = 0; ii < priKey.size(); ii++)
{
std::cout<<std::setw(2)<<std::hex;
std::cout<<(int)(*(priKey.begin() + ii));
}
std::cout<<std::endl;
// 获取公钥
CPubKey pubKey(testPubKey);
// 打印公钥
std::cout<<"Public key [0x"<"]:";
for(int ii = 0; ii < pubKey.size(); ii++)
{
std::cout<<std::setw(2);
std::cout<<std::setfill('0')<<std::hex<<(int)(*(pubKey.begin() + ii));
}
std::cout<<std::endl;
// 检测公私钥是否匹配
if(priKey.VerifyPubKey(pubKey)){
std::cout<<"Private Key vs. Public Key Match."<<std::endl;
}
// 获取公钥 Hash-160
uint160 hash160 = pubKey.GetID();
// 打印公钥 Hash-160
std::cout<<"Hash-160 [0x"<"]:";
for(int ii = 0; ii < hash160.size(); ii++)
{
std::cout<<std::setw(2);
std::cout<<std::setfill('0')<<std::hex<<(int)(*(hash160.begin() + ii));
}
std::cout<<std::endl;
// 获取公钥哈希值
uint256 hash = pubKey.GetHash();
// 打印公钥哈希值
std::cout<<"Hash [0x"<"]:";
for(int ii = 0; ii < hash.size(); ii++)
{
std::cout<<std::setw(2);
std::cout<<std::setfill('0')<<std::hex<<(int)(*(hash.begin() + ii));
}
std::cout<<std::endl;
std::vector<unsigned char> vchSig;
priKey.Sign(hash, vchSig);
// 打印签名
std::cout<<"Sign [0x"<"]:";
for(int ii = 0; ii < vchSig.size(); ii++){
std::cout<<std::setw(2);
std::cout<<std::setfill('0')<<std::hex<<(int)(*(vchSig.begin() + ii));
}
std::cout<<std::endl;
// 校验签名
if(pubKey.CheckLowS(vchSig) && pubKey.Verify(hash, vchSig)){
std::cout<<"Public Key Signed."<<std::endl;
}
// 获取非压缩公钥
pubKey.Decompress();
// 打印公钥
std::cout<<"Public key [0x"<"]:";
for(int ii = 0; ii < pubKey.size(); ii++)
{
std::cout<<std::setw(2);
std::cout<<std::setfill('0')<<std::hex<<(int)(*(pubKey.begin() + ii));
}
std::cout<<std::endl;
priKey.SignCompact(hash, vchSig);
pubKey.RecoverCompact(hash, vchSig);
// 打印公钥
std::cout<<"Public key Recovered From SignCompact [0x"<"]:";
for(int ii = 0; ii < pubKey.size(); ii++)
{
std::cout<<std::setw(2);
std::cout<<std::setfill('0')<<std::hex<<(int)(*(pubKey.begin() + ii));
}
std::cout<<std::endl;
if(priKey.Load(LoadPriKey, pubKey, true)){
std::cout<<"Load private key ok."<<std::endl;
}
// 获取子私钥
CKey keyChild;
CPubKey pubkeyChild;
ChainCode ccChild;
unsigned int nChild = 1;
ChainCode cc = hash;
std::cout<<std::setw(100);
std::cout<<std::endl<<std::setfill('=')<<"="<<std::endl;
while(nChild <= 5){
std::cout<<"Child key: [0x";
std::cout<<std::setw(2);
std::cout<<std::setfill('0')<<std::hex<"]"<<std::endl;
std::cout<<"------------------------------------"<<std::endl;
if(priKey.Derive(keyChild, ccChild, nChild, cc)){
// 打印私钥
std::cout<<"Private key [0x"<"]:";
for(int ii = 0; ii < keyChild.size(); ii++)
{
std::cout<<std::setw(2);
std::cout<<std::setfill('0')<<std::hex<<(int)(*(keyChild.begin() + ii));
}
std::cout<<std::endl;
}
if(pubKey.Derive(pubkeyChild, ccChild, nChild, cc)){
// 打印公钥
std::cout<<"Public key [0x"<"]:";
for(int ii = 0; ii < pubkeyChild.size(); ii++)
{
std::cout<<std::setw(2);
std::cout<<std::setfill('0')<<std::hex<<(int)(*(pubkeyChild.begin() + ii));
}
std::cout<<std::endl;
}
// 验证公钥私钥是否匹配
if(!priKey.VerifyPubKey(pubKey)){
break;
}
cc = ccChild;
nChild++;
std::cout<<"------------------------------------"<<std::endl;
}
std::cout<<std::setw(100);
std::cout<<std::endl<<std::setfill('=')<<"="<<std::endl;
ECC_Stop();
return 0;
}
程序输出:
Private key [0x20]:9a9a6539856be209b8ea2adbd155c0919646d108515b60b7b13d6a79f1ae5174
Public key [0x21]:0340a609475afa1f9a784cad0db5d5ba7dbaab2147a5d7b9bbde4d1334a0e40a5e
Private Key vs. Public Key Match.
Hash-160 [0x14]:154de7cabbb5822075e92c57a27ca3ef3e8be50c
Hash [0x20]:bfb3881ab6c617bb88b3ccc2c338b7c589697ecdee8b7bce281881bc37b2d2f4
Sign [0x46]:304402201d7b33869f712b8a34b9f1be40a42dcb55e15d0b7d4f4f314120fd4e937bcaf6022015223e8b35ca63e750ea07259b92e8ba69995339783c58bc0422c20e5a67cef3
Public Key Signed.
Public key [0x41]:0440a609475afa1f9a784cad0db5d5ba7dbaab2147a5d7b9bbde4d1334a0e40a5e188ac3f1c6bbbc336fdc33cb5e605ff7c3ee2d36249933b0322220a616a11fb3
Public key Recovered From SignCompact [0x21]:0340a609475afa1f9a784cad0db5d5ba7dbaab2147a5d7b9bbde4d1334a0e40a5e
Load private key ok.
====================================================================================================
Child key: [0x01]
------------------------------------
Private key [0x21]:601195ea72ec9f79fad5efe86ec9411a868d1a9f7c1a7c9709512471f41a7348
Public key [0x21]:02167423614e974d6ccad42514ea24f75df91a1c56c034aa7a5db07ecb8a31803e
------------------------------------
Child key: [0x02]
------------------------------------
Private key [0x21]:ec94b96eb36eb4ff03f6596e3523247a402a26a7d021aaf486843cbb2bdcbeac
Public key [0x21]:0273cdb90c02d53c8da352bd56cfe219eaf1206d677b01edb9be7303302db2c78a
------------------------------------
Child key: [0x03]
------------------------------------
Private key [0x21]:5c969056631b9cee3ebc618171f22f44e6f6c6579131bdd4f33c09ecfc255b99
Public key [0x21]:0355d75406b5cd1c9096fe86f1c761d4487ffd44220606c29e780a6cd6588baa55
------------------------------------
Child key: [0x04]
------------------------------------
Private key [0x21]:94bb61ee22b5101dcf390358639f105d4704a1b87cfa8bb23ff04dd5aa5d2cb4
Public key [0x21]:02fb24789c30cee067333c9f7f9738c850de3fe7ece9137f1178a232854e1a5578
------------------------------------
Child key: [0x05]
------------------------------------
Private key [0x21]:d6cf632cb5e1df23f6399515c8e1d981c2a2914c8726c6cb84e812a017177ccb
Public key [0x21]:03e311fa62acb96833cbaf74fa916d0acbd514a9f85abcfc5535efc272d8448762
------------------------------------
====================================================================================================
源码地址:
https://github.com/babylco0/bitcoin_code_examples/tree/master/testCKey
https://github.com/babylco0/bitcoin_code_examples/tree/master/TestKey (ubuntu)