[譯] 數字貨幣錢包詳解

「錢包」這個詞語在以太坊中表示的並非它原本的意思。前端

宏觀的講,錢包主要就是爲用戶提供用戶界面的一個應用。它掌管着用戶的金錢,管理着密鑰和地址,追蹤帳戶餘額以及建立交易和簽名。除此以外,一些以太坊錢包還能夠與智能合約進行交互,例如代幣之類的。python

而從一個程序員的角度更準確的講,「錢包」這個詞語指的就是存儲和管理密鑰和地址的系統。每個「錢包」都有一個密鑰管理組件。而對於有些錢包來講,這就是錢包的所有。其餘的大部分錢包都是「瀏覽器」,其實就是基於以太坊的去中心化應用的接口。因此這些各式各樣的「錢包」之間並無什麼明確的界限。android

接下來讓咱們先看一看錢包關於密鑰管理和私鑰容器部分的功能。ios

錢包技術總覽

在這個部分咱們會總結用於構建用戶友好、安全以及靈活的以太坊錢包所須要的各類技術。git

關於以太坊有一個最多見的誤解就是大部分人認爲以太坊錢包包含以太坊和其餘代幣。而實際上,錢包只包含密鑰。以太坊和其餘代幣都被記錄在以太坊的區塊鏈中。用戶經過使用他們錢包中的密鑰對錢包簽名來控制代幣。因此從某種意義上講,以太坊錢包就是一個鑰匙串程序員

提示github

以太坊錢包只包含密鑰,而沒有以太坊和代幣。每個用戶的錢包都包含密鑰。錢包就是包含公私鑰對的鑰匙串。用戶使用密鑰對交易簽名,以此來證實這些以太坊就是屬於他們的。而真正的以太坊則存儲在區塊鏈上。web

目前主要有兩種類型的錢包,他們的區別就是所包含的密鑰之間是否有關聯。算法

第一種類型叫作非肯定性錢包,它的每個密鑰都是經過一個隨機數獨立生成的。密鑰之間相互沒有關聯。這種錢包也叫作 JBOK 錢包(來自 "Just a Bunch Of Keys")。npm

第二種錢包叫作肯定性錢包,它全部的密鑰都來源於一個單獨的叫作種子的主密鑰。在這個錢包中全部的密鑰都相互關聯,而且任何擁有原始種子的人均可以將這些密鑰再生成一遍。這種肯定性錢包會使用不少不一樣的密鑰派生方法。而其中使用最廣泛的則是一種相似樹形結構的方法,這樣的錢包被稱爲分層肯定性或者 HD 錢包。

分層肯定性錢包是經過一個種子來初始化的。而爲了便於使用,種子會被編碼成英語單詞(或者其餘語言的單詞),這些單詞被稱爲助記詞

下面的章節將會在更高級的層面介紹這些技術。

非肯定性(隨機)錢包

在第一個的以太坊錢包(以太坊預售時發佈的)中,錢包文件會存儲一個單獨隨機生成的私鑰。然而這種錢包以後被肯定性錢包取代了,由於這種錢包沒法管理、備份以及導入私鑰。可是隨機密鑰的缺點是,若是你生成了不少那麼你就要把它們所有拷貝下來。每個密鑰都要備份,不然一旦錢包丟失,那些密鑰對應的資產也會丟失。進一步講,以太坊地址的隱私性會由於相互之間關聯的多筆交易和地址的重複使用而大大下降。一個類型-0 的非肯定性錢包並非一個好的選擇,尤爲是當你爲了不地址的重複使用而不得無論理多個密鑰並不斷頻繁的備份它們時。

不少以太坊客戶端(包括 go-ethereum 和 geth)都會使用一個鑰匙串文件,這是一個 JSON 編碼的文件,並且它還包含一個單獨的(隨機生成的)私鑰,爲了安全性,這個私鑰會經過一個密碼進行加密。這個 JSON 文件就像下面這樣:

