以太坊系列之三: 以太坊的crypto模塊--以太坊源碼學習

以太坊的crypto模塊

該模塊分爲兩個部分一個是實現sha3,一個是實現secp256k1(這也是比特幣中使用的簽名算法). 須要說明的是secp256k1有兩種實現方式,一種是依賴libsecp256k1,須要cgo,另一種是依賴github.com/btcsuite/btcd,這是一個使用go語言實現的比特幣的客戶端.git

sha3模塊

這個模塊實際上能夠認爲就是一個功能計算sha3-256,用法也很簡單,就是調用crypto中的Keccak256,輸出是一個32字節的hash結果github

hash := crypto.Keccak256Hash([]byte("hello"))
//hash值:4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45

secp256k1模塊

這個模塊比較複雜,若是要細度源碼,須要對密碼學有比較深刻的理解,可是使用起來其實比較簡單.
主要就是簽名,驗證,以及公鑰與以太坊地址轉換算法

1.簽名

secp256k1的私鑰地址長度是32字節256位,公鑰地址長度是65字節,而以太坊的地址長度是20字節,ui

//簽名
var testPrivHex = "289c2857d4598e37fb9647507e47a309d6133539bf21a8b9cb6df88fd5232032"
//1.獲取私鑰
key, _ := crypto.HexToECDSA(testPrivHex)
//2.對message進行hash
msg := crypto.Keccak256([]byte("foo"))
//3.對hash進行簽名,注意簽名對象只能是hash,而且長度真是32個字節的hash
sig, err := crypto.Sign(msg, key)
//sig:d155e94305af7e07dd8c32873e5c03cb95c9e05960ef85be9c07f671da58c73718c19adc397a211aa9e87e519e2038c5a3b658618db335f74f800b8e0cfeef4401
//簽名結果長度和公鑰長度相同

2.驗證

驗證簽名是否正確,須要公鑰,hash(對message進行hash的結果),以及簽名. 這裏面真正校驗的是第三步,也就是公鑰是否和個人相同,而不像普通工RSA簽名驗證同樣.固然咱們能夠封裝成和RSA簽名驗證同樣形式的func VerifySignature(pubKey,msg,sig []byte) errorcode

//1.從簽名中提取公鑰
recoveredPub, err := crypto.Ecrecover(msg, sig)
//2.將公鑰轉換爲長度爲65的字節序列
recoveredPubBytes:=crypto.FromECDSAPub(recoveredPub)
//3.校驗這個公鑰是否和個人公鑰一致
if recoveredPubBytes!=myPubKey {
    ......
}

3.公鑰與地址的轉換

以太坊中並無直接拿公鑰當作帳戶地址,而是進行了一個簡單的轉換,具體來講就是hash(公鑰)的後20位,這裏的hash算法是sha3-256,能夠用一行代碼來表示對象

crypto.Keccak256(pubKey)[12:]

詳細的代碼在crypto.go中,get

func PubkeyToAddress(p ecdsa.PublicKey) common.Address {
    pubBytes := FromECDSAPub(&p) //將pubkey轉換爲字節序列
    return common.BytesToAddress(Keccak256(pubBytes[1:])[12:]) //對字節序列進行hash並去後二十個字節,BytesToAddress實際上就是[32]byte
}
相關文章
相關標籤/搜索