比特币源码解读之私钥、公钥和地址

(本文使用的是比特币v0.1.0版本 点击下载源码)

  • 公钥和私钥的生成
    • 密钥的生成
    • 公钥的获取
    • 私钥的获取
    • 公钥和私钥的存储
  • 通过公钥生成公钥HASH
  • 通过公钥Hash生成地址
    • 公钥HASH前缀加上一个字节的版本号
    • 公钥HASH后缀加入4字节的校验码
    • 通过EncodeBase58编码生成比特币地址

比特币是建立在数字加密基础上的,接触过比特币的朋友应该知道:
(1)购买比特币最后是通过一个比特币地址进行的,比特币地址就像支票中的支付对象(收款方);
(2)而比特币地址则是通过公钥单向哈希生成的;
(3)而公钥则是通过私钥使用椭圆曲线算法生成的,
(4)而私钥通过操作系统底层生成的256位随机熵;
比特币系统的私钥、公钥和地址生成是通过OpenSSL库实现的。
具体流程图如下所示:
比特币源码解读之私钥、公钥和地址_第1张图片

公钥和私钥的生成

密钥的生成

 
  
  1. CKey key;
  2. key.MakeNewKey();
  3. void MakeNewKey()
  4. {
  5. if (!EC_KEY_generate_key(pkey))
  6. throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
  7. }

公钥的获取

 
  
  1. vector<unsigned char> GetPubKey() const
  2. {
  3. unsigned int nSize = i2o_ECPublicKey(pkey, NULL);
  4. if (!nSize)
  5. throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
  6. vector<unsigned char> vchPubKey(nSize, 0);
  7. unsigned char* pbegin = &vchPubKey[0];
  8. if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
  9. throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
  10. return vchPubKey;
  11. }

私钥的获取

 
  
  1. CPrivKey GetPrivKey() const
  2. {
  3. unsigned int nSize = i2d_ECPrivateKey(pkey, NULL);
  4. if (!nSize)
  5. throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");
  6. CPrivKey vchPrivKey(nSize, 0);
  7. unsigned char* pbegin = &vchPrivKey[0];
  8. if (i2d_ECPrivateKey(pkey, &pbegin) != nSize)
  9. throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size");
  10. return vchPrivKey;
  11. }

公钥和私钥的存储

私钥存储在mapKeys结构中(键为公钥),公钥存储在mapPubKeys结果中(键为公钥HASH)

 
  
  1. mapKeys[key.GetPubKey()] = key.GetPrivKey();
  2. mapPubKeys[Hash160(key.GetPubKey())] = key.GetPubKey();

通过公钥生成公钥HASH

公钥先使用SHA256函数再使用RIPEMD160函数生成公钥HASH

 
  
  1. inline uint160 Hash160(const vector<unsigned char>& vch)
  2. {
  3. uint256 hash1;
  4. SHA256(&vch[0], vch.size(), (unsigned char*)&hash1);
  5. uint160 hash2;
  6. RIPEMD160((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);
  7. return hash2;
  8. }

通过公钥Hash生成地址

公钥HASH前缀加上一个字节的版本号

 
  
  1. inline string Hash160ToAddress(uint160 hash160)
  2. {
  3. // add 1-byte version number to the front
  4. vector<unsigned char> vch(1, ADDRESSVERSION);
  5. vch.insert(vch.end(), UBEGIN(hash160), UEND(hash160));
  6. return EncodeBase58Check(vch);
  7. }

公钥HASH后缀加入4字节的校验码

 
  
  1. inline string EncodeBase58Check(const vector<unsigned char>& vchIn)
  2. {
  3. // add 4-byte hash check to the end
  4. vector<unsigned char> vch(vchIn);
  5. uint256 hash = Hash(vch.begin(), vch.end());
  6. vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
  7. return EncodeBase58(vch);
  8. }

通过EncodeBase58编码生成比特币地址

 
  
  1. inline string EncodeBase58(const vector<unsigned char>& vch)
  2. {
  3. return EncodeBase58(&vch[0], &vch[0] + vch.size());
  4. }

上一篇: 比特币源码解读之线程处理-其他线程

下一篇:比特币源码解读之创世块的产生

版权声明:B链网原创,严禁修改。转载请注明作者和原文链接
http://www.360bchain.com/article/67.html



版权声明:B链网原创,严禁修改。转载请注明作者和原文链接

作者:雨后的蚊子

原文链接: http://www.360bchain.com/article/67.html

你可能感兴趣的:(区块链)