《精通以太坊》-密鑰,地址

原文:Keys, Addresses

以太坊的基礎(chǔ)技術(shù)之一是密碼學(xué),這是數(shù)學(xué)的一個分支,廣泛用于計算機安全。密碼學(xué)在希臘語中意為“秘密寫作”,但密碼學(xué)的科學(xué)不僅包括秘密寫作,也稱為加密。密碼學(xué)也可用于證明秘密知識而不泄露秘密(數(shù)字簽名),或證明數(shù)據(jù)的真實性(數(shù)字指紋)。這些類型的加密證明是對以太坊和大多數(shù)區(qū)塊鏈系統(tǒng)至關(guān)重要的數(shù)學(xué)工具,廣泛用于以太坊應(yīng)用程序。具有諷刺意味的是,加密并不是以太坊的重要組成部分,因為它的通信和交易數(shù)據(jù)沒有加密,也不需要加密來保護系統(tǒng)。在本章中,我們將介紹以太坊中用于控制資金所有權(quán)的一些密碼學(xué)技術(shù)。

介紹

以太坊有兩種不同類型的賬戶,可以擁有和控制以太:外部賬戶(EOA)和合約。在本節(jié)中,我們將研究密碼學(xué)的使用,以通過外部擁有的帳戶(即私鑰)建立以太的所有權(quán)。

EOA中以太的所有權(quán)是通過數(shù)字密鑰,以太坊地址和數(shù)字簽名建立的。數(shù)字密鑰實際上不存儲在區(qū)塊鏈中或不在以太坊網(wǎng)絡(luò)上傳輸,而是由用戶在文件或稱為錢包的簡單數(shù)據(jù)庫中創(chuàng)建和存儲。用戶錢包中的數(shù)字密鑰完全獨立于以太坊協(xié)議,并且可以由用戶的錢包軟件生成和管理,而無需參考區(qū)塊鏈或訪問互聯(lián)網(wǎng)。數(shù)字密鑰可以實現(xiàn)以太坊的許多有趣屬性,包括去中心化的信任和控制以及所有權(quán)證明。

以太坊交易要求有效的數(shù)字簽名包含在區(qū)塊鏈中,只能用密鑰生成; 因此,任何擁有該密鑰副本的人都可以控制以太。以太坊交易中的數(shù)字簽名證明了資金的真正所有者。

數(shù)字密鑰成對出現(xiàn),包括私有(秘密)密鑰和公鑰??梢詫⒐€視為與銀行帳號相似,私鑰與密碼PIN類似,可提供對帳戶的控制。這些數(shù)字密鑰很少被以太坊的用戶看到。在大多數(shù)情況下,它們存儲在錢包文件中并由以太坊錢包軟件管理。

在以太坊交易的支付部分中,預(yù)期接收者由以太坊地址表示,該地址以與支票上的受益人姓名相同的方式使用(即,“支付給訂單”)。在大多數(shù)情況下,以太坊地址是從公鑰生成的并且對應(yīng)于公鑰。但是,并非所有以太坊地址都代表公鑰; 他們也可以代表合約,我們將在[合約]中看到。以太坊地址是用戶經(jīng)常看到的密鑰的唯一表示,因為這是他們需要與世界共享的部分。

首先,我們將介紹密碼學(xué)并解釋以太坊中使用的數(shù)學(xué)。接下來,我們將了解如何生成、存儲和管理密鑰。最后,我們將回顧用于表示私鑰和公鑰以及地址的各種編碼格式。

公鑰加密和加密貨幣

公鑰加密是現(xiàn)代信息安全的核心概念。1970年代由Martin Hellman,Whitfield Diffie和Ralph Merkle首次公開發(fā)明,這是一個巨大的突破,引發(fā)了第一次公眾關(guān)注的密碼學(xué)領(lǐng)域。在70年代之前,強大的密碼學(xué)知識在政府的控制下進行,幾乎沒有公共研究,直到公開密鑰學(xué)研究的公開發(fā)表。

公鑰加密使用用于保護信息的唯一密鑰。這些唯一密鑰基于具有獨特屬性的數(shù)學(xué)函數(shù):它們易于在一個方向上計算,但很難在反方向上計算?;谶@些數(shù)學(xué)函數(shù),密碼學(xué)能夠創(chuàng)建數(shù)字密鑰和不可偽造的數(shù)字簽名,這些簽名受到數(shù)學(xué)定律的保護。

例如,將兩個大質(zhì)數(shù)相乘是微不足道的。但考慮到兩個大素數(shù)的乘積,很難找到素因子(一個稱為素數(shù)因子分解的問題)。假設(shè)我出現(xiàn)了數(shù)字6895601,并告訴你它是兩個素數(shù)的乘積。找到這兩個素數(shù)要比將它們乘以產(chǎn)生6895601要困難得多。

