區塊鏈入門 ② - 錢包
錢包
概述
-
定義
- 廣義上講,錢包是一個應用程式,為用戶提供互動界面,錢包控制用戶訪問權限,管理私鑰和地址,跟蹤余額以及創建和簽名交易,
- 狹義上講,從程式員的角度來看,“錢包”是指用于存盤和管理用戶私鑰的資料結構,也是本章所指的錢包含義,
-
錢包型別
-
第一種型別是非確定性錢包(nondeterministic wallet),其中每個私鑰都是從亂數獨立生成的,密鑰彼此之間無關聯,

-
必須備份所有私鑰,
-
如果為了減少備份而復用地址,這會將多個交易與此地址關聯在一起,這樣會增加隱私泄露風險,
-
除了簡單的測驗之外,不推薦非確定性錢包,
-
-
第二種型別是確定性錢包(deterministic wallet),其中所有的私鑰都是從一個主私鑰派生出來,這個主私鑰即為種子(seed),該型別錢包中所有私鑰都相互關聯,如果有原始種子,則可以再次生成全部私鑰,
-
1 型確定性錢包

-
分層確定性錢包

-
優點一:樹狀結構可以用來表達額外的組織含義,
-
優點二:可以讓用戶去創建一系列公鑰而無須知曉相對應的私鑰,(見子公鑰的派生)
-
-
-
注記詞
- 助記詞編碼是表示確定性錢包的種子的英語單詞序列,
- 不同于“腦錢包”,腦錢包由用戶選擇的單詞組成,而助記詞是由錢包隨機創建并展現給用戶的,
- 創建注記詞程序

- 創建一個 128~256 位的亂數(熵),
- 提取亂數的 SHA256 散列值的前 x 位(x 等于亂數位數除以 32)作為校驗碼,
- 將校驗碼添加到隨機序列的末尾,
- 將序列按 11 位進行劃分,
- 將每 11 位的值映射到一個含 2048($2^{11}$)個單詞的預定義字典中,
- 生成的有順序的單詞組就是助記詞,

-
從注記詞生成種子
- 助記詞表示長度為 128~256 位的熵(亂數),通過使用密鑰延伸函式 PBKDF2,熵被用于派生出更長的(512 位)種子,將所得的種子用于構建確定性錢包并派生密鑰,

- PBKDF2 密鑰延伸函式的第一個引數是從步驟 6 生成的助記詞,
- PBKDF2 密鑰延伸函式的第二個引數是鹽,由固定的字串“mnemonic”與可選的用戶輸入的密碼字串連接組成,
- PBKDF2 將助記詞和鹽作為引數,呼叫 2048 次 HMAC-SHA512 散列演算法,生成一個 512 位的值作為其延伸的最終輸出,這個 512 位的值就是種子,
創建主私鑰和主鏈碼

- 根種子(還有可選密碼)輸入到 HMAC-SHA512 演算法中就可以得到一個可用來創造主私鑰(m)和主鏈碼(c)的散列值,
- 主私鑰(m)可以生成相對應的主公鑰(M),
- 主鏈碼(c)用于從父私鑰創造子私鑰的那個函式中引入亂數(熵),
子密鑰的派生
分層確定性錢包使用 CKD(child key derivation,子密鑰派生)函式從父密鑰派生出子密鑰,
-
子密鑰派生函式是基于單向散列函式的,這個函式結合了:
- 一個父私鑰或者父公鑰(ECDSA 未壓縮密鑰)
- 一個 256bit 的鏈碼,鏈碼是用來給這個確定性程序引入隨機資料的,以便知道索引編號和子私鑰也不足以派生其他子私鑰,
- 一個 32bit 的索引碼,用于按順序生成相應的子私鑰和子鏈編碼,
-
因為衍生方程是單向方程,所以子密鑰不能被用來發現他們的母密鑰,子密鑰也不能用來發現他們的相同層級的姊妹密鑰,
-
沒有子鏈碼的話,子密鑰也不能用來衍生出任何孫密鑰,你需要同時有子密鑰以及對應的鏈碼才能創建一個新的分支來衍生出孫密鑰,
-
父私鑰-> 子私鑰-> 子公鑰

- 父公鑰-> 子公鑰

