[C#] Ethereum 以太坊產生高清錢包 (HD Wallet)

2021-10-27

最近在弄一些東西,這篇來產一下以太坊 ( Ethereum ) 的高清錢包( HD Wallet )

我發現我之前有寫過比特幣的高清錢包  手把手來玩比特幣 (Bitcoin) - 製作高清錢包

這一篇來產一下 Ethereum  的高清錢包,加上如何產出可以匯入到 Metamask 的 JSON file. 




1. 首先,引入一個 library  Nethereum.HdWallet  



2. 接下來就是 code 的部分,在 new Wallet 的時候放入的 words 這字串是要用 空白隔開的單字,只是因為我是用中文,所以就是 24 個中文字。

public static Nethereum.Web3.Accounts.Account GetHDWalletInfoByIndex(string words, string password, int index) { return new Wallet(words, password).GetAccount(index); } var words = "會不會有人知道當麻在這個孤獨的星球曾這樣的活過過"; var password = "password"; for (var index = 0; index &lt;= 10; index++) { var walletAccount = GetHDWalletInfoByIndex(string.Join(" ", words.ToArray()), password, index); Response.Write("編號:" + index + " , 錢包位置:" + walletAccount.Address + " ,私鑰:" + walletAccount.PrivateKey ); Response.Write("<br>"); }

所以在傳入之前,我是先把中文 24 個字用空白隔開,所以你看其他範例應該可能會是 "word1 word2 ... word24"
Result:
編號:0 , 錢包位置:0x8980559aE8B41b04D46654041A36881Ca39f8adF,私鑰:0x8ca224fec50afaffc70e445ae2d01434e666268298548f67597068735562ad10 編號:1 , 錢包位置:0x75aE99b77B9cea5848eCFa6e0F982DfC7c2af07d,私鑰:0xcf893594f8c20fc51ec5452169be4691e58f9abe624ba803c95692d5514c08d6 編號:2 , 錢包位置:0xe0d4657211F5C252EDbD4BEcb0883df20bB206DB,私鑰:0x02f49fd0f312f53a35e092f9da6329374acfdbe45bfb8c32de2f4fe3943e90d7 編號:3 , 錢包位置:0x36E8b19A90e20fa3c66Ce37DE708943db4D3c8F8,私鑰:0x018fe3b25668c393bbc4953ef9f8e22201e769f422f6493049b0cafb0c2d2fde 編號:4 , 錢包位置:0x26146021F293B2216EcC009029Df601642d99755,私鑰:0x3881ed87be2ec87069466cd4316087828e0712e592965eaed83ed84fde26dbb0 編號:5 , 錢包位置:0xAfC3f84aA12713003e7Ad7E054e44be3fCAd2f5b,私鑰:0x6984206e9e1af8090a120774fd657d88b278f8bde685ef8532dabe9d61f557bc 編號:6 , 錢包位置:0x4132260bA1cB451B4Efb65FbEF63bacBf7e287ce,私鑰:0xa93e86896010eabb2dbbdf788cb183630ab3391c85f16e3dacc9beb53faef911 編號:7 , 錢包位置:0x0E285c3F18A1181Cc81901973Bf0806Aa7c013Fc,私鑰:0x1d7617dcc35e942710b495764681279a19caf5c9c26d824cf093b9162ccef608 編號:8 , 錢包位置:0x119196a780A372F1CE6016918aF4951a5a749B0B,私鑰:0x65da4a4e30a8174388d97650869ab6c88f0ff539b1d5f66c369f1554fd5ba01f 編號:9 , 錢包位置:0xCC648a8424Fad9a2E9Cd2F82fCe48F894b8ab663,私鑰:0x010e0f160a3c8f3f891858d29dceecedccede8d87a6d29e164d2f42cfc0c1aee 編號:10 , 錢包位置:0xA152c004dE276D0BAb6662A54B6A8C41B66A1A5E,私鑰:0xfc76bc0ac79f66c982a638b6eeff6c60bad9f5e554394b3f140a281cb3317fb0

3. 轉換成 JSON ,其實你拿上面的 result , 你直接複製 privatekey 去 貼在 metamask 中,你也可以成功匯入



不過還有一種作法,就是匯入 json file 檔案,然後輸入密碼來匯入



C# Code :

public static string ConvertWalletToJson(Nethereum.Web3.Accounts.Account walletInfo,string password) { var keyBytes = Enumerable.Range(0, walletInfo.PrivateKey.Substring(walletInfo.PrivateKey.Length - 64).Length) .Where(x =&gt; x % 2 == 0) .Select(x =&gt; Convert.ToByte(walletInfo.PrivateKey.Substring(walletInfo.PrivateKey.Length - 64).Substring(x, 2), 16)) .ToArray(); return new Nethereum.KeyStore.KeyStoreService().EncryptAndGenerateDefaultKeyStoreAsJson(password, keyBytes, walletInfo.Address); } var walletAccount2 = GetHDWalletInfoByIndex(string.Join(" ", words.ToArray()), password, 2); Response.Write(ConvertWalletToJson(walletAccount2,password));

Result:
{ "crypto": { "cipher": "aes-128-ctr", "ciphertext": "bb544dd9df5f310c0b8394209765553e6d0418c251332efe4ac0264c1e1ec1bf", "cipherparams": { "iv": "6f21602b3e6dcd423e5069a6383eab5b" }, "kdf": "scrypt", "mac": "00a9bf7e67bdfd32d6ee50f2f2b00979a2422ee996708c7e929d48b6ccf609f7", "kdfparams": { "n": 262144, "r": 1, "p": 8, "dklen": 32, "salt": "72bec0fdeeb22dd7d9c47678fb473b0f1ed1e0057c7451f5cbac064d919ad2d4" } }, "id": "cf8a3d29-e87a-4a41-9898-008489b0e4c3", "address": "0xe0d4657211F5C252EDbD4BEcb0883df20bB206DB", "version": 3 }



總結一下,為何乙太跟比特不一樣不能合併打包打款為何還要 HD 錢包呢,其實主要就是 "方便管理" ,因為你的助記詞密碼就只會有一組

然後產出的錢包本身只有 privatekey 要保存,而且只要記住助記詞跟密碼都可以在把錢包推回來。不過不代表你資料庫可以不要記錄錢包只記錄index 

其實,推的速度蠻慢的,所以囉,建議就是 預產=>分配=>查詢 ,看懂的就知道我在說啥..

reference :


當麻許的超技八 2014 | Donma Hsu Design.