如果你知道一些秘密信息,這些數(shù)學(xué)函數(shù)中的一些可以很容易地反轉(zhuǎn)。在上面的例子中,如果我告訴你其中一個主要因素是1931,你可以通過簡單的除法輕松找到另一個:6895601/1931 = 3571.這些函數(shù)被稱為trapdoor函數(shù),因為給出了一條秘密信息,你可以采取一種快捷方式,使得反轉(zhuǎn)功能變得微不足道。

在密碼學(xué)中有用的另一類數(shù)學(xué)函數(shù)基于橢圓曲線上的算術(shù)運算。在橢圓曲線算術(shù)中,乘以modulo的素數(shù)很簡單,但除法是不可能的(稱為離散對數(shù)問題)。橢圓曲線密碼術(shù)廣泛用于現(xiàn)代計算機系統(tǒng)中,是以太坊(和其他加密貨幣)數(shù)字密鑰和數(shù)字簽名的基礎(chǔ)。

閱讀有關(guān)密碼學(xué)和現(xiàn)代密碼學(xué)中使用的數(shù)學(xué)函數(shù)的更多信息:

在以太坊中,我們使用公鑰加密來創(chuàng)建一個控制ether訪問并允許我們對合約進行身份驗證的密鑰對。密鑰對由私鑰、唯一公鑰組成,并且被認為是“pair”,因為公鑰是從私鑰導(dǎo)出的。公鑰用于接收資金,私鑰用于創(chuàng)建數(shù)字簽名以簽署交易來花費資金。數(shù)字簽名也用于驗證合約的所有者或用戶,我們將在[contract_authentication]中看到。

公鑰和私鑰之間存在數(shù)學(xué)關(guān)系,允許私鑰用于在消息上生成簽名。可以在不泄露私鑰的情況下針對公鑰驗證此簽名。

在花費以太時,當(dāng)前所有者在交易中呈現(xiàn)她的公鑰和簽名(每次不同,但是從同一私鑰創(chuàng)建)。通過公鑰和簽名的呈現(xiàn),以太坊系統(tǒng)中的每個人都可以獨立有效地驗證和接受交易,確認交易以太的人在轉(zhuǎn)移時擁有它們。

Tip 在大多數(shù)錢包實現(xiàn)中,為方便起見,私鑰和公鑰一起存儲為密鑰對。但是,可以從私鑰簡單地計算公鑰,因此也可以僅存儲私鑰。

為什么使用非對稱加密技術(shù)(公鑰/私鑰)?
為什么以太坊使用非對稱加密?它不習(xí)慣“加密”(秘密)交易。相反,非對稱加密的有用特性是生成數(shù)字簽名的能力??梢詫⑺借€應(yīng)用于交易的數(shù)字指紋以產(chǎn)生數(shù)字簽名。此簽名只能由具有私鑰的人員生成。但是,任何有權(quán)訪問公鑰和交易指紋的人都可以使用它們來驗證簽名。非對稱加密的這種有用屬性使任何人都可以驗證每個交易上的每個簽名,同時確保只有私鑰的所有者才能生成有效的簽名。

私鑰

私鑰只是一個隨機挑選的數(shù)字。對私鑰的所有權(quán)和控制權(quán)是用戶控制與相應(yīng)的以太坊地址相關(guān)聯(lián)的所有資金的根源,以及對授權(quán)該地址的合約的訪問權(quán)。私鑰用于通過證明交易中使用的資金所有權(quán)來創(chuàng)建需要花費以太的簽名。私鑰必須始終保密,因為向第三方披露私鑰等同于讓他們控制以太和由該密鑰保護的合約。還必須備份私鑰并防止意外丟失。如果它丟失了,它就無法恢復(fù),而它所保證的資金也會永遠丟失。

Tip 以太坊私鑰只是一個數(shù)字。您可以使用硬幣、鉛筆和紙張隨機選擇您的私鑰:擲硬幣256次,您可以在以太坊錢包中使用隨機私鑰的二進制數(shù)字。然后可以從私鑰生成公鑰和地址。

從隨機數(shù)生成私鑰

生成密鑰的第一步也是最重要的一步是找到安全的熵源或隨機性。創(chuàng)建以太坊私鑰與“選擇1到2^{256}之間的數(shù)字”基本相同。用于選擇該數(shù)字的確切方法無關(guān)緊要,只要它不可預(yù)測或不可重復(fù)即可。以太坊軟件使用底層操作系統(tǒng)的隨機數(shù)生成器產(chǎn)生256位熵(隨機性)。通常,OS隨機數(shù)生成器由人類隨機源初始化,這就是為什么可能會要求您將鼠標(biāo)擺動幾秒鐘,或者按鍵盤上的隨機鍵。

