密鑰、地址

以太坊的基礎技術之一是 密碼學 cryptography,它是數學的一個分支,廣泛用於計算機安全。密碼學在希臘文中的意思是“祕密寫作”,但密碼學的科學不僅僅包含祕密寫作,它被稱為加密。加密也可以用來檢驗證明 (prove) 祕密中的知識之正確性而不洩露該祕密(數位簽章),或者證明數據的真實性(數字指紋)。這些類型的密碼學證明是以太坊和大多數區塊鏈系統的關鍵數學工具,廣泛用於以太坊應用。諷刺的是,加密並不是以太坊的重要組成部分,因為它的通信和交易數據沒有加密,也不需要加密以保護系統。在本章中,我們將以密鑰和地址的形式介紹一些以太坊用來控制資金所有權的密碼學。

簡介

以太坊有兩種不同類型的帳戶,可以擁有和控制ether:外部擁有帳戶(EOA)和合同。在本節中,我們將研究使用密碼學來確定外部擁有帳戶(即私人密鑰)對ether的所有權。

EOAs中以太的所有權通過 數字密鑰 digital keys以太坊地址數位簽章 建立 。數字密鑰實際上並不儲存在區塊鏈中或在以太坊網路上傳輸,而是由用戶創建並儲存在檔案或稱為錢包的簡單資料庫中。用戶錢包中的數字密鑰完全獨立於以太坊協議,可以由用戶的錢包軟體生成和管理,無需參考區塊鏈或訪問互聯網。數字密鑰可實現以太坊的許多有趣特性,包括去中心化的信任和控制以及所有權證明。

以太坊交易需要將有效的數位簽章包含在區塊鏈中,該簽名只能使用密鑰生成;因此,任何擁有該密鑰副本的人都可以控制ether。以太坊交易中的數位簽章證明了資金的真正所有者。

數字密鑰成對組成,密鑰和公鑰。將公鑰視為類似於銀行帳號,私鑰類似於私密PIN,用於控制帳戶。以太坊的用戶很少看到這些數字密鑰。在大多數情況下,它們儲存在錢包檔案內並由以太坊錢包軟體管理。

在以太坊交易的付款部分中,預期收款人由以太坊地址表示,該地址與支票上的收款人名稱相同(即“付款給誰”)。在大多數情況下,以太坊地址是從公鑰生成並對應的。但是,並非所有以太坊地址都代表公鑰。他們也可以代表合同,我們將在 [contracts] 中看到。以太坊地址是用戶常會看到的唯一密鑰表示,因為這是他們需要與世界分享的部分。

首先,我們將介紹密碼學並解釋以太坊使用的數學。接下來,我們將看看密鑰是如何生成,儲存和管理的。最後,我們將回顧用於表示私鑰和公鑰以及地址的各種編碼格式。

公鑰密碼技術和密碼貨幣

公鑰密碼技術是現代資訊安全的核心概念。首先由Martin Hellman,Whitfield Diffie和Ralph Merkle在20世紀70年代公開發明的,這是一個巨大的突破,它激起了公眾對密碼學領域的廣泛興趣。在70年代以前,強大的密碼學知識在政府的控制下,很少有公開的研究,直到公鑰密碼技術研究的公開發表。

公鑰密碼系統使用唯一的密鑰來保護資訊。這些獨特的密鑰基於具有獨特屬性的數學函數:它們很容易在一個方向上計算,但很難在相反方向上計算。基於這些數學函數,密碼學能夠創建數字密鑰和不可偽造的數位簽章,這些簽名由數學定律保證。

例如,計算兩個大質數的乘積是微不足道的。但是給定兩個大質數的乘積,很難找到這兩個質數(稱為素因式分解問題)。假設我提供數字6895601並告訴你它是兩個質數的乘積。找到這兩個質數要比讓它們相乘生產6895601要困難得多。

如果你知道一些祕密資訊,這些數學函數可以很容易地被反轉。在我們上面的例子中,如果我告訴你一個主質數是1931,你可以簡單地用一個簡單的除法找到另一個:6895601/1931 = 3571。這樣的函數被稱為trapdoor函數因為給定一個祕密資訊,你可以採取一個快捷方式,使得反轉該函數很簡單。