{
    "address": "001d3f1ef827552ae1114027bd3ecf1f086ba0f9",
    "crypto": {
        "cipher": "aes-128-ctr",
        "ciphertext": "233a9f4d236ed0c13394b504b6da5df02587c8bf1ad8946f6f2b58f055507ece",
        "cipherparams": {
            "iv": "d10c6ec5bae81b6cb9144de81037fa15"
        },
        "kdf": "scrypt",
        "kdfparams": {
            "dklen": 32,
            "n": 262144,
            "p": 1,
            "r": 8,
            "salt": "99d37a47c7c9429c66976f643f386a61b78b97f3246adca89abe4245d2788407"
        },
        "mac": "594c8df1c8ee0ded8255a50caf07e8c12061fd859f4b7c76ab704b17c957e842"
    },
    "id": "4fcb2ba4-ccdb-424f-89d5-26cce304bf9c",
    "version": 3
}
複製代碼

鑰匙串格式使用的是Key Derivation Function (KDF),同時還被成爲密碼拉伸算法,這個算法能夠防止暴力破解、字典攻擊以及彩虹表攻擊。簡單來講就是私鑰並非直接經過密碼簡單的進行加密的。相反,這個密碼是經過不斷的重複哈希拉伸過的。這個哈希函數會重複 262144 輪,這個數字就是鑰匙串 JSON 文件中的 crypto.kdfparams.n 這個參數指定的。一個攻擊者試圖經過暴力破解的手段來破解密碼的話,那麼他須要爲每個可能的密碼執行 262144 輪哈希,這樣對於一個足夠複雜和長度的密碼來講被破解幾乎是不可能的。

這裏還有一些軟件庫能夠讀取和寫入鑰匙串格式,例如 JavaScript 的庫 keythereum:

github.com/ethereumjs/…

提示

除了一些簡單的測試以外,咱們是不推薦使用非肯定性錢包的。咱們推薦使用的是擁有助記詞種子備份功能的基於行業標準的HD 錢包

肯定性錢包(種子)錢包

