本文首发于深刻浅出区块链社区 原文连接:使用 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多位区块链技术爱好者一块儿交流。