1. 什么是 keystore 文件
以太坊的每个外部账户都是由一对密钥(一个公钥和一个私钥)定义的。账户以地址为索引,地址由公钥衍生而来,取公钥的最后 20个字节。每对私钥 /地址都编码在一个钥匙文件里,也就是我们说的keystore文件。该文件是 JSON 文本文件,可以用任何文本编辑器打开和浏览。钥匙文件的关键部分,账户私钥,通常用你创建帐户时设置的密码进行加密。也就是说 keystore 文件,就是你独有的、用于签署交易的以太坊私钥的加密文件。如果你丢失了这个文件,你就丢失了私钥,意味着你失去了签署交易的能力,意味着你的资金被永久的锁定在了你的账户里。
2. keystore 文件的内容
我们先看一下keystore文件都包含哪些数据:
1 | { |
我们可以看到大部分内容都在 crypto 字段中,这里包括:
- cipher:对称 AES 算法的名称;
- cipherparams:上述 cipher 算法需要的参数;
- ciphertext:你的以太坊私钥使用上述 cipher 算法进行加密;
- kdf:密钥生成函数,用于让你用密码加密 keystore 文件;
- kdfparams:上述 kdf 算法需要的参数;
- Mac:用于验证密码的代码。
3. keystore文件如何工作的?
3.1 加密你的私钥
就像之前提到的,一个以太坊账户就是用于加密签署交易的一个私钥-公钥对。为了确保你的私钥没有在文件中明文存储(即任何人只要能得到这个文件就能读),使用强对称算法(cipher)对其加密至关重要。
这些对称算法使用密钥来加密数据。加密后的数据可以使用相同的方法和同样的密钥来解密,因此算法命名为对称算法。在本文中,我们称这个对称密钥为解密密钥,因为它将用于对我们的以太坊私钥进行解密。
加密过程,如下图:
以下是 cipher,cipherparams 和 ciphertext 对应的概念:
- cipher: 是用于加密以太坊私钥的对称加密算法。此处cipher用的是 aes-128-ctr 加密模式。
- cipherparams: 是 aes-128-ctr 加密算法需要的参数。在这里,用到的唯一的参数 iv,是aes-128-ctr加密算法需要的初始化向量。
- ciphertext: 密文是 aes-128-ctr 函数的加密输入。
在这里,你已经有了进行解密以太坊私钥计算所需要的一切。但是我们首先要取回解密密钥。
3.2 用你的密码来保护它
要确保解锁你的账户很容易,你不需要记住你的每一个又长又非用户友好型的用于解密 ciphertext 密文解密密钥。相反,以太坊开发者选择了基于密码的保护,也就是说你只需要输入密码就能拿回解密密钥。
为了能做到这一点,以太坊用了一个密钥生成函数,输入密码和一系列参数就能计算解密密钥。
这就是 kdf 和 kdfparams 的用途:
- kdf: 是一个密钥生成函数,根据你的密码计算(或者取回)解密密钥。在这里,kdf 用的是scrypt算法。
- kdfparams: 是scrypt函数需要的参数。在这里,简单来说,dklen、n、r、p 和 salt 是 kdf 函数的参数。
在这里,用 kdfparams 参数对 scrypt 函数进行调整,反馈到我们的密码中,你就会得到解密密钥也就是密钥生成函数的输出。
3.3 确认输入的密码是正确的
这就是 keystore 文件中 mac 值起作用的地方。在密钥生成函数执行之后,它的输出(解密密钥)和 ciphertext 密文就被处理,并且和 mac(就像一种认可的印章)作比较。如果结果和 mac 相同,那么密码就是正确的,并且解密就可以开始了。
3.4 将这三步结合起来
首先,你输入了密码,这个密码作为 kdf 密钥生成函数的输入,来计算解密密钥。然后,刚刚计算出的解密密钥和 ciphertext 密文连接并进行处理,和 mac 比较来确保密码是正确的。最后,通过 cipher 对称函数用解密密钥对 ciphertext 密文解密。
就像你从图中可以看到的,整个过程可以看做一个黑盒(不过,图中是个灰盒),你的密码是惟一的输入,你的以太坊私钥是惟一的输出。所需的其他信息都可以在你的以太坊账户创建时生成的keystore文件中获得。