更準(zhǔn)確地說,可能的私鑰范圍略小于2^{256}。私鑰可以是1到n-1之間的任何數(shù)字,其中n是常數(shù)(n = 1.158*10^{77},略小于2^{256}),定義為以太坊中使用的橢圓曲線的順序(參見[橢圓曲線加密解釋])。為了創(chuàng)建這樣一個密鑰,我們隨機選擇一個256位的數(shù)字并檢查它是否小于n-1.在編程術(shù)語中,這通常是通過從密碼安全的隨機源收集的更大的隨機bits來實現(xiàn)的。轉(zhuǎn)換為256位哈希算法,如Keccak-256或SHA256(參見[cryptographic_hash_algorithm]),這將方便地產(chǎn)生256位數(shù)字。如果結(jié)果小于n - 1,我們有一個合適的私鑰。否則,我們只需再次嘗試獲取另一個隨機數(shù)。

Warning 不要編寫自己的代碼來創(chuàng)建隨機數(shù)或使用編程語言提供的“簡單”隨機數(shù)生成器。使用加密安全的偽隨機數(shù)生成器(CSPRNG)和來自足夠熵源的種子。研究您選擇的隨機數(shù)生成器庫的文檔,以確保它是加密安全的。正確實施CSPRNG對密鑰的安全性至關(guān)重要。

以下是以十六進制格式顯示的隨機生成的私鑰(k)(256位顯示為64個十六進制數(shù)字,每個4位):

f8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315
Tip 以太坊私鑰空間的大?。?img class="math-inline" src="https://math.jianshu.com/math?formula=2%5E%7B256%7D" alt="2^{256}" mathimg="1">)是一個不可思議的大數(shù)字。十進制約為10^{77}。為了比較,可見宇宙估計包含10^{80}個原子。

公鑰

以太坊公鑰是橢圓曲線上的一個點,這意味著它是一組滿足橢圓曲線方程的X和Y坐標(biāo)。

簡單來說,以太坊公鑰是兩個連接在一起的數(shù)字。這些數(shù)字是通過只能單向計算的私鑰生成的。這意味著如果您擁有私鑰,那么計算公鑰是微不足道的。但是您無法從公鑰計算私鑰。

MATH即將發(fā)生!不要驚慌。如果您發(fā)現(xiàn)很難閱讀上一段,則可以跳過接下來的幾節(jié)。有許多工具和庫可供您進行數(shù)學(xué)計算。

使用橢圓曲線乘法從私鑰計算公鑰,這是不可逆的:K = k * G,其中k是私鑰,G是稱為生成點的常數(shù)點,K是結(jié)果公鑰。反向操作,稱為“找到離散對數(shù)” - 計算k,如果你知道K - 就像嘗試所有可能的k值一樣困難,即暴力搜索。

簡而言之:橢圓曲線上的算術(shù)不同于“常規(guī)”整數(shù)算術(shù)。點(G)可以乘以整數(shù)(k)以產(chǎn)生另一個點(K)。但是沒有除法之類的東西,因此不可能簡單地將公鑰K“除”點G來計算私鑰k。這是公鑰加密和加密貨幣中描述的單向數(shù)學(xué)函數(shù)。

Tip 橢圓曲線乘法是密碼學(xué)家稱之為“單向”函數(shù)的一種函數(shù):它很容易在一個方向上進行(乘法)而在反向(分割)中是不可能的。私鑰的所有者可以輕松地創(chuàng)建公鑰,然后與世界共享它,知道沒有人可以反轉(zhuǎn)該功能并從公鑰計算私鑰。這種數(shù)學(xué)技巧成為不可偽造和安全的數(shù)字簽名的基礎(chǔ),證明了以太坊資金的所有權(quán)和合約的控制權(quán)。

在我們演示如何從私鑰生成公鑰之前,讓我們更詳細地看一下橢圓曲線加密。

橢圓曲線加密解釋

橢圓曲線加密是一種基于離散對數(shù)問題的非對稱或公鑰加密,如橢圓曲線的點上的加法和乘法所表示的。

橢圓曲線的可視化是橢圓曲線的一個例子,類似于以太坊使用的曲線。

Tip 以太坊使用與比特幣完全相同的橢圓曲線,稱為secp256k1。這使得重用比特幣的許多橢圓曲線庫和工具成為可能。
image

圖1.橢圓曲線的可視化

以太坊使用特定的橢圓曲線和一組數(shù)學(xué)常數(shù),如由國家標(biāo)準(zhǔn)與技術(shù)研究所(NIST)建立的名為secp256k1的標(biāo)準(zhǔn)中所定義。secp256k1曲線由以下函數(shù)定義,該函數(shù)生成橢圓曲線:
y^2 = (x^3 + 7) over (F_p)
或者
y^2 mod (p) = (x^3 + 7) mod (p)

所述mod p(mod 素數(shù)p)表明,該曲線是在素數(shù)階的有限域p,也寫為F_p,其中p = 2^{256} - 2^{32} - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1,一個非常大的素數(shù)。