肯定性或者說「種子」錢包是指那些全部的私鑰都是經過一個普通的種子使用一個單向哈希函數延伸而來的錢包。這個種子是結合一些其餘的數據而隨機生成的數字,例如利用一個索引數字或者「鏈碼」(查看HD 錢包(BIP-32/BIP-44)來派生出私鑰。在一個肯定性錢包中,一個種子就足夠恢復出全部派生的密鑰,所以只須要在建立的時候作一次備份就能夠了。同時,這個種子對於錢包來講也是能夠導入導出的,可讓全部用戶的密鑰在各類不一樣的錢包之間進行簡單的遷移。

HD 錢包 (BIP-32/BIP-44)

肯定性錢包的開發就是爲了能夠簡單的從一個「種子」派生出不少個密鑰。而這種肯定性錢包最高級的實現就是由比特幣的 BIP-32 標準定義的 HD 錢包。HD 錢包包含的密鑰來源於一個樹形的結構,例如一個父密鑰能夠派生出一系列子密鑰,每個子密鑰又能夠派生出一系列孫子密鑰,不停的循環往復,沒有盡頭。這個樹形結構的示意圖以下:

HD wallet: a tree of keys generated from a single
seed

HD 錢包相對於隨機的(非肯定性的)密鑰有兩個主要的優點。一,樹形結構能夠表達額外的組織意義,例如當一個子密鑰特定的分支用來接收轉入支付而另外一個不一樣的分支能夠接收轉出支付的改變。密鑰的分支也能夠在一些共同的設置中被使用,例如能夠分配不一樣的分支給部門、子公司、特定的函數或者不一樣的帳單類別。

第二個優點就是用戶可使用 HD 錢包在不利用相關私鑰的狀況下建立一系列公鑰。這樣 HD 錢包就能夠用來作一個安全的服務或者是一個僅僅用來觀察和接收的服務,而錢包自己卻沒有私鑰,因此它也沒法花費資金。

種子和助記詞 (BIP-39)

HD 錢包對於管理多個密鑰和地址來講是一個很強力的機制。若是再結合一個從一系列英語單詞(或者其餘語言的單詞)中建立種子的標準化方法的話,那麼經過錢包進行抄寫、導出和導入都變得更加簡單易用。這就是你們所熟知的由標準 BIP-39 定義的助記詞。今天,不少以太坊錢包(還有其餘的數字貨幣錢包)都在使用這個標準來導入導出種子,並使用共同的助記詞來進行備份和恢復。

讓咱們來從實踐的角度看一下。下面哪一個種子在抄寫、紙上記錄以及閱讀障礙這幾個方面更優秀呢?

一個 16 進制編碼的肯定性錢包種子

FCCF1AB3329FD5DA3DA9577511F8F137
複製代碼

一個由 12 個單詞組成的助記詞的錢包種子

wolf juice proud gown wool unfair
wall cliff insect more detail hub
複製代碼

錢包最佳實踐

隨着數字貨幣錢包技術的逐漸成熟,也慢慢造成了共同的行業標準,使得錢包在交互性、易用性、安全性和靈活性等方面大幅度提升。這些標準同時也使得錢包能夠僅僅從一個單獨助記詞就爲各類不一樣的數字貨幣派生出不一樣的密鑰。這些共同的標準就是下面這些:

  • 基於 BIP-39 的助記詞

  • 基於 BIP-32 的 HD 錢包

  • 基於 BIP-43 的多用途 HD 錢包結構

  • 基於 BIP-44 的多貨幣多帳戶錢包

這些標準或許會改變,也或許會被將來的開發者廢棄,可是如今它們組成的這一組連鎖技術儼然已經成爲了大多數數字貨幣的實際上的錢包標準。

這些標準已經被大部分的軟件和硬件錢包所採用,使得這些錢包之間能夠相互通用。一個用戶能夠從這些錢包中的任意一個導出助記詞,而後導入到另外一個錢包中,並恢復因此的交易、密鑰和地址。

不少軟件錢包都支持這種標準,例如(按字母 排序)Jaxx, MetaMask, MyEtherWallet (MEW)。硬件錢包則有 Keepkey, Ledger, and Trezor。

下面的章節會詳細講解這些技術。

提示

若是你要實現一個以太坊錢包,他應該是一個 HD 錢包,種子會被編碼成助記詞以供備份,BIP-3二、BIP-3九、BIP-4三、和 BIP-44 這些標準會在下面的章節中詳細說明。

助記詞 (BIP-39)

助記詞就是表明一個隨機數的單詞序列,這個助記詞會做爲種子派生出一個肯定性錢包。這個序列的單詞可以再次建立種子、錢包和全部派生出的密鑰。一個實現了肯定性錢包助記詞功能的應用將會向在第一次建立錢包的時候向用戶展現一組長度爲 12 到 24 的單詞序列。這個序列就是錢包的備份,它能夠在任何兼容的錢包上實現恢復和重建全部的密鑰。助記詞可讓用戶更簡單的備份錢包,由於相比於一組隨機數助記詞可讀性更好,抄寫的正確率也更高。

提示

助記詞經常與「大腦錢包」想混淆。可是它們並非一回事。而其中最主要的區別在於大腦錢包是由用戶本身選擇的單詞組成的,而助記詞則是錢包表明用戶隨機建立的。這個重要的區別使得助記詞更加的安全,由於人類隨機性的來源少的可憐。

助記詞編碼是在 BIP-39 中定義的。注意 BIP-39 只是助記詞編碼的一個實現。還有不少不一樣的標準,比特幣錢包 Electrum 就是在 BIP-39 以前使用了一組不一樣的單詞。BIP-39 這個標準是由硬件錢包 Trezor 背後的公司提出來的,並且還兼容 Electrum 的實現。可是,BIP-39 如今已經取得了普遍的行業支持,而且兼容十幾個相互操做的實現,因此 BIP-39 應該就是如今的行業標準。而且,BIP-39 能夠用來生成支持以太坊的多貨幣錢包,而 Electrum 的種子並不支持。

BIP-39 標準定義了助記詞編碼和種子的生成過程,也就是接下來的九個步驟。爲了表達的更清楚,整個過程分紅了兩個部分:第一步到第六步在生成助記詞,第七步到第九步在助記詞到種子

生成助記詞

助記詞是錢包使用 BIP-39 中定義的標準化過程自動生成的。錢包起始於一個熵的源頭,而後添加一個校驗和並將熵映射到一個單詞數組中。

  1. 建立一個 128 位到 256 位的隨機序列(熵)

  2. 經過取 SHA256 的前(熵長度除以 32)位來建立這個隨機序列的校驗和。

  3. 將校驗和添加到隨機序列的末尾。

  4. 將序列分紅幾個 11 位的部分。

  5. 從預約義的 2048 個單詞字典中將每個 11 位的值映射到一個單詞上面。

  6. 助記詞編碼就是一系列單詞。

生成熵並編碼成助記詞將會展現出熵是如何生成助記詞的。

Generating entropy and encoding as mnemonicwords

助記詞編碼:熵和單詞長度 展現出了熵數據的大小和單詞中助記詞長度的關係。

助記詞編碼: 熵(entropy)和單詞(word)長度
Entropy (bits) Checksum (bits) Entropy + checksum (bits) Mnemonic length (words)

128

4

132

12

160

5

165

15

192

6

198

18

224

7

231

21

256

8

264

24

從助記詞到種子

助記詞表明着長度爲 128 到 256 位的熵。這個熵會經過密鑰拉伸函數 PBKDF2 生成一個更長的(512 位)種子。這個種子再構建一個肯定性錢包並派生出它的密鑰。

密鑰拉伸函數須要兩個參數:助記詞和。鹽的目的是爲了讓暴力破解構建查詢表的難度提升。在標準 BIP-39 中,鹽還有另一個目的,那就是密碼能夠做爲一個額外的安全因子來保護種子,這部分會在BIP-39 中的可選密碼中詳細講述。

第七步到第九步的過程:

  1. 密鑰拉伸函數 PBKDF2 的第一個參數第六步中生成的助記詞。

  2. 密鑰拉伸函數 PBKDF2 的第二個參數就是。這個鹽由字符串常量 "mnemonic" 和一個額外的用戶提供的密碼字符串拼接構成。

  3. PBKDF2 使用 HMAC-SHA512 算法進行了 2048 輪哈希運算對助記詞和鹽進行拉伸,生成一個 512 位的值做爲最後的輸出。這個 512 位的值就是種子。

[fig_5_7] 展現出了一個助記詞是如何生成種子的。

From mnemonic to seed

提示

密鑰拉伸函數以及它的 2048 輪哈希從某種程度上講對於暴力破解助記詞和密碼是一個有效的保護。會讓其以昂貴的代價(在計算資源上)不停的嘗試成千上萬種密碼和助記詞的組合,而這些組合的數量則猶如汪洋大海(2512)。

下面的表格分別展現了 #mnemonic_128_no_pass、#mnemonic_128_w_pass 和 #mnemonic_256_no_pass 這幾個類型的助記詞和他們產生的種子(沒有密碼)的例子。

128 位(bit)熵(entropy)的助記詞編碼(mnemonic code),無密碼生成的種子(seed)

Entropy input (128 bits)

0c1e24e5917779d297e14d45f14e1a1a

Mnemonic (12 words)

army van defense carry jealous true garbage claim echo media make crunch

Passphrase

(none)

Seed (512 bits)

5b56c417303faa3fcba7e57400e120a0ca83ec5a4fc9ffba757fbe63fbd77a89a1a3be4c67196f57c39 a88b76373733891bfaba16ed27a813ceed498804c0570

128 位(bit)熵(entropy)的助記詞編碼(mnemonic code),有密碼生成的種子(seed)

Entropy input (128 bits)

0c1e24e5917779d297e14d45f14e1a1a

Mnemonic (12 words)

army van defense carry jealous true garbage claim echo media make crunch

Passphrase

SuperDuperSecret

Seed (512 bits)

3b5df16df2157104cfdd22830162a5e170c0161653e3afe6c88defeefb0818c793dbb28ab3ab091897d0 715861dc8a18358f80b79d49acf64142ae57037d1d54

256 位(bit)熵(entropy)的助記詞編碼(mnemonic code),無密碼生成的種子(seed)

Entropy input (256 bits)

2041546864449caff939d32d574753fe684d3c947c3346713dd8423e74abcf8c

Mnemonic (24 words)

cake apple borrow silk endorse fitness top denial coil riot stay wolf luggage oxygen faint major edit measure invite love trap field dilemma oblige

Passphrase

(none)

Seed (512 bits)

3269bce2674acbd188d4f120072b13b088a0ecf87c6e4cae41657a0bb78f5315b33b3a04356e53d062e5 5f1e0deaa082df8d487381379df848a6ad7e98798404

BIP-39 中的可選密碼

BIP-39 標準容許用戶在生成種子的時候使用可選密碼。若是沒有使用密碼,那麼助記詞就會被一個由常量字符串 "mnemonic" 組成的鹽拉伸,而後由給定的助記詞產生一個特定的 512 位種子。若是使用了密碼,則拉伸函數在使用同一個助記詞的狀況下會產生一個不一樣的種子。實際上,給定一個助記詞,每個可能的密碼都會生成不一樣的種子。而且基本上沒有任何「錯誤」的 密碼。全部的密碼都是可用的而且全部的密碼均可以生成不一樣種子,這些不一樣的助記詞會造成一組數量巨大的爲初始化的錢包。這些可能的錢包數量是如此之大 (2512),以致於實際狀況中暴力破解和意外猜對的可能性幾乎爲零,只要密碼擁有足夠的複雜度和長度。

提示

在標準 BIP-39 中不存在「錯誤的」密碼。每一個密碼都會生成一個錢包,若是不是以前使用的密碼的話那就是一個新的錢包。

可選密碼會產生兩個重要的特性:

  • 一個須要記憶的第二個因子能夠防止助記詞的備份被竊取。

  • 選擇密碼的這些貌似擁有可信拒絕能力或者說是「監禁的錢包」使得那些小額資金的錢包常常將攻擊者的注意力從那些「真正的」大額資金錢包中分散出來。

可是,須要注意的一點是使用密碼會面臨密碼丟失的風險。

  • 若是錢包的主人缺少行動能力或者去世了,那麼就沒人知道密碼了,也沒人知道種子是什麼,那麼錢包中儲存的全部資金就所有丟失了。

  • 相反,若是錢包的主人在與種子一樣的地方備份了密碼,那麼它就失去了第二個因素的目的。

雖然密碼很是有用,可是也應該結合當心的計劃備份和恢復的過程來使用,由於要考慮到錢包主人生還的可能性並能夠容許他們的家人來恢復數字貨幣的資產。

助記詞的工做

BIP-39 在不少不一樣的編程語言中都有實現的庫:

python-mnemonic
參考了 SatoshiLabs 團隊在 BIP-39 中提議的 Python 版本

Consensys/eth-lightwallet
用於節點和瀏覽器(基於 BIP-39)的輕量級 JS 以太坊錢包

npm/bip39
比特幣 BIP39 的 JavaScript 實現:用於生成肯定性密鑰的助記詞編碼

還有一個在單獨的網頁中實現的 BIP-39 生成器,這個網頁在測試和實驗中很是有用。BIP-39 生成器展現了一個能夠生成助記詞、種子以及拓展的私鑰的單獨的網頁。

A BIP-39 generator as a standalone web page

網頁(iancoleman.github.io/bip39/)能夠在瀏覽器中離線使用(在線固然也能夠)。

經過種子建立一個 HD 錢包

HD 錢包是經過一個根種子來建立的,這個根種子通常是 12八、256 或者 512 位的隨機數。一般狀況下,這個種子是經過一個助記詞來生成的。

HD 錢包中的每個密鑰都是派生自這個根種子,這樣就使得經過這個種子在其餘兼容性錢包中重建整個 HD 錢包成爲了可能。同時還使得備份、恢復、導出以及導入包含成千上萬個密鑰的錢包變的很是簡單,僅僅經過轉移從根種子派生出的助記詞就能夠了。

[[bip32_bip43/44]] ==== 分層肯定性錢包 (BIP-32) 和路徑 (BIP-43/44)

大多數 HD 錢包都遵循 BIP-32 標準,同時 BIP-32 也是肯定密鑰生成器的實際上的行業標準。詳細的說明能夠查看下面的連接:

github.com/bitcoin/bip…

在這裏咱們不會討論 BIP-32,咱們只須要理解錢包中使用它的部分就能夠了。在其餘一些軟件庫中還有不少關於 BIP-32 彼此協做的實現。

Consensys/eth-lightwallet
用於節點和瀏覽器(基於 BIP-39)的輕量級 JS 以太坊錢包

這裏還有一個標準 BIP-32 的網頁版的生成器,對於測試和實驗都很是有用。

bip32.org/

提示

這個單獨的 BIP-32 生成器不是一個 HTTPS 的站點。就是爲了告訴你使用這個工具不是安全的。只是用來作測試的。你不該該在生產環境中(真實的資金)使用這個網頁生成的密鑰。

拓展公鑰和私鑰

在 BIP-32 的術語中,一個父密鑰能夠拓展的生成「兒子」,這個兒子就是拓展密鑰。若是它是一個私鑰,那麼它就是一個拓展私鑰,並經過前綴 xprv 來區分:

xprv9s21ZrQH143K2JF8RafpqtKiTbsbaxEeUaMnNHsm5o6wCW3z8ySyH4UxFVSfZ8n7ESu7fgir8imbZKLYVBxFPND1pniTZ81vKfd45EHKX73
複製代碼

一個拓展公鑰經過前綴 xpub 來區分:

xpub661MyMwAqRbcEnKbXcCqD2GT1di5zQxVqoHPAgHNe8dv5JP8gWmDproS6kFHJnLZd23tWevhdn4urGJ6b264DfTGKr8zjmYDjyDTi9U7iyT
複製代碼

HD 錢包中一個很是有用的角色就是從父公鑰派生出子公鑰,不包含私鑰。這會給咱們提供兩種方法來派生子公鑰:從子私鑰或者直接從父公鑰來派生。

一個拓展公鑰能夠在 HD 錢包的結構中派生出全部的公鑰(也只能是公鑰)。

不管什麼狀況只要部署的服務和應用有一份拓展公鑰而且沒有私鑰,那麼這個快捷方式就能夠建立很是安全的公鑰。這種部署能夠生成無窮個公鑰和以太坊地址,可是卻不能花費任何發送到這些地址的資金。同時,在另一個更安全的服務器上,拓展私鑰能夠派生出全部相關的私鑰用來給交易簽名,並花費資金。

利用這種解決方案的一個常見的應用就是在一個 web 服務器上安裝一個拓展公鑰,來爲電子商務應用服務。這個網頁服務器可使用公鑰派生函數爲每一筆交易(例如客戶的購物車)創造出一個全新的以太坊地址。這個網頁服務器沒有任何私鑰因此盜賊也沒法竊取。不使用 HD 錢包的狀況下,想作到這個程度惟一的方法就是在一個分割的安全服務器上生成上千個以太坊地址而後在電子商務服務器上預加載他們。這個方法低效笨重,而且須要常常的維護以確保電子商務服務器不會泄露密鑰。

還有一個常見的應用就是冷存儲和硬件錢包。在這種場景下,拓展私鑰能夠存儲在硬件錢包中,可是拓展公鑰能夠放在線上。用戶能夠按照他們的意願建立接收的地址,私鑰則會離線安全的保存。想花掉裏面的資金的話,用戶能夠在離線簽名的以太坊客戶端或者支持交易簽名的硬件錢包上使用拓展私鑰。

硬化密鑰派生

從 xpub 中派生出一個公鑰分支的能力時頗有用的,但同時也是具備風險的。知道 xpub 並不意味着知道子密鑰。然而,由於 xpub 包含鏈碼,因此若是一個子密鑰被別人知道或者暴露了的話,那麼它就能夠和鏈碼一塊兒派生出全部其餘的子密鑰。一個單獨泄露的子密鑰和一個父鏈碼一塊兒能夠暴露出全部的子私鑰。而更糟糕的是,子私鑰和父鏈碼一塊兒還能夠推斷出父私鑰。

爲了不這個風險,HD 錢包使用了另一種叫作硬化派生的派生函數,這個函數能夠「破壞」父公鑰和子鏈碼的聯繫。這種硬化派生函數是使用父私鑰來派生出子鏈碼的,而不是父公鑰。這樣會在父或子序列中創造出一個「防火牆」,而這個防火牆並不會威脅到父或者子私鑰的安全。

簡單的來講就是,若是不想承受泄露你本身鏈碼風險,而且還想要方便的使用 xpub 來派生出公鑰分支,那麼你應該經過硬化父輩來派生它,而不是一個正常的父輩。這其中的最佳實踐就是,爲了防止威脅到主要的密鑰,主要密鑰的 level-1 子輩老是經過硬化派生來派生。

正常派生和硬化派生的指數

BIP-32 中的派生函數使用的是一個 32 位整型的指數。爲了方便的區分出正常派生函數和硬化派生函數生成的密鑰,這個指數分紅了兩個區間。0 到 231–1 (0x0 to 0x7FFFFFFF) 用來表示正常的派生。231 到 232–1 (0x80000000 to 0xFFFFFFFF) 用來表示硬化派生。所以,若是指數小於 231,則子輩是正常的,若是指數大於等於 231,那麼子輩就是硬化的。

爲了讓指數的易讀性和顯示性更好,硬化子輩的指數是從零開始顯示的(有一個素數符合)。第一個正常子密鑰則顯示爲 0,這樣第一個硬化子輩(指數爲 0x80000000)就會顯示爲 0'。而第二個硬化密鑰指數從 0x80000001 開始,而且顯示爲1',以此類推。當你看到一個 HD 錢包的指數爲 i' 時,就意味着 231+i。

HD 錢包密鑰標識符(路徑)

一個 HD 錢包中的密鑰是經過「路徑」命名規則來標識的,對於樹的每個層級都經過斜槓 (/) 這個字符來分隔(查看HD 錢包路徑示例)。 從主私鑰派生出的私鑰都以 "m." 開頭。從主公鑰派生出的公鑰以 "M." 開頭。所以主私鑰的第一個子私鑰就是 m/0。主公鑰的第一個子公鑰就是 M/0。第一個子輩的第二個孫子就是 m/0/1,以此類推。

一個密鑰的「祖先」是從右向左讀取的,直到派生出它自己的主密鑰爲止。舉個例子,標識符 m/x/y/z 就是 m/x/y 的第 z 個子密鑰、m/x 的第 y 個子密鑰、m 的第 x 個子密鑰。

HD 錢包路徑示例
HD path Key described

m/0

主私鑰 m 的第一個(0)兒子私鑰

m/0/0

第一個子輩(m/0)的第一個孫子私鑰

m/0'/0

第一個硬化子輩 (m/0') 的第一個標準孫子

m/1/0

第二個子輩(m/1)的第一個孫子私鑰

M/23/17/0/0

第 24 個子輩的第 18 個孫子輩的第一個曾孫輩的第一個玄孫的公鑰

HD 錢包的樹形結構指南

HD 錢包的樹形結構提供了巨大的靈活性。每個父拓展密鑰均可以擁有 40 億個子輩:20 億個普通子輩和 20 億個硬化子輩。每個子輩都有另外 40 億個子輩,以此類推。只要你想,這個樹形結構就能夠一代一代的無限延伸下去。可是這種靈活性又使得對這個無限的樹形結構操做變的複雜。尤爲是在各類實現之間轉移 HD 錢包變的尤其困難,由於這個內部的結構從分支到子分支的可能性是無限的。

如今的兩種 BIP 都是經過對 HD 錢包的樹形結構建立一些標準來解決這些複雜性的。BIP-43 提議將第一個硬化子指數做爲能夠表示樹形結構「用途」的特殊標識符。而 BIP-43 則認爲,HD 錢包應該只使用一個樹形結構 level-1 的分支,並經過定義它的用途來讓指數來標識結構以及剩餘數的命名空間。例如,一個 HD 錢包只使用分支 m/i'/,並打算使用它來指明一個特殊的用途,而這個用途就是用指數 "i" 來標識的。

再說明一下這個細則,BIP-44 提議的多貨幣多帳戶的結構就是 BIP-43 的「用途」數字 44'。全部的 HD 錢包都遵循 BIP-44 結構,這個結構就是實際中使用樹形結構一個分支 m/44'/ 所標識的結構。

BIP-44 還指明瞭五個預約義的樹層級:

m / purpose' / coin_type' / account' / change / address_index
複製代碼

第一個層級 "purpose" 一直等於 44'。第二個層級 "coin_type" 指明瞭數字貨幣的類型,對於多貨幣的 HD 錢包來每個種貨幣都在第二層級下有他本身的子樹。這裏有幾個在標準文檔中定義的貨幣,叫做 SLIP0044:

github.com/satoshilabs…

舉個例子:以太坊是 m/44'/60',以太經典是 m/44'/61',比特幣是 m/44'/0',全部這些貨幣的測試網絡都是 m/44'/1'。

第三個層級是 "account",它容許用戶把他們的錢包再分紅幾個邏輯子帳戶,用於會計或者組織的目的。舉例來講,一個 HD 錢包能夠包含兩個以太坊「帳戶」:m/44'/60'/0' 和 m/44'/60'/1'。而每一個賬戶都是它本身子樹的根。

由於 BIP-44 一開始是爲比特幣創造的,因此它包含的 "quirk" 和以太坊一點關係都沒有。路徑的第四層級是 "change",一個 HD 錢包有兩個子樹,一個用來建立接收地址,一個用來建立改變地址。而以太坊中只有「接收」地址,並不須要改變地址。注意,因爲上個層級使用了硬化派生,因此這個層級就是普通派生。這是爲了讓這個層級的樹能夠在非安全環境下導出可使用的公鑰。可用的地址由 HD 錢包派生出來做爲第四層級的子輩,而後造成樹第五層級的 "address_index"。舉例來講就是,以太坊的第三個接收地址在主帳戶中的支付將會是 M/44'/60'/0'/0/2。BIP-44 HD 錢包的結構示例

BIP-44 HD 錢包結構示例
HD 路徑 密鑰描述

M/44'/60'/0'/0/2

主以太坊帳戶的第三個收到的公鑰

M/44'/0'/3'/1/14

第四個比特幣帳戶的第 15 個可變地址的公鑰

m/44'/2'/0'/0/1

用於簽名交易的萊特幣主帳戶的第二個私鑰

掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章
相關標籤/搜索