在密碼學中有用的另一類數學函數基於橢圓曲線上的算術運算。在橢圓曲線算術中,乘以模數是簡單的,但是除法是不可能的(一個被稱為離散對數的問題)。橢圓曲線密碼術在現代計算機系統中被廣泛使用,並且是以太坊(和其他密碼貨幣)數字密鑰和數位簽章的基礎。

Tip

更多關於密碼學和現代密碼學中使用的數學函數:

橢圓曲線密碼學: https://en.wikipedia.org/wiki/Elliptic_curve_cryptography

在以太坊,我們使用公鑰加密技術來創建一個密鑰對,以控制對ether的訪問,並允許我們對合同進行身份驗證。密鑰對由私鑰和唯一公鑰組成,並且被認為是“一對兒”,因為公鑰是從私鑰中派生出來的。公鑰用於接收資金,私鑰用於創建數位簽章來簽署交易以支付資金。數位簽章也可用於驗證合同的所有者或用戶,我們將在 << contract_authentication>> 中看到。

公鑰和私鑰之間存在數學關係,允許私鑰用於在消息上生成簽名。該簽名可以在不公開私鑰的情況下使用公鑰進行驗證。

當使用ether時,當前所有者在交易中呈現她的公鑰和簽名(每次不同,但是使用相同的私鑰創建)。通過公鑰和簽名,以太坊系統中的每個人都可以獨立驗證並接受交易的有效性,從而確認在轉移ether的人擁有他們。

Tip

在大多數錢包實現中,為了方便起見,私鑰和公鑰一起儲存為key pair。但是,公鑰可以由私鑰進行簡單計算,因此只儲存私鑰也是可以的。

為什麼使用不對稱加密(公鑰/私鑰)?

為什麼在以太坊使用非對稱密碼術?它不習慣“加密”(保密)交易。相反,非對稱密碼術的有用特性是產生數位簽章的能力。私鑰可應用產生交易的數位簽章。這個簽名只能由知道私鑰的人制作。但是,任何有權訪問公鑰和交易簽名的人都可以使用它們來驗證。非對稱加密技術的這一有用特性使任何人都可以驗證每筆交易的每個簽名,

私鑰

私鑰只是一個隨機選取的數字。私有密鑰的所有權和控制權是用戶控制與相應以太坊地址相關聯的所有資金的基礎,也是對該地址的合同的訪問權授權。通過證明交易中使用的資金的所有權,私鑰用於創建花費ether所需的簽名。私鑰在任何時候都必須保密,因為向第三方透露密鑰相當於讓他們控制以太和由該密鑰保證的合同。私鑰還必須備份並防止意外丟失。如果它丟失了,無法恢復,它保護的資金也將永遠丟失。

Tip

以太坊私鑰只是一個數字。你可以使用硬幣,鉛筆和紙隨機挑選你的私鑰:投擲硬幣256次,得到可以在以太坊錢包中使用的隨機二進制數字作為私鑰。然後可以從私鑰生成公鑰和地址。

從隨機數生成私鑰

生成密鑰的第一步也是最重要的一步是找到一個安全的熵源或隨機源。創建以太坊私鑰基本上與“選擇1到2256之間的數字”相同。只要不可預測和不可重複,用於選擇該數字的確切方法並不重要。以太坊軟體使用底層作業系統的隨機數生成器生成256位熵(隨機性)。通常,作業系統隨機數生成器是由一個人為的隨機源進行初始化的,這就是為什麼可能會要求你將鼠標左右搖擺幾秒鐘,或者按下鍵盤上的隨機鍵。