因為此曲線是在素數(shù)階的有限域而不是實數(shù)上定義的,所以它看起來像是在兩個維度上散布的點圖案,這使得難以可視化。但是,數(shù)學(xué)與實數(shù)上的橢圓曲線相同。例如,橢圓曲線密碼學(xué):在F(p)上可視化橢圓曲線,p = 17,在素數(shù)階17的小得多的有限域上顯示相同的橢圓曲線,顯示網(wǎng)格上的點圖案。secp256k1以太坊橢圓曲線可以被認為是在一個不可思議的大網(wǎng)格上更復(fù)雜的點圖案。

image

圖2.橢圓曲線加密:在F(p)上可視化橢圓曲線,p = 17

因此,例如,以下是坐標(biāo)(x,y)的點Q,它是secp256k1曲線上的一個點:

Q =(49790390825249384486033144355916864607616083520101638681403973749255924539515,59574132161899900045862086493921015780032175291755807399284007721050341297360)

[使用Python確認這一點在橢圓曲線上]顯示了如何使用Python自己檢查。變量x和y是如上所述的點Q的坐標(biāo)。變量p是橢圓曲線的素數(shù)階(用于所有mod運算的素數(shù))。Python的最后一行是橢圓曲線方程(Python中的%運算符是mod運算符)。如果x和y確實是橢圓曲線上的點,那么它們滿足等式并且結(jié)果為零(0L是值為零的長整數(shù))。通過在命令行上鍵入python并從列表中復(fù)制每一行(在提示>>>之后)自己嘗試:

示例1.使用Python確認此點位于橢圓曲線上

Python 3.4.0 (default, Mar 30 2014, 19:23:13)
[GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.38)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> p = 115792089237316195423570985008687907853269984665640564039457584007908834671663
>>> x = 49790390825249384486033144355916864607616083520101638681403973749255924539515
>>> y = 59574132161899900045862086493921015780032175291755807399284007721050341297360
>>> (x ** 3 + 7 - y**2) % p
0L

橢圓曲線算術(shù)運算

很多橢圓曲線的數(shù)學(xué)看起來非常像我們在學(xué)校學(xué)到的整數(shù)運算。具體來說,我們可以定義一個加法運算符,而不是添加數(shù)字就是在曲線上添加點。一旦我們有了加法運算符,我們還可以定義一個點和一個整數(shù)的乘法,這樣它就相當(dāng)于多重加法

定義加法使得在橢圓曲線上給定兩個點P_1P_2,在橢圓曲線上也存在第三點P_3 = P_1 + P_2。

幾何上,通過在P_1P_2之間畫線來計算該第三點P_3。該線將在一個額外的位置與橢圓曲線相交。稱此點為P_3'= (x,y)。然后在x軸上反射得到P_3 = (x,-y)。

在橢圓曲線數(shù)學(xué)中,有一個稱為“無限遠點”的點,它大致對應(yīng)于數(shù)字零的作用。在計算機上,它有時用x = y = 0表示(它不滿足橢圓曲線方程,但它是一個可以檢查的簡單的獨立案例)。有幾個特殊情況可以解釋“無限遠點”的必要性。

如果P_1P_2是相同的點,則“P_1P_2之間的線” 應(yīng)該延伸到該點P_1處曲線上的切線。該切線將恰好與一個新點相交。您可以使用微積分來確定切線的斜率。這些技術(shù)奇怪地起作用,即使我們用兩個整數(shù)坐標(biāo)來限制我們對曲線上的點的興趣!

在某些情況下(即,如果P_1P_2具有相同的x值但y值不同),則切線將完全垂直,在這種情況下,P_3 =“無限遠點”。

如果P_1是“無限遠點”,那么P_1 + P_2 = P_2。類似地,如果P_2是無窮遠處的點,那么P_1 + P_2 = P_1。這顯示了無限遠處的點如何扮演零在“正?!彼阈g(shù)中扮演的角色。

事實證明,+是關(guān)聯(lián)的,這意味著(A + B)+ C = A +(B + C)。這意味著我們可以在沒有括號的情況下編寫A + B + C而且沒有歧義。

現(xiàn)在我們已經(jīng)定義了加法,我們可以用擴展加法的標(biāo)準(zhǔn)方式定義乘法。對于橢圓曲線上的點P,如果k是整數(shù),則k * P = P + P + P + ... + P(k次)。注意,在這種情況下,k有時會被混淆地稱為“指數(shù)”

生成公鑰

以一個隨機生成的數(shù)字k形式的私鑰開始,我們用曲線上的一個預(yù)定點G乘以它,得到曲線上的另一個點,也就是對應(yīng)的公鑰K。生成器點被指定為secp256k1標(biāo)準(zhǔn)的一部分,對于secp256k1的所有實現(xiàn)和從該曲線導(dǎo)出的所有密鑰都使用相同的點G:

K = k * G

其中k是私鑰,G是生成器點,K是結(jié)果公鑰,即曲線上的一個點。因為生成器點總是同一Ethereum所有用戶私鑰k乘以G,總是會導(dǎo)致相同的公鑰k。k和K之間的關(guān)系是固定的,但只能在一個方向上進行計算,從k到K。這就是為什么以太坊地址(從K派生)可以與任何人共享并且不會泄露用戶的私鑰(k)。

