本文首發於深刻淺出區塊鏈社區 原文連接:使用 ethers.js 開發以太坊 Web 錢包 2 - 帳號 Keystore 文件導入導出) 原文已更新,請讀者前往原文閱讀html
以太坊去中心化網頁錢包開發系列,將從零開始開發出一個能夠實際使用的錢包,本系列文章是理論與實戰相結合,一共有四篇:建立錢包帳號、帳號Keystore文件導入導出、展現錢包信息及發起簽名交易、發送Token(代幣),這是第二篇,主要介紹錢包帳號導出與導入,將對Keystore文件的生成的原理進行介紹。git
在上一篇文章,介紹瞭如何使用私鑰及助記詞來建立帳號,若是是使用已有的私鑰及助記詞,這其實也是帳號導入的過程。github
有一些同窗會問,個人帳號是Geth生成的,如何導入到錢包呢?使用Geth的同窗,應該知道Geth在建立帳號時會生成一個對應keystore JSON文件,Keystore文件存儲加密後的私鑰信息,所以咱們須要作的就是導入這個Keystore文件,這個文件一般在同步區塊數據的目錄下的keystore文件夾(如: ~/.ethereum/keystore)裏。web
儘管在ethers.js 中,簡單的使用一個函數就能夠完成keystore文件的導入,不過理解Keystore 文件的做用及原理仍是很是有必要的,固然若是你是在沒有興趣,能夠直接跳到本文最後一節:使用ethers.js 實現帳號導出導入。算法
經過這篇文章理解開發HD 錢包涉及的 BIP3二、BIP4四、BIP39,私鑰其實就表明了一個帳號,最簡單的保管帳號的方式就是直接把私鑰保存起來,若是私鑰文件被人盜取,咱們的數字資產將洗劫一空。json
Keystore 文件就是一種以加密的方式存儲密鑰的文件,這樣的發起交易的時候,先從Keystore 文件是使用密碼解密出私鑰,而後進行簽名交易。這樣作以後就會安全的多,由於只有黑客同時盜取 keystore 文件和密碼才能盜取咱們的數字資產。安全
以太坊是使用對稱加密算法來加密私鑰生成Keystore文件,所以對稱加密祕鑰(注意它其實也是發起交易時須要的解密祕鑰)的選擇就很是關鍵,這個祕鑰是使用KDF算法推導派生而出。所以在完整介紹Keystore 文件如何生成前,有必要先介紹一下KDF。bash
密碼學KDF(key derivation functions),其做用是經過一個密碼派生出一個或多個祕鑰,即從 password 生成加密用的 key。微信
其實在理解開發HD 錢包涉及的 BIP3二、BIP4四、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
}
複製代碼
來解讀一下各個字段:
咱們來完整梳理一下 Keystore 文件的產生:
當咱們在使用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 代碼以下:
<h3>KeyStore 導出:</h3>
<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圖以下:
<h2>加載帳號Keystore文件</h2>
<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]);
複製代碼
完整源碼請訂閱深刻淺出區塊鏈技術小專欄查看, 哈哈,是否是有一點雞賊,創做不易呀。 戳連接收看詳細的視頻課程講解。
參考文檔: ethers.js
深刻淺出區塊鏈 - 系統學習區塊鏈,打造最好的區塊鏈技術博客。
深刻淺出區塊鏈知識星球最專業技術問答社區,加入社區還能夠在微信羣裏和300多位區塊鏈技術愛好者一塊兒交流。