更確切地說,可能的私鑰範圍略小於2256。在以太坊中,私鑰可以是1和n-1之間的任何數字,其中n是定義為使用的橢圓曲線的階數的常數(n = 1.158*1077,略小於2256)(參見橢圓曲線密碼學解釋)。為了創建這樣的密鑰,我們隨機選擇一個256位數字並檢查它是否小於n-1。在編程方面,這通常是通過將從密碼學安全的隨機源收集的更大的隨機比特串提供給256位雜湊演算法(如Keccak-256或SHA256)(參見 [cryptographic_hash_algorithm]),產生一個256位數字。如果結果小於n-1,我們有一個合適的私鑰。否則,我們只需再次嘗試使用另一個隨機數。

Warning

不要編寫自己的程式碼來創建隨機數或使用你的程式語言提供的“簡單”隨機數發生器。使用密碼學安全的偽隨機數字發生器(CSPRNG)和來自足夠熵源的種子。研究你選擇的隨機數生成器庫的文件,以確保其是密碼學安全的。正確實施CSPRNG對於密鑰的安全至關重要。

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

f8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315
Tip

以太坊的私人密鑰空間的大小(2256)是一個難以置信的大數目。十進制大約是1077。可見宇宙估計含有1080原子。

公鑰

以太坊公鑰是一個橢圓曲線上的 point,意思是它是一組滿足橢圓曲線方程的X和Y座標。

簡單來說,以太坊公鑰是兩個數字,並聯在一起。這些數字是通過一次單向的計算從私鑰生成的。這意味著,如果你擁有私鑰,則計算公鑰是微不足道的。但是你不能從公鑰中計算私鑰。

MATH即將發生!不要驚慌。如果你發現難以閱讀前一段,則可以跳過接下來的幾節。有很多工具和庫會為你做數學。

公鑰使用橢圓曲線乘法和私鑰計算,這是不可逆的:K = k * G,其中k是私鑰,G是一個稱為generator point的常數點,K是結果公鑰。如果你知道K,那麼稱為“尋找離散對數”的逆運算就像嘗試所有可能的k值一樣困難,也就是蠻力搜索。

簡單地說:橢圓曲線上的算術不同於“常規”整數算術。點(G)可以乘以整數(k)以產生另一點(K)。但是沒有除法這樣的東西,所以不可能簡單地用公共密鑰K除以點G來計算私鑰k。這是公鑰密碼技術和密碼貨幣中描述的單向數學函數。

Tip

橢圓曲線乘法是密碼學家稱之為“單向”函數的一種函數:在一個方向(乘法)很容易完成,而在相反方向(除法)不可能完成。私鑰的所有者可以很容易地創建公鑰,然後與世界共享,因為知道沒有人能夠反轉該函數並從公鑰計算私鑰。這種數學技巧成為證明以太坊資金所有權和合同控制權的不可偽造和安全數位簽章的基礎。

在我們演示如何從私鑰生成公鑰之前,我們先來看一下橢圓曲線加密。

橢圓曲線密碼學解釋

橢圓曲線密碼術是一種基於離散對數問題的非對稱或公鑰密碼體系,如橢圓曲線上的加法和乘法運算。

A visualization of an elliptic curve 是橢圓曲線的一個例子,類似於以太坊使用的曲線。

Tip

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

ecc-curve
Figure 1. A visualization of an elliptic curve

以太坊使用特定的橢圓曲線和一組數學常數,由國家標準與技術研究院(NIST)制定的名為 secp256k1 的標準中所定義的。secp256k1 曲線由以下函數定義,該函數產生一個橢圓曲線:

\[\begin{equation} {y^2 = (x^3 + 7)}~\text{over}~(\mathbb{F}_p) \end{equation}\]

\[\begin{equation} {y^2 \mod p = (x^3 + 7) \mod p} \end{equation}\]

mod p (模質數p) 表示該曲線在質數階p的有限域上,也寫作 \(\( \mathbb{F}_p \)\), 其中 p = 2256 – 232 – 29 – 28 – 27 – 26 – 24 – 1, 一個非常大的質數。

因為這條曲線是在有限的質數階上而不是在實數上定義的,所以它看起來像是一個散佈在二維中的點的模式,使得難以可視化。然而,數學與實數上的橢圓曲線的數學是相同的。作為一個例子,Elliptic curve cryptography: visualizing an elliptic curve over F(p), with p=17 在一個更小的質數階17的有限域上顯示了相同的橢圓曲線,顯示了一個網格上的點的圖案。secp256k1 以太坊橢圓曲線可以被認為是一個更復雜的模式,在一個不可思議的大網格上的點。