正如我們在橢圓曲線算術(shù)運算中所描述的,k * G的乘法等價于重復(fù)的加法,所以G + G + G +…+ G,重復(fù)k次??傊獜乃借€k中生成公鑰K,我們將生成器點G加上它自己,K次。

Tip 可以將私鑰轉(zhuǎn)換為公鑰,但不能將公鑰轉(zhuǎn)換為私鑰,因為計算方法只有一種。

讓我們應(yīng)用此計算來查找我們在私鑰中顯示的特定私鑰的公鑰:

示例公鑰計算的私鑰

K = f8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315 * G

加密庫可以幫助我們使用橢圓曲線乘法計算K。生成的公鑰K定義為點K =(x,y):

示例公鑰由示例私鑰計算

K = (x, y)

where,

x = 6e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b
y = 83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0

在以太坊中,您可能會看到公鑰表示為66個十六進制字符(33個字節(jié))的十六進制序列化。這是從高效密碼學(xué)標(biāo)準(zhǔn)行業(yè)協(xié)會(SECG)提出的標(biāo)準(zhǔn)序列化格式中采用的,在高效密碼學(xué)標(biāo)準(zhǔn)(SEC1)中有記錄。該標(biāo)準(zhǔn)定義了四個可用的前綴,可用于識別橢圓曲線上的點:

前綴 含義 長度(前綴的字節(jié)數(shù))
0x00 無窮點 1
0×04 未壓縮點 65
0x02 偶數(shù)Y的壓縮點 33
0x03 奇數(shù)Y的壓縮點 33

以太坊僅使用未壓縮的公鑰,因此唯一相關(guān)的前綴是(十六進制)04。序列化連接公鑰的X和Y坐標(biāo):

04 + X-coordinate (32 bytes/64 hex) + Y coordinate (32 bytes/64 hex)

因此,我們在[示例公鑰由示例私鑰計算]中計算的公鑰被序列化為:

046e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0

橢圓曲線庫

在加密貨幣相關(guān)項目中使用了幾個secp256k1橢圓曲線的實現(xiàn):

OpenSSL

OpenSSL庫提供了一套全面的加密組件,包括secp256k1的完整實現(xiàn)。例如,為了導(dǎo)出公鑰,可以使用函數(shù)EC_POINT_mul()。在https://www.openssl.org/上找到它

libsecp256k1

Bitcoin Core的libsecp256k1是secp256k1橢圓曲線和其他加密組件的C語言實現(xiàn)。橢圓曲線加密的libsecp256是從頭開始編寫的,用Bitcoin Core軟件取代OpenSSL,在性能和安全性方面都被認為是優(yōu)越的。在以下網(wǎng)址找到它:

https://github.com/bitcoin-core/secp256k1

加密哈希函數(shù)

在以太坊中使用加密哈希函數(shù)。實際上,哈希函數(shù)在幾乎所有的加密系統(tǒng)中都被廣泛使用,這是由密碼學(xué)家Bruce Schneier得出的事實,他說“不僅僅是加密算法,單向哈希函數(shù)是現(xiàn)代密碼學(xué)的主力”。

在本節(jié)中,我們將討論哈希函數(shù),理解它們的基本屬性以及這些屬性如何使它們在現(xiàn)代密碼學(xué)的許多領(lǐng)域中如此有用。我們在這里解釋哈希函數(shù),因為它們是將以太網(wǎng)公鑰轉(zhuǎn)換為地址的一部分。

簡單來說,“哈希函數(shù)是可用于將任意大小的數(shù)據(jù)映射到固定大小的數(shù)據(jù)的任何函數(shù)?!?資料來源:維基百科。哈希函數(shù)的輸入稱為pre-image或message。輸出稱為hash或digest。哈希函數(shù)的一個特殊子類是加密哈希函數(shù),它具有對加密有用的特定屬性。

加密哈希函數(shù)是單向哈希函數(shù),它將任意大小的數(shù)據(jù)映射到固定大小的字節(jié)字符串,如果知道輸出,則重新創(chuàng)建輸入在計算上是不可行的。確定輸入的唯一方法是對可能的輸入進行暴力搜索,檢查匹配的輸出。

加密哈希函數(shù)有五個主要屬性(來源:維基百科/加密哈希函數(shù)):

確定性

任何輸入message始終生成相同的哈希摘要。

可驗證

計算message的hash是有效的(線性性能)。

不相關(guān)

對message的一個小更改(例如,一個字節(jié)更改)應(yīng)該對哈希輸出進行很大的更改,以至于它不能與原始message的哈希相關(guān)聯(lián)。

不可逆性(第一原像阻力)

從哈希計算message是不可行的,相當(dāng)于通過可能的message進行暴力搜索。

碰撞保護(第二原像阻力)

計算產(chǎn)生相同哈希輸出的兩個不同message應(yīng)該是不可行的。

