上文《比特幣btcd代碼之初體驗》提到比特幣除了主網外,還有Testnet以及Regtest網路。
Testnet是公開的測試網,所有開發都可以訪問這個網路,為了避免有人惡意囤積上面的Testnet bitcoin,這個testnet每隔一段時期就會清空並以新的創始塊重新開始。這也應該就是代碼裡面有時候會看到testnet3的原因。
Regtest則是本地的測試網路,這個網路不會公開出去,僅作為本地開發測試使用。
除此之外,還有Segnet即隔離見證的測試網路。而btcd代碼裡還看到了simnet這個測試網路選項,目測和Regtest一樣是本地測試網路,但是具體有什麼不同暫時未深入研究。
這篇文章主要從btcd相關代碼出發,研究比特幣的私密金鑰、公開金鑰以及地址如何產生,詳情參見精通比特幣第二版(中文版),簡單地說:
第一步,也是最重要的一步,從一個隨機數產生私密金鑰。比特幣軟體使用作業系統底層的隨機數產生器來產生256位的熵,即私密金鑰。
第二步,通過橢圓曲線乘法可以從私密金鑰計算得到公開金鑰。
第三步,從公開金鑰計算出比特幣地址。
以下代碼是從《在比特幣上表白-使用Golang將誓言存在比特幣的區塊鏈上》拷貝過來的代碼
分析如下:
隨機數與私密金鑰
privKey, err := btcec.NewPrivateKey(btcec.S256())
首先,在之前clone的btcd代碼裡,其中有一個模組叫btcec,它實現了比特幣所需的橢圓曲線密碼演算法。S256返回的是一個實現了secp256k1標準所定義的一種特殊的橢圓曲線。再查看NewPrivateKey實現細節,發現是把一個橢圓曲線以及隨機數產生器傳入了crypto包。
這段代碼直接返回了私密金鑰和公開金鑰,即上述的第一步和第二步。需要注意這代碼裡key是PrivateKey類型的對象,其有變數存放了公開金鑰。
這裡剛好可以和比特幣源碼研讀(1)--私密金鑰文章裡做一對比,可以發現在C++版本裡,其隨機數產生的隨機性應該更強,因為它同時採用了幾個不同的隨機源,而Golang版本則只用了軟體提供的rand方法。這可能會有潛在的隱患,假如某一環境下軟體的隨機數分布不均衡,隨機數演算法中選取了某一段地區內的高機率隨機數。那麼原本理論上2^256個範圍便會大大縮小,駭客從而提高了隨機性碰撞的可能性。
WIF
privKeyWif, err := btcutil.NewWIF(privKey, &chaincfg.MainNetParams,false)
繼續看代碼,這句是把256位元字的私密金鑰以錢包匯入格式(WIF)來表示。同樣的256位元字的私密金鑰,通過不同編碼可以有不同的表示,WIF是其中一種格式。
相同的密鑰,不同的格式
需要留意這裡用到了與btcd項目同屬的btcutil代碼,可以把它看成是通用類的包。
地址
pubKeyAddress, err := btcutil.NewAddressPubKey(pubKeySerial, &chaincfg.MainNetParams)
和私密金鑰的WIF類似,公開金鑰可以通過一些演算法來計算出其地址,詳情需要參考《精通比特幣》的講解。
如何從公開金鑰產生比特幣地址
就這樣,一個符合規則的比特幣地址以及私密金鑰就這樣產生出來了,可以在https://btc.com上檢查地址格式是否正確。