ecc-over-F17-math
Figure 2. Elliptic curve cryptography: visualizing an elliptic curve over F(p), with p=17

例如,以下是座標為(x,y)的點Q,它是 secp256k1 曲線上的一個點:

Q = (49790390825249384486033144355916864607616083520101638681403973749255924539515, 59574132161899900045862086493921015780032175291755807399284007721050341297360)

Using Python to confirm that this point is on the elliptic curve 顯示了如何使用Python檢查它。變數x和y是上述點Q的座標。變數p是橢圓曲線的主要階數(用於所有模運算的質數)。Python的最後一行是橢圓曲線方程(Python中的%運算符是模運算符)。如果x和y確實是橢圓曲線上的點,那麼它們滿足方程,結果為零(0L是零值的長整數)。通過在命令行上鍵入python 並複製下面的每行(不包括提示符 >>>),親自嘗試一下:

Example 1. Using Python to confirm that this point is on the elliptic curve
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

橢圓曲線算術運算

很多橢圓曲線數學看起來很像我們在學校學到的整數算術。具體而言,我們可以定義一個加法運算符,而不是添加數字就是在曲線上添加點。一旦我們有了加法運算符,我們也可以定義一個點和一個整數的乘法,等於重複加法。

A lot of elliptic curve math looks and works very much like the integer arithmetic we learned at school. Specifically, we can define an addition operator, which instead of adding numbers is adding points on the curve. Once we have the addition operator, we can also define multiplication of a point and a whole number, such that it is equivalent to repeated addition.

加法定義為給定橢圓曲線上的兩個點 P1 and P2 , 第三個點 P3 = P1 + P2, 也在橢圓曲線上。

在幾何上,這個第三點 P3 是通過在 P1 和 P2 之間畫一條直線來計算的。這條線將在另外一個地方與橢圓曲線相交。稱此點為 P3' = (x, y)。然後在x軸上反射得到 P3 = (x, –y)。

在橢圓曲線數學中,有一個叫做“無窮點”的點,它大致對應於零點的作用。在計算機上,它有時用 x = y = 0表示(它不滿足橢圓曲線方程,但它是一個容易區分的情況,可以檢查)。有幾個特殊情況解釋了“無窮點”的需要。

如果 P1 和 P2 是同一點,P1 and P2 之間的直線應該延伸到曲線上 P1 的切線。 該切線恰好與曲線在一個新點相交。你可以使用微積分技術來確定切線的斜率。我們將我們的興趣侷限在具有兩個整數座標的曲線上,這些技巧令人好奇地工作!

在某些情況下(即,如果 P1 和 P2 具有相同的x值但不同的y值),切線將精確地垂直,在這種情況下P3 =“無窮點”。

如果 P1 是“無窮點”,那麼 P1 + P2 = P2。 類似地, 如果 P2 是“無窮點”,P1 + P2 = P1。這顯示了無窮點如何扮演零在“正常”算術中扮演的角色。

+ 是可結合的, (A + B) + C = A + (B + C). 這表示 A + B + C 不加括號也沒有歧義。

現在我們已經定義了加法,我們可以用擴展加法的標準方式來定義乘法。對於橢圓曲線上的點P,如果k是整數,則 k * P = P + P + P + …​ + P (k 次)。請注意,在這種情況下,k有時會被混淆地稱為“指數”。

生成一個公鑰

以一個隨機生成的數字k的私鑰開始,我們通過將它乘以稱為generator point G的曲線上的預定點,在曲線上的其他位置產生另一個點,這是相應的公鑰K。生成點被指定為secp256k1標準的一部分,對於secp256k1的所有實現始終相同,並且從該曲線派生的所有密鑰都使用相同的點G

\[\begin{equation} {K = k * G} \end{equation}\]