第二原像阻力,對于防止在以太的數(shù)字簽名偽造是很重要的。

這些屬性的組合使得加密哈希函數(shù)對廣泛的安全應(yīng)用程序有用,包括:

  • 數(shù)據(jù)指紋識別
  • 消息完整性(錯誤檢測)
  • 驗證的工作
  • 身份驗證(密碼哈希和密鑰擴展)
  • 偽隨機數(shù)發(fā)生器
  • 原像承諾(Pre-image commitment)
  • 唯一標(biāo)識符

隨著我們在系統(tǒng)的各個層面上進展,我們將在以太坊中找到許多這些。

以太坊的加密哈希函數(shù) - Keccak-256

以太坊在許多地方使用Keccak-256加密哈希函數(shù)。Keccak-256被設(shè)計為2007年由國家科學(xué)技術(shù)研究所(NIST)舉辦的SHA-3密碼哈希函數(shù)競賽的候選人。Keccak是獲勝的算法,在2015年被標(biāo)準(zhǔn)化為聯(lián)邦信息處理標(biāo)準(zhǔn)(FIPS)202。

然而,在以太坊開發(fā)期間,NIST標(biāo)準(zhǔn)化正在最終確定。NIST在標(biāo)準(zhǔn)流程完成后調(diào)整了Keccak的一些參數(shù),據(jù)稱是為了提高其效率。這是在英雄告密者愛德華·斯諾登透露文件的同時發(fā)生的,這些文件暗示NIST可能受到國家安全局的不當(dāng)影響,故意削弱Dual_EC_DRBG隨機數(shù)發(fā)生器標(biāo)準(zhǔn),有效地在標(biāo)準(zhǔn)隨機數(shù)發(fā)生器中放置后門。這一爭議的結(jié)果是對提議的變更的強烈抵制以及SHA-3標(biāo)準(zhǔn)化的顯著延遲。當(dāng)時,以太坊基金會決定實施其發(fā)明人提出的原始Keccak算法,

Warning 雖然您可能會在以太坊文檔和代碼中看到“SHA3”,但很多(如果不是全部)實例實際上都是指Keccak-256,而不是最終的FIPS-202 SHA-3標(biāo)準(zhǔn)。實現(xiàn)差異很小,與填充參數(shù)有關(guān),但它們的重要性在于Keccak-256在給定相同輸入的情況下產(chǎn)生與FIPS-202 SHA-3不同的哈希輸出。

由于以太坊(Keccak-256)中使用的哈希函數(shù)與最終標(biāo)準(zhǔn)(FIP-202 SHA-3)之間的差異所造成的混淆,現(xiàn)在正在努力將所有代碼、操作碼和庫中的sha3實例重命名為keccak256。有關(guān)詳細信息,請參閱ERC-59。

我使用了哪個哈希函數(shù)?

如果兩者都被稱為“SHA3”,你怎么知道你使用的代碼庫是FIPS-202 SHA-3還是Keccak-256?

一種簡單的方法是使用測試向量,即給定輸入的預(yù)期輸出。最常用于哈希函數(shù)的測試是空輸入。如果您使用空字符串作為輸入運行哈希函數(shù),您應(yīng)該看到以下結(jié)果:

測試您使用的SHA3庫是否為FIP-202 SHA-3的Keccak-256

Keccak256("")=
c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470

SHA3??("")=
a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a

因此,無論調(diào)用什么函數(shù),您都可以通過運行上面的簡單測試來測試它是否是原始的Keccak-256,或最終的NIST標(biāo)準(zhǔn)FIPS-202 SHA-3。請記住,以太坊使用Keccak-256,即使它在代碼中通常稱為SHA-3。

接下來,讓我們來看看以太坊中Keccak-256的第一個應(yīng)用,即從公鑰生成以太坊地址。

以太坊地址

以太坊地址是使用單向哈希函數(shù)(特別是Keccak-256)從公鑰或合約派生的唯一標(biāo)識符。
在前面的示例中,我們從私鑰開始,并使用橢圓曲線乘法來派生公鑰:

私鑰k:

k = f8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315

公鑰K(X和Y坐標(biāo)連接并顯示為十六進制):

K = 6e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0
Warning 值得注意的是,在計算地址時,公鑰未使用前綴(十六進制)04格式化。

我們使用Keccak-256來計算這個公鑰的哈希值:

Keccak256(K)= 2a5bc342ed616b5ba5732269001d3f1ef827552ae1114027bd3ecf1f086ba0f9

然后我們只保留最后20個字節(jié)(big-endian中最不重要的字節(jié)),這是我們的以太坊地址:

001d3f1ef827552ae1114027bd3ecf1f086ba0f9

大多數(shù)情況下,您會看到前綴為“0x”的以太坊地址,表示它是十六進制編碼,如下所示:

0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9

以太坊地址格式

