1. 程式人生 > >理解以太坊的橢圓曲線簽名-校驗簽名

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

原  理

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

以太坊數字簽名,幾乎完全沿用了比特幣的數字簽名演算法ECDSA-secp256k1。只有雜湊的生成方式不一樣,這個之後會說。ECDSA-secp256k1是一種非對稱加密演算法。

什麼是ECDSA

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

什麼是secp256k1

橢圓曲線演算法簡單的說就是用X和Y座標畫一個曲線。這個曲線怎麼畫,需要很多個引數來確定。以太坊使用了一套叫secp256k1的引數確定了橢圓的形狀。所以,以太坊的簽名演算法全稱就是是ECDSA-secp256k1。

什麼是非對稱加密

什麼是對稱加密,什麼是非對稱加密呢?簡單的說,只有一個金鑰的,就是對稱加密,加密解密用它。有兩個金鑰的,就是非對稱加密,加密用一個金鑰,解密用另外一個。相對於對稱加密演算法而言,非對稱加密優點是不需要在網路上暴露加密的金鑰,從機制上來說更安全;缺點是加密效率比對稱加密低很多。所以非對稱加密一般只用於諸如數字簽名這類資料量較小的加密運算。

常見的非對稱加密演算法除了橢圓加密演算法之外,還有著名的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
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。