其中k是私鑰,G是生成點,K是生成的公鑰,即曲線上的一個點。因為所有以太坊用戶的生成點始終相同,所以G乘以G的私鑰總是會導致相同的公鑰KkK之間的關係是固定的,但只能從kK的一個方向進行計算。這就是為什麼以太坊地址(來自K)可以與任何人共享,並且不會洩露用戶的私鑰(k)。

正如我們在 橢圓曲線算術運算中所描述的那樣,k * G的乘法相當於重複加,G + G + G + …​ + G ,重複k次。總而言之,為了從私鑰k生成公鑰K,我們將生成點G添加到自己k次。

Tip

私鑰可以轉換為公鑰,但公鑰不能轉換回私鑰,因為數學只能單向工作。

讓我們應用這個計算來找到我們在 私鑰 中給出的特定私鑰的公鑰:

Example private key to public key calculation
K = f8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315 * G

密碼庫可以幫助我們使用橢圓曲線乘法計算K值。得到的公鑰K被定義為一個點 K = (x,y) :

Example public key calculated from the example private key
K = (x, y)

where,

x = 6e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b
y = 83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0

在以太坊中,你可以看到公鑰以66個十六進制字符(33字節)的十六進制序列表示。這是從行業聯盟標準高效密碼組(SECG)提出的標準序列化格式採用的,在http://www.secg.org/sec1-v2.pdf[Standards for Efficient Cryptography(SEC1)]中有記載。該標準定義了四個可用於識別橢圓曲線上點的可能前綴:

Prefix

Meaning

Length (bytes counting prefix)

0x00

Point at Infinity

1

0x04

Uncompressed Point

65

0x02

Compressed Point with even Y

33

0x03

Compressed Point with odd Y

33

以太坊只使用未壓縮的公鑰,因此唯一相關的前綴是(十六進制)04。順序連接公鑰的X和Y座標:

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

因此,我們在 Example public key calculated from the example private key 中計算的公鑰被序列化為:

046e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0

橢圓曲線庫

密碼貨幣相關項目中使用了secp256k1橢圓曲線的幾個實現:

OpenSSL

OpenSSL庫提供了一套全面的加密原語,包括secp256k1的完整實現。例如,要派生公鑰,可以使用函數EC_POINT_mul()。https://www.openssl.org/

libsecp256k1

Bitcoin Core的libsecp256k1是secp256k1橢圓曲線和其他密碼原語的C語言實現。橢圓曲線密碼學的libsecp256是從頭開始編寫的,代替了Bitcoin Core軟體中的OpenSSL,在性能和安全性方面被認為是優越的。https://github.com/bitcoin-core/secp256k1

加密雜湊函數

加密雜湊函數在整個以太坊使用。事實上,雜湊函數幾乎在所有密碼系統中都有廣泛應用,這是密碼學家布魯斯•施奈爾(Bruce Schneier)所說的一個事實,他說:“單向雜湊函數遠不止於加密演算法,而是現代密碼學的主要工具。

在本節中,我們將討論雜湊函數,瞭解它們的基本屬性以及這些屬性如何使它們在現代密碼學的很多領域如此有用。我們在這裡討論雜湊函數,因為它們是將以太坊公鑰轉換成地址的一部分。

簡而言之,“雜湊函數是可用於將任意大小的數據映射到固定大小的數據的函數。” Source:Wikipedia。雜湊函數的輸入稱為 原象 _ pre-image_ 或 消息 message。輸出被稱為 雜湊 hash摘要 digest。雜湊函數的一個特殊子類別是 加密雜湊函數,它具有對密碼學有用的特定屬性。

加密雜湊函數是一種單向雜湊函數,它將任意大小的數據映射到固定大小的位串,如果知道輸出,計算上不可能重新創建輸入。確定輸入的唯一方法是對所有可能的輸入進行蠻力搜索,檢查匹配輸出。

加密雜湊函數有五個主要屬性 (Source: Wikipedia/Cryptographic Hash Function):

確定性

任何輸入消息總是產生相同的雜湊摘要。

可驗證性

計算消息的雜湊是有效的(線性性能)。

不相關