以太坊地址是十六進制數(shù),是從公鑰的Keccak-256哈希的最后20個字節(jié)派生的標(biāo)識符。

與在所有客戶端的用戶界面中編碼的比特幣地址不同,包括內(nèi)置校驗和以防止輸入錯誤的地址,以太網(wǎng)地址以原始十六進制形式呈現(xiàn),沒有任何校驗和。

該決定背后的理由是,以太坊地址最終會隱藏在系統(tǒng)較高層的抽象(例如名稱服務(wù))之后,并且必要時應(yīng)在更高層添加校驗和。

回想起來,這種設(shè)計選擇會導(dǎo)致許多問題,包括由于輸入錯誤的地址和輸入驗證錯誤導(dǎo)致的資金損失。以太坊名稱服務(wù)的開發(fā)速度比最初預(yù)期慢,錢包開發(fā)人員采用ICAP等替代編碼非常緩慢。

國際交易客戶端地址協(xié)議(ICAP)

國際交易客戶端地址協(xié)議(ICAP)是一個以太坊的地址編碼,與國際銀行賬戶號碼(IBAN)編碼部分兼容,提供了一種通用的、可校驗和互操作的Ethereum地址編碼。ICAP地址可以編碼以太坊地址或通過以太坊名稱注冊表注冊的常用名稱。

閱讀以太坊Wiki上的ICAP:https://github.com/ethereum/wiki/wiki/ICAP:-Inter-exchange-Client-Address-Protocol

IBAN是識別銀行賬號的國際標(biāo)準(zhǔn),主要用于電匯。它在歐洲單一歐元支付區(qū)(SEPA)及其他地區(qū)被廣泛采用。IBAN是一種集中且嚴(yán)格監(jiān)管的服務(wù)。ICAP是以太坊地址的分散但兼容的實現(xiàn)。

IBAN由最多34個字母數(shù)字字符(不區(qū)分大小寫)字符串組成,其中包含國家/地區(qū)代碼,校驗和和銀行帳戶標(biāo)識符(特定于國家/地區(qū))。

ICAP通過引入代表“以太坊”的非標(biāo)準(zhǔn)國家代碼“XE”使用相同的結(jié)構(gòu),然后是兩個字符的校驗和以及帳戶標(biāo)識符的3種可能變體:

  • 直接:最多30個字母數(shù)字字符的big-endian base-36整數(shù),表示以太坊地址的最低有效位。因為此編碼小于155位,所以它僅適用于以一個或多個零字節(jié)開頭的以太坊地址。優(yōu)點是它在字段長度和校驗和方面與IBAN兼容。示例:XE60HAMICDXSV5QXVJA7TJW47Q9CHWKJD(33個字符長)
  • 基本:與“直接”編碼相同,但長度為31個字符。這允許它編碼任何以太坊地址,但使其與IBAN字段驗證不兼容。示例:XE18CHDJBPLTBCJ03FE9O2NS0BPOJVQCU2P(35個字符長)
  • 間接:對通過名稱注冊表提供程序解析為以太坊地址的標(biāo)識符進行編碼。使用16個字母數(shù)字字符,由資產(chǎn)標(biāo)識符(例如ETH),名稱服務(wù)(例如XREG)和9字符名稱(例如KITTYCATS)組成,這是一個人類可讀的名稱。示例:XE ## ETHXREGKITTYCATS(長度為20個字符),其中“##”應(yīng)替換為兩個計算的校驗和字符。

我們可以使用helpeth命令行工具來創(chuàng)建ICAP地址。讓我們嘗試使用我們的示例私鑰(前綴為0x并作為參數(shù)傳遞給helpeth):

$ helpeth keyDetails -p 0xf8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315

Address: 0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9
ICAP: XE60 HAMI CDXS V5QX VJA7 TJW4 7Q9C HWKJ D
Public key: 0x6e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0

helpeth命令為我們構(gòu)造十六進制以太坊地址和ICAP地址。我們的示例密鑰的ICAP地址是:

XE60HAMICDXSV5QXVJA7TJW47Q9CHWKJD

因為我們的示例以太坊地址恰好以零字節(jié)開始,所以可以使用在IBAN格式中有效的“直接”ICAP編碼方法對其進行編碼。你可以說,因為它長33個字符。

如果我們的地址不是以零開頭,則它將使用“基本”編碼進行編碼,該編碼長度為35個字符,并且作為IBAN格式無效。

Tip 任何以0字節(jié)開始的以太網(wǎng)絡(luò)地址的概率是1/256。要生成這樣一個密鑰,我們平均需要256次嘗試,使用256個不同的隨機私鑰,然后才能找到一個與IBAN兼容的“直接”編碼的ICAP地址。

目前,不幸的是,只有少數(shù)錢包支持ICAP。

大小寫校驗和的十六進制編碼(EIP-55)

由于ICAP或名稱服務(wù)的部署緩慢,因此提出了使用以太坊改進提案55(EIP-55)的新標(biāo)準(zhǔn)。您可以在以下位置閱讀詳細信息

