1. 程式人生 > >比特幣原始碼解讀之私鑰、公鑰和地址

比特幣原始碼解讀之私鑰、公鑰和地址

(本文使用的是比特幣v0.1.0版本 點選下載原始碼)

比特幣是建立在數字加密基礎上的,接觸過比特幣的朋友應該知道:
(1)購買比特幣最後是通過一個比特幣地址進行的,比特幣地址就像支票中的支付物件(收款方);
(2)而比特幣地址則是通過公鑰單向雜湊生成的;
(3)而公鑰則是通過私鑰使用橢圓曲線演算法生成的,
(4)而私鑰通過作業系統底層生成的256位隨機熵;
比特幣系統的私鑰、公鑰和地址生成是通過OpenSSL庫實現的。
具體流程圖如下所示:

公鑰和私鑰的生成

金鑰的生成

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

公鑰的獲取

  1. vector<unsignedchar>GetPubKey()const
  2. {
  3. unsignedint nSize = i2o_ECPublicKey(pkey, NULL);
  4. if(!nSize)
  5. throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
  6. vector<unsignedchar> vchPubKey(nSize,0);
  7. unsignedchar* 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. CPrivKeyGetPrivKey()const
  2. {
  3. unsignedint nSize = i2d_ECPrivateKey(pkey, NULL);
  4. if(!nSize)
  5. throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed"
    );
  6. CPrivKey vchPrivKey(nSize,0);
  7. unsignedchar* 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. inlineuint160Hash160(constvector<unsignedchar>& vch)
  2. {
  3. uint256 hash1;
  4. SHA256(&vch[0], vch.size(),(unsignedchar*)&hash1);
  5. uint160 hash2;
  6. RIPEMD160((unsignedchar*)&hash1,sizeof(hash1),(unsignedchar*)&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<unsignedchar> vch(1, ADDRESSVERSION);
  5. vch.insert(vch.end(), UBEGIN(hash160), UEND(hash160));
  6. returnEncodeBase58Check(vch);
  7. }

公鑰HASH字尾加入4位元組的校驗碼

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

通過EncodeBase58編碼生成比特幣地址

  1. inline string EncodeBase58(constvector<unsignedchar>& vch)
  2. {
  3. returnEncodeBase58(&vch[0],&vch[0]+ vch.size());
  4. }

作者:雨後的蚊子