我们都知道, 在区块链的世界中, 私钥是你有用某一地址的唯一标识丢失了私钥就等于丢失了此地址的所有权
以太坊私钥存储
以太坊的私钥文件存储于数据目录 (datadir 指向或默认目录) 下, 对应的目录为 keystore 所有的私钥文件都经过加密之后存储于此目录下
以太坊的客户端或图形界面帮助我们因此了底层复杂的密码实现, 唯一需要我们做的就是保存好(多出备份)keystore 下面的加密私钥文件和加密的密码否则, 有可能失去辛苦挖来的以太币或花钱购买来的以太币
记住, 永远不要犯的错误: 丢失 keystore 文件或忘记密码!
以太坊创建账户
以太坊创建账户的操作非常简单, 但有不同的展现形式以 geth 客户端为例
command 命令方式
- bogon:geth zzs$ ./geth account new
- Your new account is locked with a password. Please give a password. Do not forget this password.
- Passphrase:
- Repeat passphrase:
- Address: {0f7b73f3034d0d17a165e4cf50bd77051235b4e6}
- bogon:geth zzs$ ./geth account list
- Account #0: {0f7b73f3034d0d17a165e4cf50bd77051235b4e6} keystore:///Users/zzs/Library/Ethereum/keystore/UTC--2018-02-21T02-56-46.285140000Z--0f7b73f3034d0d17a165e4cf50bd77051235b4e6
- bogon:geth zzs$
以上操作是直接执行 geth 客户端的命令 (command) 来创建账户和展示账户私钥文件信息创建过程中需要两次输入对私钥加密的密码此种方式的好处是不需要单独启动 geth 节点即可创建完成账户
console 命令方式
此种方式需先启动 geth 节点, 并进入 console 命令行交互界面然后执行以下命令:
- > personal.newAccount("123456")
- "0x00fe1b8a035b5c5e42249627ea62f75e5a071cb3"
- // 或
- > personal.newAccount()
- Passphrase:
- Repeat passphrase:
- "0x6a787f16c2037826fbc112c337d7b571bb19c022"
通过 personal 角色来管理和创建新账号, 并设置密码
keystore 文件
keystore 文件是你独有的, 用于签名交易的以太坊私钥的加密文件一旦丢失文件或加密密码就意味着你失去了此地址发起交易签名交易的特权, 账户里面的资金将永远被锁
keystore 文件存在的价值就是以加密的方式存储密钥, 同时在使用的时候只需要提供 keystore 文件和对应的密码即可发起交易安全性与可用性达到了完美的平衡
但是, 我们需要注意的是一旦用密码对加密文件进行解锁之后, 在有效时间内通一个客户端下, 你可以发起交易, 如果别人可以访问你的客户端, 同样也可以发起交易在网络安全不足的情况下, 这是被盗币的场景之一
秘钥文件内容
秘钥文件为文本文件, 可以使用任何文本编辑器或浏览器打开
- bogon:keystore zzs$ cat UTC--2018-02-21T03-01-27.385349000Z--6a787f16c2037826fbc112c337d7b571bb19c022
- {
- "address": "6a787f16c2037826fbc112c337d7b571bb19c022",
- "crypto": {
- "cipher": "aes-128-ctr",
- "ciphertext": "8ed39b22ab67a787baa4ebb545382255f747328e2a3e2e74970a0f66b422d169",
- "cipherparams": {
- "iv": "8e0e0905919d6d1669957fdf65f114ce"
- },
- "kdf": "scrypt",
- "kdfparams": {
- "dklen": 32,
- "n": 262144,
- "p": 1,
- "r": 8,
- "salt": "a2a84d4843dbcb7c0aefa933f37ead073aefe8503ac8497b77828e85467c6822"
- },
- "mac": "1fc4a5d260fdd70e772fdc9a28614e82d5ff0adc6c98332f8455c5aa0a3352ad"
- },
- "id": "7bce1a69-79a2-429a-836c-cc2bf72c80de",
- "version": 3
- }
通过文件中的内容, 我们能看到的是一个 json 字符串, 里面包含了此秘钥对应的地址和加密相关的一些信息
cipher: 加密算法, 对称加密, AES 算法, 用于加密以太坊私钥;
cipherparams:cipher 算法需要的参数, 参数 iv, 是 aes-128-ctr 加密算法需要的初始化向量;
ciphertext: 加密后的密文, aes-128-ctr 函数的加密输入密文;
kdf: 秘钥生成函数, 用于使用密码加密 keystore 文件;
kdfparams:kdf 算法所需要的参数;
mac: 验证密码的编码;
原理解析
加密秘钥
一个以太坊账户是由一对公私钥对构成, 并使用强对称算法 (cipher) 进行加密
我们看一下具体的流程图 ciphertex 密文的对称解密:
客户端读取密钥文件和加密密码, 对私钥进行解密, 然后使用私钥对发送的交易进行签名
密码保护
以太坊使用基于密码保护的机制来解密密钥这样用户就不需要记住一串非用户友好的密码为了达到此效果, 以太坊使用密钥生成函数, 根据输入的密码和一系列参数就能计算解密密钥
这就涉及到 kdf 和 kdfparams 的用途:
kdf 是一个密钥生成函数, 根据密码计算 (或者取回) 解密密钥 kdf 用的是 scrypt 算法
kdfparams 是 scrypt 函数需要的参数更多的参数可以参考: https://tools.ietf.org/html/rfc7914
用 kdfparams 参数对 scrypt 函数进行调整, 反馈密码中, 得到解密密钥, 也就是密钥生成函数的输出
错误密码
当输入错误密码时, 密码派生和解密等操作都会成功, 但最终计算所得的以太坊私钥不是正确的, 因此无法进行解锁账户的操作
keystore 文件中 mac 值起作用的地方在密钥生成函数执行之后, 它的输出 (解密密钥) 和 ciphertext 密文就被处理, 并且和 mac(类似于数据签名)作比较如果结果和 mac 相同, 那么密码就是正确的, 可以开始解密操作
在和 mac 进行比较之前, 需要解密密钥 (左起第二字节开始的 16 字节) 要和 ciphertext * 密文连接在一起, 并进行哈希散列(用 SHA3-256 的方法)
流程回顾
输入密码, 密码作为 kdf 密钥生成函数的输入, 计算解密密钥用解密密钥和 ciphertext 密文连接并进行处理, 和 mac 比较确保密码正确最后, 通过 cipher 对称函数用解密密钥对 ciphertext 密文解密
来源: https://mp.weixin.qq.com/s/HXMr-noheDxkulsRyH-xMQ