對消息的小改動(例如,一位改變)會大幅改變雜湊輸出,以致它不能與原始消息的雜湊相關聯。

不可逆性

從雜湊計算消息是不可行的,相當於通過可能的消息進行蠻力搜索。

碰撞保護

計算兩個不同的消息產生相同的雜湊輸出應該是不可行的。

碰撞保護對於防止以太坊中的數位簽章偽造至關重要。

這些屬性的組合使加密雜湊函數可用於廣泛的安全應用程式,包括:

  • 數據指紋識別

  • 消息完整性(錯誤檢測)

  • 工作證明

  • 認證(密碼雜湊和密鑰擴展)

  • 偽隨機數發生器

  • 原象承諾

  • 唯一識別碼

通過研究系統的各個層面,我們會在以太坊找到它的很多應用。

以太坊的加密雜湊函數 - Keccak-256

以太坊在許多地方使用Keccak-256加密雜湊函數。Keccak-256被設計為於2007年舉行的SHA-3密碼雜湊函數競賽的候選者。Keccak是獲勝的演算法,在2015年被標準化為 FIPS(聯邦資訊處理標準)202。

然而,在以太坊開發期間,NIST標準化工作正在完成。在標準過程完成後,NIST調整了Keccak的一些參數,據稱可以提高效率。這與英雄告密者愛德華斯諾登透露的檔案暗示NIST可能受到國家安全局的不當影響同時發生,故意削弱Dual_EC_DRBG隨機數生成器標準,有效地在標準隨機數生成器中放置一個後門。這場爭論的結果是對所提議修改的反對以及SHA-3標準化的嚴重拖延。當時,以太坊基金會決定實施最初的Keccak演算法。

Warning

雖然你可能在Ethereum文件和程式碼中看到“SHA3”,但很多(如果不是全部)這些實例實際上是指Keccak-256,而不是最終確定的FIPS-202 SHA-3標準。實現差異很小,與填充參數有關,但它們的重要性在於Keccak-256在給定相同輸入的情況下產生與FIPS-202 SHA-3不同的雜湊輸出。

由於Ethereum中使用的雜湊函數(Keccak-256)與最終標準(FIP-202 SHA-3)之間的差異造成了混淆,因此正在努力將程式碼中所有的 sha3 的所有實例,操作碼和庫重新命名為 keccak256。詳情請參閱https://github.com/ethereum/EIPs/issues/59[ERC-59]。

我正在使用哪個雜湊函數?

如何判斷你使用的軟體庫是FIPS-202 SHA-3還是Keccak-256(如果兩者都可能被稱為“SHA3”)?

一個簡單的方法是使用test vector,一個給定輸入的預期輸出。最常用於雜湊函數的測試是empty input。如果你使用空字串作為輸入運行雜湊函數,你應該看到以下結果:

Testing whether the SHA3 library you are using is Keccak-256 of FIP-202 SHA-3
Keccak256("") =
c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470

SHA3("") =
a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a

因此,無論調用什麼函數,都可以通過運行上面的簡單測試來測試它是否是原始的Keccak-256或最終的NIST標準FIPS-202 SHA-3。請記住,以太坊使用Keccak-256,儘管它在程式碼中通常被稱為SHA-3。

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

以太坊地址

以太坊地址是 唯一識別碼 unique identifiers,它們是使用單向雜湊函數(Keccak-256)從公鑰或合約派生的。

在我們之前的例子中,我們從一個私鑰開始,並使用橢圓曲線乘法來派生一個公鑰:

Private Key k:

k = f8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315

Public Key K (X and Y coordinates concatenated and shown as hex):

K = 6e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0
Warning

值得注意的是,在計算地址時,公鑰沒有用前綴(十六進制)04格式化。

我們使用Keccak-256來計算這個公鑰的hash

Keccak256(K) = 2a5bc342ed616b5ba5732269001d3f1ef827552ae1114027bd3ecf1f086ba0f9

然後我們只保留最後的20個字節(大端序中的最低有效字節),這是我們的以太坊地址:

001d3f1ef827552ae1114027bd3ecf1f086ba0f9

