您好,登錄后才能下訂單哦!
本篇文章為大家展示了如何進行Keystore文件的導入導出,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
將從零開始開發出一個可以實際使用的錢包,這里主要介紹錢包賬號導出與導入,將對Keystore文件的生成的原理進行介紹。
在上一篇文章,介紹了如何使用私鑰及助記詞來創建賬號,如果是使用已有的私鑰及助記詞,這其實也是賬號導入的過程。
有一些同學會問,我的賬號是Geth生成的,如何導入到錢包呢?使用Geth的同學,應該知道Geth在創建賬號時會生成一個對應keystore JSON文件,Keystore文件存儲加密后的私鑰信息,因此我們需要做的就是導入這個Keystore文件,這個文件通常在同步區塊數據的目錄下的keystore文件夾(如: ~/.ethereum/keystore)里。
盡管在ethers.js 中,簡單的使用一個函數就可以完成keystore文件的導入,不過理解Keystore 文件的作用及原理還是非常有必要的,當然如果你是在沒有興趣,可以直接跳到本文最后一節:使用ethers.js 實現賬號導出導入。
通過這篇文章理解開發HD 錢包涉及的 BIP32、BIP44、BIP39,私鑰其實就代表了一個賬號,最簡單的保管賬號的方式就是直接把私鑰保存起來,如果私鑰文件被人盜取,我們的數字資產將洗劫一空。
Keystore 文件就是一種以加密的方式存儲密鑰的文件,這樣的發起交易的時候,先從Keystore 文件是使用密碼解密出私鑰,然后進行簽名交易。這樣做之后就會安全的多,因為只有黑客同時盜取 keystore 文件和密碼才能盜取我們的數字資產。
以太坊是使用對稱加密算法來加密私鑰生成Keystore文件,因此對稱加密秘鑰(注意它其實也是發起交易時需要的解密秘鑰)的選擇就非常關鍵,這個秘鑰是使用KDF算法推導派生而出。因此在完整介紹Keystore 文件如何生成前,有必要先介紹一下KDF。
密碼學KDF(key derivation functions),其作用是通過一個密碼派生出一個或多個秘鑰,即從 password 生成加密用的 key。
其實在理解開發HD 錢包涉及的 BIP32、BIP44、BIP39中介紹助記詞推導出種子的PBKDF2算法就是一種KDF函數,其原理是加鹽以及增加哈希迭代次數。
而在Keystore中,是用的是Scrypt算法,用一個公式來表示的話,派生的Key生成方程為:
DK = Scrypt(salt, dk_len, n, r, p)
其中的 salt 是一段隨機的鹽,dk_len 是輸出的哈希值的長度。n 是 CPU/Memory 開銷值,越高的開銷值,計算就越困難。r 表示塊大小,p 表示并行度。
Litecoin 就使用 scrypt 作為它的 POW 算法
實際使用中,還會加上一個密碼進行計算。
上面已經用KDF算法生成了一個秘鑰,這個秘鑰就是接著進行對稱加密的秘鑰,這里使用的對稱加密算法是 aes-128-ctr,aes-128-ctr 加密算法還需要用到一個參數初始化向量 iv。
好了,我們現在結合具體 Keystore文件的內容,就很容易理解了Keystore 文件怎么產生的了。
{ "address":"856e604698f79cef417aab...", "crypto":{ "cipher":"aes-128-ctr", "ciphertext":"13a3ad2135bef1ff228e399dfc8d7757eb4bb1a81d1b31....", "cipherparams":{ "iv":"92e7468e8625653f85322fb3c..." }, "kdf":"scrypt", "kdfparams":{ "dklen":32, "n":262144, "p":1, "r":8, "salt":"3ca198ce53513ce01bd651aee54b16b6a...." }, "mac":"10423d837830594c18a91097d09b7f2316..." }, "id":"5346bac5-0a6f-4ac6-baba-e2f3ad464f3f", "version":3 }
來解讀一下各個字段:
address: 賬號地址
version: Keystore文件的版本,目前為第3版,也稱為V3 KeyStore。
id : uuid
crypto: 加密推倒的相關配置.
cipher 是用于加密以太坊私鑰的對稱加密算法。用的是 aes-128-ctr 。
cipherparams 是 aes-128-ctr 加密算法需要的參數。在這里,用到的唯一的參數 iv。
ciphertext 是加密算法輸出的密文,也是將來解密時的需要的輸入。
kdf: 指定使用哪一個算法,這里使用的是 scrypt。
kdfparams: scrypt函數需要的參數
mac: 用來校驗密碼的正確性, mac= sha3(DK[16:32], ciphertext) 下面一個小節單獨分析。
我們來完整梳理一下 Keystore 文件的產生:
使用scrypt函數 (根據密碼 和 相應的參數) 生成秘鑰
使用上一步生成的秘鑰 + 賬號私鑰 + 參數 進行對稱加密。
把相關的參數 和 輸出的密文 保存為以上格式的 JSON 文件
當我們在使用Keystore文件來還原私鑰時,依然是使用kdf生成一個秘鑰,然后用秘鑰對ciphertext進行解密。
此時細心的同學會發現,無論使用說明密碼,來進行這個操作,都會生成一個私鑰,但是最終計算的以太坊私鑰到底是不是正確的,卻不得而知。
這就是 keystore 文件中 mac 值的作用。mac 值是 kdf輸出 和 ciphertext 密文進行SHA3-256運算的結果,顯然密碼不同,計算的mac 值也不同,因此可以用來檢驗密碼的正確性。
現在我們以解密的角度完整的梳理下流程,就可以得到以下圖:
ethers.js 直接提供了加載keystore JSON來創建錢包對象以及加密生成keystore文件的方法,方法如下:
// 導入keystore Json ethers.Wallet.fromEncryptedJson(json, password, [progressCallback]).then(function(wallet) { // wallet }); // 使用錢包對象 導出keystore Json wallet.encrypt(pwd, [progressCallback].then(function(json) { // 保存json });
現在結合界面來完整的實現賬號導出及導入,先看看導出,UI圖如下:
HTML 代碼如下:
<h4>KeyStore 導出:</h4> <table> <tr> <th>密碼:</th> <td><input type="text" placeholder="(password)" id="save-keystore-file-pwd" /></td> </tr> <tr> <td> </td> <td> <div id="save-keystore" class="submit">導出</div> </td> </tr> </table>
上面主要定義了一個密碼輸入框和一個導出按鈕,點擊“導出”后,處理邏輯代碼如下:
// "導出" 按鈕,執行exportKeystore函數 $('#save-keystore').click(exportKeystore); exportKeystore: function() { // 獲取密碼 var pwd = $('#save-keystore-file-pwd'); // wallet 是上一篇文章中生成的錢包對象 wallet.encrypt(pwd.val()).then(function(json) { var blob = new Blob([json], {type: "text/plain;charset=utf-8"}); // 使用了FileSaver.js 進行文件保存 saveAs(blob, "keystore.json"); }); }
FileSaver.js 是可以用來在頁面保存文件的一個庫。
再來看看導入keystore 文件, UI圖如下:
<h3>加載賬號Keystore文件</h3> <table> <tr> <th>Keystore:</th> <td><div class="file" id="select-wallet-drop">把Json文件拖動到這里</div><input type="file" id="select-wallet-file" /></td> </tr> <tr> <th>密碼:</th> <td><input type="password" placeholder="(password)" id="select-wallet-password" /></td> </tr> <tr> <td> </td> <td> <div id="select-submit-wallet" class="submit disable">解密</div> </td> </tr> </table>
上面主要定義了一個文件輸入框、一個密碼輸入框及一個“解密“按鈕,因此處理邏輯包含兩部分,一是讀取文件,二是解析加載賬號,關鍵代碼如下:
// 使用FileReader讀取文件, var fileReader = new FileReader(); fileReader.onload = function(e) { var json = e.target.result; // 從加載 ethers.Wallet.fromEncryptedJson(json, password).then(function(wallet) { }, function(error) { }); }; fileReader.readAsText(inputFile.files[0]);
上述內容就是如何進行Keystore文件的導入導出,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。