擴展密鑰
將密鑰以及鏈碼這兩個重要的部分組合在一起,稱為擴展密鑰(extended key),術語“擴展密鑰”也被認為是“可擴展的密鑰”,因為這種密鑰可以用來派生子密鑰,擴展密鑰可以簡單地表示為將密鑰與鏈碼串聯成的序列并儲存,
-
兩種型別的擴展密鑰:
- 私鑰以及鏈碼組成擴展私鑰,前綴為 xprv,它可用來派生子私鑰(子私鑰可以用來派生子公鑰),
- 公鑰以及鏈碼組成擴展公鑰,前綴為 xpub,它可以用來派生子公鑰
-
擴展公鑰及其應用:
- 部署擴展公鑰可以創造出無限數量的公鑰以及位元幣地址,但是不能花費發送到這個地址里的任何位元幣,與此同時,在另一種更安全的服務器上,擴展私鑰可以衍生出對應的私鑰,簽署交易支付花費,
- 應用一:安裝擴展公鑰在電商的 web 服務器上,web 服務器可以使用公鑰衍生函式去給每一筆交易(比如客戶的購物車)創造一個新的位元幣地址,服務器沒有私鑰,也就避免了被盜的風險,
- 應用二:冷存盤或者硬體錢包,在這種情況下,擴展私鑰可以儲存在紙錢包或者硬體設備中,與此同時擴展公鑰可以在線保存,用戶可以任意創建“收款”地址,而私鑰可以安全地在離線狀態下保存,為了使用資金,用戶可以用擴展私鑰在位元幣錢包中進行離線簽名或者通過硬體錢包設備簽名交易,
-
存在的安全隱患
如果知道某個子私鑰,有可能造成父私鑰泄露,推導如下:
- 兩種子密鑰的派生方式的輸入引數均為父公鑰,父鏈碼,父索引號,導致 512bits 輸出一致,鏈碼(右 256bits)也一致,
- 因為擴展公鑰包含鏈碼以及可生成后代鏈碼,可得左 256bits,
- 根據子私鑰 = 左 256bits + 父私鑰,如果相應子私鑰泄露,則可逆推得到父私鑰,
- 繼續逆推最終可得到已知最早的擴展公鑰所對應的私鑰,
子私鑰強派生

這個強派生函式使用了父私鑰去推導子私鑰,這導致 512bits 輸出以及鏈碼(右 256bits)與派生子公鑰方式生成的不一致,因此無法獲得相應的左 256bits,也就無法倒推出父私鑰,
- 注意:這樣也會導致兩種方式生成的子公鑰也不相同,如果后續使用擴展公鑰的方式作為收款地址,后續派生子私鑰的方式需要為正常派生,但就算后續發生私鑰泄露,最多只會影響到這一分支,
因此強派生也因此被用于密鑰樹中擴展公鑰的上一層以創造“間隙/防火墻”,
為了避免主密鑰泄露,主密鑰所衍生的第一層級的子密鑰總是通過強化衍生得來,
索引碼、密鑰識別符、路徑
-
索引碼
- 常規派生索引碼在 0 和 $2^{31}-1$(0x0 到 0x7FFFFFFF)之間,
- 強派生索引碼在 $2{31}$和$2{32}-1$(0x80000000 到 0xFFFFFFFF)之間,
- 為了讓索引碼更容易被閱讀和顯示,強派生的索引號碼也是從 0 開始展示的,但是右上角有一個小撇號,第一個常規子私鑰因此被表述為 0,但是第一個強化子私鑰(索引號為 0x80000000)就被表示為 0',
-
HD 錢包密鑰識別符(路徑)
- 每個級別之間用斜杠(/)字符來表示,
- 由主私鑰派生出的私鑰起始以“m”打頭,由主公鑰派生的公鑰起始以“M”打頭,
HD path 密鑰描述 m/0 主私鑰(m)衍生的第一個子私鑰(0) m/0/0 第一個子私鑰 (m/0)衍生的第一個子私鑰(0) m/0'/0 第一個強化子私鑰 (m/0')衍生的第一個常規子私鑰(0) m/1/0 第二個子私鑰 (m/1)衍生的第一個子私鑰(0) M/23/17/0/0 第 24 個子公鑰(M/23)衍生的第 18 個子公鑰(M/23/17)的第一個子公鑰(M/23/17/0)的第一個子公鑰(0) -
HD 錢包樹狀結構的導航
BIP-44 指定了包含 5 個預定義樹狀層級的結構:
m / purpose' / coin_type' / account' / change / address_index- 第 1 層的 purpose 總是被設定為 44',
- 第 2 層的“coin_type”特指幣種,允許多貨幣 HD 錢包中的貨幣在第二個層級下有自己的子樹結構,
- 第 3 層是“account”,這允許用戶創建多個獨立的子賬號,便于財務統計或者部門管理,
- 第 4 層是“change”,每一個 HD 錢包在這一層都有兩個子樹,一個用來創建收款地址,另外一個用來創建找零地址,注意無論先前的層級是否使用強派生,這一層級使用的都是常規派生,這是為了允許這一層級的樹可以通過使用擴展公鑰的方式生成下一級的公鑰,
- 被 HD 錢包派生的可用地址是第 4 層級的子級,就是第 5 層級的“address_index”,
HD path Key described M/44'/0'/0'/0/2 位元幣主賬戶的第三個收款公鑰 M/44'/0'/3'/1/14 位元幣第四個賬戶的第十五個找零收款公鑰 m/44'/2'/0'/0/1 Litecoin 主賬戶中的第二個私鑰,用于簽名交易
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/541572.html
標籤:區塊鏈
上一篇:新版以太坊Ethereum庫ethersV5.0配合后端Golang1.18實時鏈接區塊鏈錢包(Metamask/Okc)以及驗簽操作
下一篇:區塊鏈入門 ③ - 交易