大多數情況下,你會看到帶有前綴“0x”的以太坊地址,表明它是十六進制編碼,如下所示:

0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9

以太坊地址格式

以太坊地址是十六進制數字,從公鑰的Keccak-256雜湊的最後20個字節匯出的識別碼。

與在所有客戶端的用戶界面中編碼的比特幣地址不同,它們包含內建校驗和來防止輸入錯誤的地址,以太坊地址以原始十六進制形式呈現,沒有任何校驗和。

該決定背後的基本原理是,以太坊地址最終會隱藏在系統高層的抽象(如名稱服務)之後,並且必要時應在較高層添加校驗和。

回想起來,這種設計選擇導致了一些問題,包括由於輸入錯誤地址和輸入驗證錯誤而導致的資金損失。以太坊名稱服務的開發速度低於最初的預期,諸如ICAP之類的替代編碼被錢包開發商採用得非常緩慢。

互換客戶端地址協議 Inter Exchange Client Address Protocol (ICAP)

互換客戶端地址協議(ICAP)是一種部分與國際銀行帳號(IBAN)編碼兼容的以太坊地址編碼,為以太坊地址提供多功能,校驗和互操作編碼。ICAP地址可以編碼以太坊地址或通過以太坊名稱註冊表註冊的常用名稱。

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

IBAN是識別銀行帳號的國際標準,主要用於電匯。它在歐洲單一歐元支付區(SEPA)及其以後被廣泛採用。IBAN是一項集中和嚴格監管的服務。ICAP是以太坊地址的分散但兼容的實現。

一個IBAN由含國家程式碼,校驗和和銀行帳戶識別碼(特定國家)的34個字母數字字符(不區分大小寫)組成。

ICAP使用相同的結構,通過引入代表“Ethereum”的非標準國家程式碼“XE”,後面跟著兩個字符的校驗和以及3個可能的帳戶識別碼變體:

Direct

最多30個字母數字字符big-endian base-36整數,表示以太坊地址的最低有效位。由於此編碼適合小於155位,因此它僅適用於以一個或多個零字節開頭的以太坊地址。就欄位長度和校驗和而言,它的優點是它與IBAN兼容。範例:XE60HAMICDXSV5QXVJA7TJW47Q9CHWKJD(33個字符長)

Baasic

與“Direct”編碼相同,只是長度為31個字符。這使它可以編碼任何以太坊地址,但使其與IBAN欄位驗證不兼容。範例:XE18CHDJBPLTBCJ03FE9O2NS0BPOJVQCU2P(35個字符長)

Indrect

編碼通過名稱註冊表提供程式解析為以太坊地址的識別碼。使用由asset identifier(例如ETH),名稱服務(例如XREG)和9個字符的名稱(例如KITTYCATS)組成的16個字母數字字符,這是一個人類可讀的名稱。範例:XE## ETHXREGKITTYCATS(20個字符長),其中“##”應由兩個計算校驗和字符替換。

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

$ helpeth keyDetails -p 0xf8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315

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

helpeth 命令為我們構建了一個十六進制以太坊地址以及一個ICAP地址。我們範例密鑰的ICAP地址是:

XE60HAMICDXSV5QXVJA7TJW47Q9CHWKJD

由於我們的範例以太坊地址恰好以零字節開始,因此可以使用IBAN格式中有效的“Direct”ICAP編碼方法進行編碼。因為它是33個字符長。

如果我們的地址不是從零開始,那麼它將被編碼為“Basic”編碼,這將是35個字符長並且作為IBAN格式無效。

Tip

以零字節開始的任何以太坊地址的概率是1/256。為了生成這樣一個類型,在我們找到一個作為IBAN兼容的“Direct”編碼之前,它將平均用256個不同的隨機私鑰進行256次嘗試ICAP地址。

不幸的是,現在,只有幾個錢包支持ICAP。

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

由於ICAP或名稱服務部署緩慢,因此提出了一個新的標準,以太坊改進建議55(EIP-55)。你可以閱讀詳細資訊:

