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

原文:Keys, Addresses

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

介紹

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

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

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

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

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

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

公鑰加密和加密貨幣

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

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

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

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

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

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

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

公鑰和私鑰之間存在數(shù)學(xué)關(guān)系,允許私鑰用于在消息上生成簽名??梢栽诓恍孤端借€的情況下針對(duì)公鑰驗(yàn)證此簽名。

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

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

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

私鑰

私鑰只是一個(gè)隨機(jī)挑選的數(shù)字。對(duì)私鑰的所有權(quán)和控制權(quán)是用戶控制與相應(yīng)的以太坊地址相關(guān)聯(lián)的所有資金的根源,以及對(duì)授權(quán)該地址的合約的訪問權(quán)。私鑰用于通過證明交易中使用的資金所有權(quán)來(lái)創(chuàng)建需要花費(fèi)以太的簽名。私鑰必須始終保密,因?yàn)橄虻谌脚端借€等同于讓他們控制以太和由該密鑰保護(hù)的合約。還必須備份私鑰并防止意外丟失。如果它丟失了,它就無(wú)法恢復(fù),而它所保證的資金也會(huì)永遠(yuǎn)丟失。

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

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

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

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

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

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

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

公鑰

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

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

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

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

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

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

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

橢圓曲線加密解釋

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

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

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

圖1.橢圓曲線的可視化

以太坊使用特定的橢圓曲線和一組數(shù)學(xué)常數(shù),如由國(guó)家標(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 素?cái)?shù)p)表明,該曲線是在素?cái)?shù)階的有限域p,也寫為F_p,其中p = 2^{256} - 2^{32} - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1,一個(gè)非常大的素?cái)?shù)。

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

image

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

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

Q =(49790390825249384486033144355916864607616083520101638681403973749255924539515,59574132161899900045862086493921015780032175291755807399284007721050341297360)

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

示例1.使用Python確認(rèn)此點(diǎn)位于橢圓曲線上

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ù)運(yùn)算

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

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

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

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

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

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

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

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

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

生成公鑰

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

K = k * G

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

正如我們?cè)跈E圓曲線算術(shù)運(yùn)算中所描述的,k * G的乘法等價(jià)于重復(fù)的加法,所以G + G + G +…+ G,重復(fù)k次??傊?,要從私鑰k中生成公鑰K,我們將生成器點(diǎn)G加上它自己,K次。

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

讓我們應(yīng)用此計(jì)算來(lái)查找我們?cè)谒借€中顯示的特定私鑰的公鑰:

示例公鑰計(jì)算的私鑰

K = f8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315 * G

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

示例公鑰由示例私鑰計(jì)算

K = (x, y)

where,

x = 6e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b
y = 83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0

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

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

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

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

因此,我們?cè)赱示例公鑰由示例私鑰計(jì)算]中計(jì)算的公鑰被序列化為:

046e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0

橢圓曲線庫(kù)

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

OpenSSL

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

libsecp256k1

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

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

加密哈希函數(shù)

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

在本節(jié)中,我們將討論哈希函數(shù),理解它們的基本屬性以及這些屬性如何使它們?cè)诂F(xiàn)代密碼學(xué)的許多領(lǐng)域中如此有用。我們?cè)谶@里解釋哈希函數(shù),因?yàn)樗鼈兪菍⒁蕴W(wǎng)公鑰轉(zhuǎn)換為地址的一部分。

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

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

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

確定性

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

可驗(yàn)證

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

不相關(guān)

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

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

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

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

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

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

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

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

隨著我們?cè)谙到y(tǒng)的各個(gè)層面上進(jìn)展,我們將在以太坊中找到許多這些。

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

以太坊在許多地方使用Keccak-256加密哈希函數(shù)。Keccak-256被設(shè)計(jì)為2007年由國(guó)家科學(xué)技術(shù)研究所(NIST)舉辦的SHA-3密碼哈希函數(shù)競(jìng)賽的候選人。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ù)稱是為了提高其效率。這是在英雄告密者愛德華·斯諾登透露文件的同時(shí)發(fā)生的,這些文件暗示NIST可能受到國(guó)家安全局的不當(dāng)影響,故意削弱Dual_EC_DRBG隨機(jī)數(shù)發(fā)生器標(biāo)準(zhǔn),有效地在標(biāo)準(zhǔn)隨機(jī)數(shù)發(fā)生器中放置后門。這一爭(zhēng)議的結(jié)果是對(duì)提議的變更的強(qiáng)烈抵制以及SHA-3標(biāo)準(zhǔn)化的顯著延遲。當(dāng)時(shí),以太坊基金會(huì)決定實(shí)施其發(fā)明人提出的原始Keccak算法,

