钱包原理——助记词与公私钥
目前錢包分為兩種:
一種是非確定性(隨機)的錢包,就是隨機生成多個私鑰,錢包管理這些私鑰。如果需要成千上萬的地址,通過隨機的方式來生成私鑰,這就需要存儲那么多無規律的私鑰,這樣就很麻煩不好管理。
另一種是確定性(種子)的錢包,就是通過種子可以生成無數的私鑰,我們只需要記住種子就可以了。我們在使用錢包時記住的助記詞可以生成種子,只要我們保管好助記詞,我們的幣就能找回來。用一句話來解釋助記詞:它是私鑰的明文顯示。
主要流程
1、隨機生成128到258位的隨機數,稱作熵;
2、熵經過一定處理方法,生成助記詞;
3、助記詞經過密鑰延伸函數PBKDF2,生成種子;
4、種子經過HMAC-SHA512算法,生成母密鑰;
5、通過CKD(child key derivation)函數,母密鑰生成眾多子密鑰。
從熵到助記詞
1、生成一個128到256位的數字,叫做熵,熵的長度是32的整數倍,分別為 128, 160, 192, 224, 256,也就是我們私鑰的長度。
2、熵通過SHA256哈希得到一個值,取前面的幾位(熵長/32),稱為校驗和, 所以校驗和長度可為 4,5,6,7,8 位。
3、校驗和加入熵的末尾,組成一個新的序列。
4、將新序列以11位為一部分,與已經預先定義2048個單詞的字典做對應。
5、生成的有順序的單詞組就是助記詞。
從助記詞到種子
通過使用密鑰延伸函數PBKDF2,熵被用于導出較長的(512位)種子。
PBKDF2的基本原理是通過一個偽隨機函數(例如HMAC-SHA512函數),把明文和一個鹽值作為輸入參數,然后重復進行運算,并最終產生密鑰。如果重復的次數足夠大,破解的成本就會變得很高。而鹽值的添加也會增加“彩虹表”攻擊的難度。
DK的值由一個以上的block拼接而成。block的數量是dkLen/hLen的值。就是說如果PRF輸出的結果比期望得到的密鑰長度要短,則要通過拼接多個結果以滿足密鑰的長度:
DK = T1 || T2 || … || Tdklen/hlen
而每個block則通過則通過函數F得到:
Ti = F(Password, Salt, c, i)
在函數F里,PRF會進行c次的運算,然后把得到的結果進行異或運算,得到最終的值。
F(Password, Salt, c, i) = U1 ^ U2 ^ … ^ Uc
第一次,PRF會使用Password作為key,Salt作為鹽值進行運算。
U1 = PRF(Password, Salt)
而后續的c-1次則會使用上次得到的結果作為鹽值。
U2 = PRF(Password, U1)
…
Uc = PRF(Password, Uc-1)
這個最終生成的值就是種子。
從種子到母密鑰
種子通過不可逆 HMAC-SHA512 算法推算出 512 位的哈希串,左 256 位是主私鑰Master Private key(m), 右 256 位是主鏈碼 master chain code, 通過 m 結合推導公鑰的橢圓曲線算法能推導出與之對應的 264 位主公鑰master public Key (M)。chain code 作為推導下級密鑰的熵。
子私鑰推導
使用 CKD(child key derivation) 函數從父密鑰(parent keys)推導子密鑰(child keys),CKD 由下列三個要素做單向散列哈希(one way hash function) 。
?父密鑰 (沒有壓縮過的橢圓曲線推導的私鑰或公鑰 ECDSA uncompressed key)
?鏈碼作為熵 (chain code 256 bits)
?子代索引序號 (index 32 bits)
索引號個數為 2 的 32 次方,每個父級密鑰能推導出該數目一半的子密鑰。
索引號從 0x00 到 0x7FFFFFFF (0 to 2 的 21 次方減 1) 會生成正常的密鑰;索引號從 0x80000000 到 0xFFFFFFFF 會生成增強密鑰 )。
通過SHA512哈希生成的字符串,又進一步拆分成左右兩個部分,左部分與父私鑰相加,成為子私鑰;右部分直接作為主鏈碼,用于生成下一級的子私鑰。
CKD 采用不可逆的 HMAC-SHA512 不可逆加密算法,子密鑰不能向上推導出父密鑰、同時也不能水平推導出同一級的密鑰。
擴展密鑰
CKD 推導子密鑰的三個元素中,其中父密鑰和鏈碼結合統稱為擴展密鑰 (Extended keys)。256 位的密鑰和 256 位的鏈碼串聯起來的 512 位就是擴展密鑰。
1.包含私鑰的擴展密鑰用以推導子私鑰,從子私鑰又可推導對應的公鑰和比特幣地址
2.包含公鑰的擴展密鑰用以推導子公鑰
擴展密鑰使用 Base58Check 算法加上特定的前綴編碼,編碼得到的包含私鑰的前綴為 xprv, 包含公鑰的擴展密鑰前綴為 xpub,相比比特幣的公私鑰,擴展密鑰編碼之后得到的長度為 512 或 513 位。
子公鑰推導
上述方法中通過推導出的私鑰可推導出對應公鑰,但在隱藏私鑰的前提下同樣可以通過公鑰推導出子公鑰,極大加強安全性。在只需要生成地址接受比特幣而無權消費的場景下非常有用,通過公鑰擴展密鑰能生成無窮盡的公鑰和比特幣地址。
子私鑰推導流程和子公鑰流程基本一樣,差異之處有兩點:
1.把子私鑰推導過程中私鑰替換為公鑰。
2.子公鑰推導出對應出與之的子鏈碼
增強擴展密鑰推導
密鑰需加強保管以免泄漏,泄漏私鑰意味著對應的地址上的幣可被轉走、泄漏公鑰意味著錢包的隱私被泄漏。增強密鑰推導 (Hardened child key derivation) 解決下述兩個問題:
1.雖然泄漏公鑰并不會導致丟幣,但含有公鑰的擴展密鑰泄漏會導致以此為根節點推導出來的擴展公鑰全部泄漏,一定程度上破壞了隱私性。
2.泄漏擴展公鑰加上該公鑰推導出的后任一代擴展公鑰對應的私鑰有被推導出該擴展公鑰的所有后代私鑰的可能性。
于此,BIP32 協議把 CKD 函數改為 HKD (hardened key derivation formula) 生成增強密鑰推導函數。
CKD 函數以推導擴展密鑰的序列號 ( 0x00 到 0x7FFFFFFF)、父鏈碼和父公鑰生或父私鑰成子鏈碼和子公鑰,子私鑰從父私鑰推導;而 HKD 通過父私鑰、父鏈碼和推導增強擴展密鑰的序列號 (0x80000000 到 0xFFFFFFFF) 增強子私鑰和增強子鏈碼。
總結
以上是生活随笔為你收集整理的钱包原理——助记词与公私钥的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于java财务管理系统(java毕业设
- 下一篇: 工业安全大数据汇聚与治理、2、多模态数据