https://github.com/Ethereum/EIPs/blob/master/EIPS/eip-55.md

EIP-55通過修改十六進制地址的大寫,為以太坊地址提供向后兼容的校驗和。這個想法是以太坊地址不區(qū)分大小寫,并且所有錢包都應(yīng)該接受以大寫或小寫字符表示的以太坊地址,而在解釋上沒有任何差別。

通過修改地址中字母字符的大小寫,我們可以傳達一個校驗和,可用于保護地址的完整性,防止輸入或讀取錯誤。不支持EIP-55校驗和的錢包忽略了地址包含混合大小寫的事實。但那些支持它的人可以驗證它并以99.986%的準(zhǔn)確率檢測錯誤。

混合大寫的編碼很微妙,一開始你可能不會注意到。我們的示例地址是:

0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9

使用EIP-55混合大小寫校驗和,它變?yōu)椋?/p>

0x001d3F1ef827552Ae1114027BD3ECF1f086bA0F9

你能分辨出來嗎?十六進制編碼字母表中的一些字母(AF)字符現(xiàn)在是大寫字母,而其他字母則是小寫字母。除非你仔細觀察,否則你甚至可能沒有注意到這種差異。

EIP-55實施起來非常簡單。我們采用小寫十六進制地址的Keccak-256哈希。此哈希充當(dāng)?shù)刂返臄?shù)字指紋,為我們提供方便的校驗和。輸入(地址)的任何微小變化都會導(dǎo)致產(chǎn)生的哈希(校驗和)發(fā)生巨大變化,從而使我們能夠有效地檢測錯誤。然后將地址的哈希值編碼為地址本身的大小寫。讓我們一步一步地分解它:

1.哈希小寫地址,不帶0x前綴:

Keccak256( “001d3f1ef827552ae1114027bd3ecf1f086ba0f9”)
23a69c1653e4ebbb619b0b2cb8a9bad49892a8b9695d9a19d8f673ca991deae1

2.如果哈希的相應(yīng)十六進制數(shù)字大于或等于0x8,則將每個字母地址字符大寫。如果我們排列地址和哈希,這更容易顯示:

地址:001d3f1ef827552ae1114027bd3ecf1f086ba0f9
哈希:23a69c1653e4ebbb619b0b2cb8a9bad49892a8b9 ......

我們的地址在第四個位置包含一個字母字符d。哈希的第四個字符是6,小于8.因此,我們保留d小寫。我們地址中的下一個字母字符是f,位于第六位。十六進制哈希的第六個字符是c,它大于8.因此,我們將地址中的F大寫,依此類推。如您所見,我們只使用散列的前20個字節(jié)(40個十六進制字符)作為校驗和,因為我們在地址中只有20個字節(jié)(40個十六進制字符)才能正確地大寫。

自己檢查生成的混合大小寫地址,看看是否可以分辨哪些字符大寫,以及它們在地址哈希中對應(yīng)的字符:

地址:001d3F1ef827552Ae1114027BD3ECF1f086bA0F9
哈希:23a69c1653e4ebbb619b0b2cb8a9bad49892a8b9 ......

檢測EIP-55編碼地址中的錯誤

現(xiàn)在,讓我們看看EIP-55地址將如何幫助我們找到錯誤。假設(shè)我們已經(jīng)打印出以太坊地址,這是EIP-55編碼的:

0x001d3F1ef827552Ae1114027BD3ECF1f086bA0F9

現(xiàn)在讓我們在閱讀該地址時犯一個基本錯誤。最后一個字符前面的字符是大寫字母“F”。對于這個例子,讓我們假設(shè)我們把它誤讀為大寫“E”。我們在錢包里輸入(錯誤的地址):

0x001d3F1ef827552Ae1114027BD3ECF1f086bA0E9

幸運的是,我們的錢包符合EIP-55標(biāo)準(zhǔn)!它注意到混合大寫并嘗試驗證地址。它將它轉(zhuǎn)換為小寫,并計算校驗和哈希:

Keccak256( “001d3f1ef827552ae1114027bd3ecf1f086ba0e9”)
5429b5d9460122fb4b11af9cb88b7bb76d8928862e0a57d46dd18dd8e08a6927

正如您所看到的,即使地址僅改變了一個字符(事實上,“e”和“f”之間只相差1位),地址的哈希也發(fā)生了根本改變。這是哈希函數(shù)的屬性,使它們對校驗和非常有用!

現(xiàn)在,讓我們排列并檢查大小寫:

001d3F1ef827552Ae1114027BD3ECF1f086bA0E9
5429b5d9460122fb4b11af9cb88b7bb76d892886 ...

這都錯了!幾個字母字符的大寫不正確。請記住,大小寫是正確校驗和的編碼。

我們輸入的地址的大小寫與剛剛計算的校驗和不匹配,這意味著地址中的某些內(nèi)容發(fā)生了變化,并且引入了錯誤。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容