# 助記詞掉了如何找回？以Tezos為例子

By [kweiwen](https://paragraph.com/@kweiwen) · 2022-04-17

---

### 揳子

如果你常在區塊鏈的世界衝浪，肯定會有一個抱團取暖的社團分享訊息，每當夥伴分享區塊鏈社會事件，如暴力討債、礦場偷電、名人錢包被盜事件⋯⋯往往是見怪不鮮不能引起你的共鳴，但看到夥伴們錢包被盜的事情，肯定會令大家豎直椅背開始團購冷錢包，或是把電腦、手機的助記詞刪除改用紙質筆記本。

隊友聽我分享完點頭如搗蒜，隨即把所有數位的痕跡都抹除，並將錢包的助記詞抄送在紙質筆記本上，然而隊友不諳區塊鏈的基礎知識，只抄送了11位助記詞！找尋那遺失的1位的過程正是本文要分享的。

### 確認可能性並使用程式計算遺失的那一位

硬幹程式之前，必須先確認規格，才能衡量這個硬幹的可能性，Tezos如其他熱門的加密貨幣，如：Ether、Bitcoin一樣，使用BIP39的規格設計助記詞，這裡有一些重點幫大家濃縮：

1.  助記詞其實就是由2048個不同的單字組成，每一個單字對應一個二進制號碼，從`0x00000000000`到`0x11111111111`，對整個表格有興趣請移駕[這裡](https://github.com/bitcoin/bips/blob/master/bip-0039/english.txt)。
    
2.  首四位不會重複，如：642號expand與643號expect只有三位重複，為的是避免助記詞在抄送的過程中出現筆誤的現象。
    
3.  支援多種語言，如：英文、日文、韓文、西班牙文、簡體中文、繁體中文、法文、義大利文、捷克文、葡萄牙文都可以有助記詞，但目前大多數錢包都是使用英文助記詞。
    

透過以上的推理，只需要從表格中取1個助記詞跟11位已知的助記詞進行排列組合後生成『錢包地址』，再拿這個『錢包地址』跟自己的『錢包地址』進行比對就能知道答案了，於是我就寫了一段Python程式：

    from pytezos.crypto.key import Key
    from mnemonic import Mnemonic
    import numpy as np
    
    incomplete_words = [...]
    target_address = "tz1..."
    size = len(Mnemonic(LANGUAGE).wordlist)
    
    for position in range(12):
      print("======")
      print(position)
      for index in range(size):
    
        # pick one from world list vector
        variable = Mnemonic(LANGUAGE).wordlist[index]
        
        # insert above to an incomplete seed phrase array
        input_data = np.insert(incomplete_words, position, variable)
    
        # as string format
        input_data_str = ' '.join(input_data)
        try:
          sk = Key.from_mnemonic(mnemonic=input_data_str)
          if(sk.public_key_hash() == target_address):
            print(position, index, input_data)
        except Exception as e:      
          pass
    

但以上方法但始終找不到正確的地址。

後來翻了一下BIP44的規格，發現常用的瀏覽器錢包插件如：MetaMask、Temple Wallet、Kukai Wallet都是HD Wallet的一種，必須了解HD Wallet的設計原理才能進一步解決問題。

### HD Wallet跟你想的不一樣

我們熟知的區塊鏈基礎知識中，一組助記詞可以推導出一組『私鑰』，再用『私鑰』推導出一組『公鑰』，而『公鑰』可以推導出『公鑰哈希』和『錢包地址』，以上推導是單向的，無法反向算出源頭。雖然這樣的構想很棒，但遇到組織架構如：企業、去中心化組織就會遇到：

*   多人管理一個助記詞很難去歸因資產的管理責任
    
*   人員調動、組織擴時充管理權限無法更新
    

在BIP44的規格被提出來之後：

*   『私鑰』用有者視同一個節點，可以再去派生子節點
    
*   派生採用階層式的架構（見下圖），可以擁有無限層
    
*   父節點的『私鑰』擁有者透過派生的機制可以推導出所有的子節點，因此可以向下管理所有子節點的資產
    
*   反之子節點的擁有者，只能去派生更下一層的節點，且子節點不能推導回父節點
    

![Hierarchical Deterministic Wallets aka HD Wallet](https://storage.googleapis.com/papyrus_images/88077c021c2b59dc9d8318917477e6d5837fc96c42a5b68e6d550d4e96a93be7.png)

Hierarchical Deterministic Wallets aka HD Wallet

透過以上特性，最大的受益者肯定是組織架構，這讓他們能夠方便管理區塊鏈資產，但同時又保留了區塊鏈加密的特性。

### 回到問題本身

原先的Python程式碼只要修改以下兩點就好了：

*   取代Key物件，改用HD Wallet Key物件
    
*   使用派生產生『私鑰』，再產生『錢包地址』
    

    from pytezos.crypto.key import Key
    from mnemonic import Mnemonic
    import numpy as np
    
    incomplete_words = [...]
    target_address = "tz1..."
    size = len(Mnemonic(LANGUAGE).wordlist)
    
    for position in range(12):
      print("======")
      print(position)
      for index in range(size):
    
        # pick one from world list vector
        variable = Mnemonic(LANGUAGE).wordlist[index]
        
        # insert above to an incomplete seed phrase array
        input_data = np.insert(incomplete_words, position, variable)
    
        # as string format
        input_data_str = ' '.join(input_data)
        try:
          hdKey = HDKey.from_mnemonic(mnemonic=input_data_str)
          sk = hdKey.derive("m/44/1729/0/0")
          if(sk.public_key_hash() == target_address):
            print(position, index, input_data)
        except Exception as e:      
          pass
    

但很可惜以上程式碼不能成功執行，因為`pytezos`還沒支援`HDKey`物件，所以要改用C#與`netezos`，這邊不囉唆直接上C#程式碼。

    using System;
    using Netezos.Keys;
    using System.Collections.Generic;
    using System.Linq;
    
    string[] lines = System.IO.File.ReadAllLines(@"english.txt");
    
    namespace ConsoleApp
    {
        internal class Program
        {
            static void Main(string[] args)
            {
                var target_address = "tz1..."
    
                for (int i = 0; i < 12; i++)
                {
                    Console.WriteLine("Current Index: ", i);
                    foreach (string line in lines)
                    {
                        var words = new List<string> { ... };
                        words.Insert(i, line);
                        var mnemonic = new Mnemonic(words);
                        var key = HDKey.FromMnemonic(mnemonic, "", ECKind.Ed25519);
                        var firstchild = key.Derive("m/44'/1729'/0'/0'");
                        if (firstchild.Address == target_address)
                        {
                            Console.WriteLine("");
                            Console.WriteLine(line);
                            Console.WriteLine(firstchild.Address);
                        }
                    }
                }
            }
        }
    }
    

### 再聊聊組織架構

透過理解BIP44也窺探了組織是怎麼管理區塊鏈資產的，看看Binance在鍊上精美且龐大的資產。

![https://tzkt.io/tz1S8MNvuFEUsWgjHvi3AxibRBf388NhT1q2/operations/](https://storage.googleapis.com/papyrus_images/6335c3be110830d02c0a4e505130c53792efb099519cbc77239bb9fc6258c5d4.png)

https://tzkt.io/tz1S8MNvuFEUsWgjHvi3AxibRBf388NhT1q2/operations/

而且不只一個Binance帳號在鏈上活躍著，到底他們是怎麼管理多個帳號，而安全性又在哪裡？這時候新的問題是，實務上如何讓多人管理鏈上資產呢？一些解決方案提供商提出一些想法，不外乎：

*   分散式的管理
    
    1.  操作者用**工具**進行操作，而不用錢包操作（因為錢包操作者等同擁有錢包的權限）
        
    2.  權限保管者擁有的是產生『私鑰』的某一環，可以是一段能生成助記詞的**工具**，且權限保管者看不到工具生成的結果，他的操作等同於蓋章
        
    3.  **工具**由開發者開發，且角色和操作者、權限保管者分開
        
*   尋找外包，讓方案提供商負責安全上的問題
    

### 結尾

今天的情況比較幸運，所以助記詞在3分鐘內使用ThinkPad T14s筆電很快就算出來了。倘若少了2位註記詞，可能就會需要耗費3分鐘的平方，也就是9個小時，此外助記詞若是順序有問題，使用以上暴力破解想找回助記詞幾乎不可行，最後祝大家都能找回助記詞。

### Reference

*   [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki)
    
*   [https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki)
    
*   [https://github.com/baking-bad/netezos/blob/master/docs/docs/wallet-import.md](https://github.com/baking-bad/netezos/blob/master/docs/docs/wallet-import.md)
    
*   [https://pytezos.baking-bad.org/](https://pytezos.baking-bad.org/)
    
*   [https://www.riddleandcode.com/blog-posts/what-makes-a-crypto-asset-custodial-solution-right-for-you](https://www.riddleandcode.com/blog-posts/what-makes-a-crypto-asset-custodial-solution-right-for-you)
    
*   [https://www.qredo.com/blog/what-to-look-for-in-a-crypto-treasury-management-solution](https://www.qredo.com/blog/what-to-look-for-in-a-crypto-treasury-management-solution)

---

*Originally published on [kweiwen](https://paragraph.com/@kweiwen/tezos)*