Warning 雖然您可能會(huì)在以太坊文檔和代碼中看到“SHA3”,但很多(如果不是全部)實(shí)例實(shí)際上都是指Keccak-256,而不是最終的FIPS-202 SHA-3標(biāo)準(zhǔn)。實(shí)現(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)在正在努力將所有代碼、操作碼和庫(kù)中的sha3實(shí)例重命名為keccak256。有關(guān)詳細(xì)信息,請(qǐng)參閱ERC-59。

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

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

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

測(cè)試您使用的SHA3庫(kù)是否為FIP-202 SHA-3的Keccak-256

Keccak256("")=
c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470

SHA3??("")=
a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a

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

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

以太坊地址

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

私鑰k:

k = f8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315

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

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

我們使用Keccak-256來(lái)計(jì)算這個(gè)公鑰的哈希值:

Keccak256(K)= 2a5bc342ed616b5ba5732269001d3f1ef827552ae1114027bd3ecf1f086ba0f9

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

001d3f1ef827552ae1114027bd3ecf1f086ba0f9

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

0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9

以太坊地址格式

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

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

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

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

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

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

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

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

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

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

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

我們可以使用helpeth命令行工具來(lái)創(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)造十六進(jìn)制以太坊地址和ICAP地址。我們的示例密鑰的ICAP地址是:

XE60HAMICDXSV5QXVJA7TJW47Q9CHWKJD

因?yàn)槲覀兊氖纠蕴坏刂非『靡粤阕止?jié)開始,所以可以使用在IBAN格式中有效的“直接”ICAP編碼方法對(duì)其進(jìn)行編碼。你可以說(shuō),因?yàn)樗L(zhǎng)33個(gè)字符。

如果我們的地址不是以零開頭,則它將使用“基本”編碼進(jìn)行編碼,該編碼長(zhǎng)度為35個(gè)字符,并且作為IBAN格式無(wú)效。

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

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

大小寫校驗(yàn)和的十六進(jìn)制編碼(EIP-55)

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

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

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

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

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

0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9

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

0x001d3F1ef827552Ae1114027BD3ECF1f086bA0F9

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

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

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

Keccak256( “001d3f1ef827552ae1114027bd3ecf1f086ba0f9”)
23a69c1653e4ebbb619b0b2cb8a9bad49892a8b9695d9a19d8f673ca991deae1

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

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

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

自己檢查生成的混合大小寫地址,看看是否可以分辨哪些字符大寫,以及它們?cè)诘刂饭V袑?duì)應(yīng)的字符:

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

檢測(cè)EIP-55編碼地址中的錯(cuò)誤

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

0x001d3F1ef827552Ae1114027BD3ECF1f086bA0F9

現(xiàn)在讓我們?cè)陂喿x該地址時(shí)犯一個(gè)基本錯(cuò)誤。最后一個(gè)字符前面的字符是大寫字母“F”。對(duì)于這個(gè)例子,讓我們假設(shè)我們把它誤讀為大寫“E”。我們?cè)阱X包里輸入(錯(cuò)誤的地址):

0x001d3F1ef827552Ae1114027BD3ECF1f086bA0E9

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

Keccak256( “001d3f1ef827552ae1114027bd3ecf1f086ba0e9”)
5429b5d9460122fb4b11af9cb88b7bb76d8928862e0a57d46dd18dd8e08a6927

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

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

001d3F1ef827552Ae1114027BD3ECF1f086bA0E9
5429b5d9460122fb4b11af9cb88b7bb76d892886 ...

這都錯(cuò)了!幾個(gè)字母字符的大寫不正確。請(qǐng)記住,大小寫是正確校驗(yàn)和的編碼。

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

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

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

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