【轉】乾貨 | 【虛擬貨幣錢包】從 BIP3二、BIP3九、BIP44 到 Ethereum HD Wallet

虛擬貨幣錢包

錢包顧名思義是存放$$$。但在虛擬貨幣世界有點不同,個人賬戶資訊(像是我有多少錢)是儲存在區塊鏈上,實際存在錢包中的是個人賬戶對應的 key。有了這把 key 我就能夠在虛擬貨幣世界證實個人身份、就能夠更改我賬戶的狀態(像是送錢給別人)。這樣來講,虛擬貨幣錢包其實是管理和儲存 key 的工具。這把 key 就是個人私鑰,而賬戶是從個人公鑰衍伸出來。git

img-Ledger 虛擬貨幣錢包-github

BIP32, BIP39, BIP44

BIP 全名是 Bitcoin Improvement Proposals,是提出 Bitcoin 的新功能或改進措施的文件。可由任何人提出,通過審覈後公佈在 bitcoin/bips 上。BIP 和 Bitcoin 的關係,就像是 RFC 之於 Internet。算法

而其中的 BIP32, BIP39, BIP44 共同定義了目前被普遍使用的 HD Wallet,包含其設計動機和理念、實做方式、實例等。npm

  • BIP32:定義 Hierarchical Deterministic wallet (簡稱 "HD Wallet"),是一個系統能夠從單一個 seed 產生一樹狀結構儲存多組 keypairs(私鑰和公鑰)。好處是能夠方便的備份、轉移到其餘相容裝置(由於都只須要 seed),以及分層的權限控制等。

img-BIP32 定義的 HD Wallet-瀏覽器

  • BIP39:將 seed 用方便記憶和書寫的單字表示。通常由 12 個單字組成,稱爲 mnemonic code(phrase),中文稱爲助記詞或助記碼。例如:

rose rocket invest real refuse margin festival danger anger border idle brown安全

  • BIP44:基於 BIP32 的系統,賦予樹狀結構中的各層特殊的意義。讓同一個 seed 能夠支援多幣種、多賬戶等。各層定義以下:

m / purpose' / coin_type' / account' / change / address_index架構

其中的 purporse' 固定是 44',表明使用 BIP44。而 coin_type' 用來表示不一樣幣種,例如 Bitcoin 就是 0',Ethereum 是 60'ide

Ethereum HD Wallet

Ethereum 的錢包目前均採用以上 Bitcoin HD Wallet 的架構,並訂 coin_type' 爲 60',能夠在 ethereum/EIPs/issues 中看到相關的討論。舉例來講,在一個 Ethereum HD Wallet 中,第一個賬戶(這裏的賬戶指 BIP44 中定義的 account')的第一組 keypair,其路徑會是 m/44'/60'/0'/0/0工具


建立 Ethereum HD wallet

使用的 JavaScript 套件包含:區塊鏈

  • bip39:實做 BIP39,隨機產生新的 mnemonic code,並能夠將其轉成 binary 的 seed。
  • ethereumjs-wallet:產生和管理公私鑰,我使用其中的 hdkey 子套件來建立 HD Wallet。
  • ethereumjs-util:集合許多 Ethereum 須要的運算功能。

安裝套件

npm install bip39 ethereumjs-wallet ethereumjs-util --save

匯入套件

var bip39 = require('bip39')
var hdkey = require('ethereumjs-wallet/hdkey')
var util = require('ethereumjs-util')

產生 mnemonic code

var mnemonic = bip39.generateMnemonic()

取得的 mnemonic code 會像:

rose rocket invest real refuse margin festival danger anger border idle brown

產生 HD wallet

先將 mnemonic code 轉成 binary 的 seed。

var seed = bip39.mnemonicToSeed(mnemonic)

使用 seed 產生 HD Wallet。若是要說更明確,就是產生 Master Key 並記錄起來。

var hdWallet = hdkey.fromMasterSeed(seed)

產生第一個 Ethereum Address

產生 Wallet 中第一個賬戶的第一組 keypair。能夠從 Master Key,根據其路徑 m/44'/60'/0'/0/0 推導出來。

var key1 = hdWallet.derivePath("m/44'/60'/0'/0/0")

使用 keypair 中的公鑰產生 address。

var address1 = util.pubToAddress(key1._hdkey._publicKey, true)

取得的 Address:

685ce4cbdd5c19b64ca008cb85b83947e5318efa

Encoding Address

Ethereum 很貼心,爲了不你們打錯 address(致使把錢送錯人),Ethereum 讓 Address 變得比較難打?!總之通常會用 EIP55: Mixed-case checksum address encoding 再進行編碼。許多錢包也支援用戶輸入沒通過編碼的 Address,那就會跳過 checksum 機制,建議仍是使用編碼過的 Address。

address1 = util.toChecksumAddress(address1.toString('hex'))

最後取得的 Address 會像:

0x685ce4CbDd5c19b64CA008cB85b83947e5318EFA

能夠用 Mnemonic Code Converter 驗證結果

img

輸入 mnemonic code

img-產生 Address、公鑰、私鑰,結果和我取得的 Address -


使用 Ethereum HD wallet

把 mnemonic code 記錄下來好好保存,就會是一個冷錢包(指不連網路的錢包,因此安全不少)。可使用產生出來的 address 收 Ether 或任何 REC20 Token。要送錢的話,能夠匯入到任一個支援 Ethereum HD Wallet 的錢包。經常使用的 Ethereum HD wallet 像,在瀏覽器使用的 MyEtherWallet、MetaMask 和在手機使用的 imToken 等。

img-MetaMask-

題外話,MetaMask 如何在瀏覽器儲存咱們的 mnemonic code?

相信你們都瞭解了,有 mnemonic code 就能夠產生 HD Wallet 中全部的 keys。有了 keys 就能夠任意送錢包中的 Ether 或 Token 給別人。因此 mnemonic code 很重要!!!那這麼重要的東西保存在瀏覽器不會很危險嗎?我便研究下我經常使用的 MetaMask 瀏覽器錢包。MetaMask 將加密後的 mnemonic code 存在瀏覽器的 Local Storage(一塊只存在 Local 且不會過時的資料區塊)。加密使用用戶另外輸入的密碼,再匯入時會要求用戶設定密碼(如上圖),而每一次從新開啓錢包都會要求輸入密碼。解密算法有 Open Source,也有線上 Live Demo

img-MetaMask Local Storage-


References

其餘相關 Ethereum JavaScript 套件

感謝 Jiyi 大大提供密碼學專業知識,雖然詳細的數學計算本篇沒有提到,但讓我有底氣的完成這篇文章。


做者: 安德森_Anderson

本文首發於簡書,EthFans 經做者受權後轉載。

相關文章
相關標籤/搜索