理解以太坊的橢圓曲線簽名-校驗簽名

原  理

以太坊數字簽名和比特幣的關係git

以太坊數字簽名,幾乎徹底沿用了比特幣的數字簽名算法ECDSA-secp256k1。只有哈希的生成方式不同,這個以後會說。ECDSA-secp256k1是一種非對稱加密算法。github

什麼是ECDSA算法

以太坊數字簽名算法使用的是橢圓曲線數字簽名算法,英文簡稱ECDSA。其中EC是「橢圓曲線」的簡稱,DSA是「數字簽名算法」的簡稱。安全

什麼是secp256k1網絡

橢圓曲線算法簡單的說就是用X和Y座標畫一個曲線。這個曲線怎麼畫,須要不少個參數來肯定。以太坊使用了一套叫secp256k1的參數肯定了橢圓的形狀。因此,以太坊的簽名算法全稱就是是ECDSA-secp256k1。app

什麼是非對稱加密區塊鏈

什麼是對稱加密,什麼是非對稱加密呢?簡單的說,只有一個密鑰的,就是對稱加密,加密解密用它。有兩個密鑰的,就是非對稱加密,加密用一個密鑰,解密用另一個。相對於對稱加密算法而言,非對稱加密優勢是不須要在網絡上暴露加密的密鑰,從機制上來講更安全;缺點是加密效率比對稱加密低不少。因此非對稱加密通常只用於諸如數字簽名這類數據量較小的加密運算。ui

常見的非對稱加密算法除了橢圓加密算法以外,還有著名的RSA。橢圓加密相比RSA的區別是:編碼

  • 橢圓加密的密鑰更短加密

  • 橢圓加密計算更快而安全性至關

  • RSA的私鑰和公鑰是何以互換加解密的,但橢圓加密只能私鑰加密公鑰解密。

私鑰

以太坊的私鑰是一個32字節的數,取值範圍從1~0xFFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFE BAAE DCE6 AF48 A03B BFD2 5E8C D036 4140。這個數能夠由僞隨機算法(PRNG)產生。其實0也是一個合法的私鑰,只不過這是一個特殊私鑰,以太坊的創世區塊就是這個私鑰生成的。

公鑰

以太坊的非壓縮公鑰是一個65字節的數,這個是繼承至比特幣的。但以太坊只使用了其中64個字節,有一個字節這64個字節中,32字節表示橢圓曲線的X座標,32字節表示橢圓曲線的Y座標。這個XY座標是私鑰經過ECDSA-secp256k1推導出來的。因此說,橢圓曲線算法的公鑰是經過私鑰計算出來的。而反過來,用公鑰推導私鑰,以現有計算機的計算幾乎是不可能的,這也是以太坊和比特幣存在的基礎。若是哪天計算機技術出現大飛躍,好比量子計算機普及,現有鏈上全部帳戶的私鑰都會曝光。固然,區塊鏈技術自己也會必定會持續演進的。

哈希

哈希,也能夠形象的叫作「摘要」。就是不管消息有多大,均可以生成一個固定長度的「摘要」,這個「摘要」能夠用來校驗消息是否被篡改。只要消息被修改了一個字節,「摘要」的校驗就會失敗。

比特幣的哈希算法使用的是SHA2-256。相對於SHA1,SHA2只是擴展了哈希的字節數而已。目前SHA1已經被攻破,SHA2被攻破只是時間問題。

以太坊的哈希算法採用的是全新的SHA3-256。和SHA1,SHA2不同,SHA3並非單純擴展字節數,而是採用了新的Keccak算法。一樣字節寬度的SHA3比SHA2更安全。

地址

以太坊的地址是公鑰通過一系列哈希和變換,在經由Base58編碼生成的字符串。過程不述。Base58編碼和Base64差很少,都是使用「」可讀符號「來表示二進制數據,Base58相對Base64移除了一些容易產生視覺混淆的字母和數字。

簽名

簽名其實就是用私鑰對消息的哈希進行加密。當一個以太坊節點向另外一個節點發送消息時,會用本身的私鑰將消息的哈希作簽名,而後吧簽名和消息自己發送給對方。

過程如圖:

image

校驗簽名

節點收到對方發來的消息和簽名後,會先作一個「recover」的動做,用消息和簽名推導出對方的公鑰。再經過公鑰,簽名,消息的哈希值計算出一個叫「r」的值,這個r是簽名的一部分,校驗簽名就是拿計算出來的r和簽名中攜帶的r經行對比,若是一致就校驗經過。

過程如圖:

image

2

代碼實現

以太坊項目geth有兩套ECDSA-secp256p1的實現。一套是純go的,一套是基於C庫的。底層算法都不是以太坊開發人員寫的,採用的是開源世界的拿來主義。

go實現

接口源碼在crypto/signature_nocgo.go。這個文件只是一個wrapper,真實的實現調用了一個第三方的比特幣的go項目,源碼在vendor//github.com/bitcsuite/bitcd。

 

https://my.oschina.net/u/3782027/blog/1799425

 

API及其功能

signature_nocgo.go和signature_cgo.go的接口是同樣的,具體以下:

//經過消息的哈希和簽名恢復公鑰 func Ecrecover(hash, sig []byte) ([]byte, error) {} //經過哈希和私鑰計算ECDSA簽名 func Sign(hash []byte, prv *ecdsa.PrivateKey) {} //經過公鑰,哈希校驗簽名 func VerifySignature(pubkey, hash, signature []byte) bool {} //將33字節的公鑰解壓成65字節公鑰 func DecompressPubkey(pubkey []byte) (*ecdsa.PublicKey, error) {} //將65字節非壓縮公鑰壓縮稱33字節壓縮公鑰 func CompressPubkey(pubkey *ecdsa.PublicKey) {} 
做者:大洋一輩子 連接:https://www.jianshu.com/p/d622e1ec9470 來源:簡書 簡書著做權歸做者全部,任何形式的轉載都請聯繫做者得到受權並註明出處。
相關文章
相關標籤/搜索