通過修改十六進制地址的大小寫,EIP-55為以太坊地址提供了向後兼容的校驗和。這個想法是,以太坊地址不區分大小寫,所有錢包都應該接受以大寫字母或小寫字母表示的以太坊地址,在解釋上沒有任何區別。

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

混合大小寫編碼很微妙,最初你可能不會注意到它。我們的範例地址是:

0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9

使用 EIP-55 混合大小寫校驗和,它變為:

0x001d3F1ef827552Ae1114027BD3ECF1f086bA0F9

你能看出區別嗎?一些來自十六進制編碼字母表的字母(AF)字符現在是大寫字母,而另一些則是小寫字母。除非你仔細觀察,否則你甚至可能沒有注意到其中的差異。

EIP-55實施起來相當簡單。我們採用小寫十六進制地址的Keccak-256雜湊。這個雜湊作為地址的數字指紋,給我們一個方便的校驗和。輸入(地址)中的任何小改動都會導致雜湊結果(校驗和)發生很大變化,從而使我們能夠有效地檢測錯誤。然後我們的地址的雜湊被編碼為地址本身的大寫字母。讓我們一步步分解它:

  1. 計算小寫地址的雜湊,不帶 0x 前綴::

Keccak256("001d3f1ef827552ae1114027bd3ecf1f086ba0f9")
23a69c1653e4ebbb619b0b2cb8a9bad49892a8b9695d9a19d8f673ca991deae1
  1. 如果雜湊的相應十六進制數字大於或等於 0x8,則將每個字母地址字符大寫。如果我們排列地址和雜湊,這將更容易顯示:

Address: 001d3f1ef827552ae1114027bd3ecf1f086ba0f9
Hash   : 23a69c1653e4ebbb619b0b2cb8a9bad49892a8b9...

我們的地址在第四個位置包含一個字母 d。雜湊的第四個字符是 6,小於8。所以,我們保持 d 小寫。我們地址中的下一個字母字符是 f,位於第六位。十六進制雜湊的第六個字符是 c,它大於8 +。因此,我們在地址中大寫 +F,等等。正如你所看到的,我們只使用雜湊的前20個字節(40個十六進制字符)作為校驗和,因為我們只有20個字節(40個十六進制字符)能正確地大寫。

檢查自己產生的混合大寫地址,看看你是否可以知道在地址雜湊中哪些字符被大寫和它們對應的字符:

Address: 001d3F1ef827552Ae1114027BD3ECF1f086bA0F9
Hash   : 23a69c1653e4ebbb619b0b2cb8a9bad49892a8b9...

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

現在,我們來看看EIP-55地址如何幫助我們發現錯誤。假設我們已經打印出ETHER-E編碼的以太坊地址:

0x001d3F1ef827552Ae1114027BD3ECF1f086bA0F9

現在,讓我們在閱讀該地址時犯一個基本錯誤。最後一個字符之前的字符是大寫字母“F”。對於這個例子,我們假設我們誤解為大寫“E”。我們在錢包中輸入(不正確的地址):

0x001d3F1ef827552Ae1114027BD3ECF1f086bA0E9

幸運的是,我們的錢包符合EIP-55標準!它注意到混合大寫字母並試圖驗證地址。它將其轉換為小寫,並計算校驗和雜湊值:

Keccak256("001d3f1ef827552ae1114027bd3ecf1f086ba0e9")
5429b5d9460122fb4b11af9cb88b7bb76d8928862e0a57d46dd18dd8e08a6927

如你所見,即使地址只改變了一個字符(事實上,“e”和“f”只相隔1位),地址的雜湊值已經根本改變了。這是雜湊函數的特性,使它們對校驗和非常有用!

現在,讓我們排列這兩個並檢查大小寫:

001d3F1ef827552Ae1114027BD3ECF1f086bA0E9
5429b5d9460122fb4b11af9cb88b7bb76d892886...

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

我們輸入的地址的大小寫與剛剛計算的校驗和不匹配,這意味著地址中的內容發生了變化,並且引入了錯誤。

<<第六章#,下一章:錢包>>

results matching ""

    No results matching ""