原理
-
私钥、公钥和地址的产生方法,这是区块链的相关知识
-
如何使用API进行远程调用等基础概念,这是传统IT行业相关知识
-
钱包设计相关的助记词(mnemonic),keystore和密码的相关概念,它和区块链公钥、私钥和地址产生的方式思路一样,但是整个过程属于区块链钱包设计过程,不能与区块链的相关知识混淆
解答
一、 私钥、公钥和地址产生的方式(以 BTC 为例):
- 比特币私钥其实是使用 SHA-256 生成的 32 字节(256 位)的随机数,有效私钥的范围则取决于比特币使用的 secp256k1 椭圆曲线数字签名标准。
- 在私钥的前面加上版本号,后面添加压缩标志和附加校验码,(所谓附加校验码,就是对私钥经过 2 次 SHA-256 运算,取两次哈希结果的前四字节),然后再对其进行 Base58 编码,就可以得到我们常见的 WIF (Wallet import Format) 格式的私钥。
- 私钥经过椭圆曲线乘法运算,可以得到公钥。公钥是椭圆曲线上的点,并具有 x 和 y 坐标。公钥有两种形式:压缩的与非压缩的。早期比特币均使用非压缩公钥,现在大部分客户端默认使用压缩公钥。
从私钥推导出公钥、再从公钥推导出公钥哈希都是单向的,也就是采用不可逆算法。
椭圆曲线算法
- 值通过 RIPEMD-160 算法来得到 20 字节的哈希值 ——Hash160
- 把版本号 [2]+Hash160 组成的 21 字节数组进行双次 SHA256 哈希运算,得到的哈希值的头 4 个字节作为校验和,放置 21 字节数组的末尾。
- 对组成 25 位数组进行 Base58 编码,最后得到地址。
二、远程过程调用 (RemoteProcedure Call, RPC)
它是一个计算机通信协议。该协议允许运行于一台计算机的程序调用另一台计算机的子程序,而程序员无需额外地为这个交互作用编程。RPC 的主要功能目标是让构建分布式计算(应用)更容易,在提供强大的远程调用能力时不损失本地调用的语义简洁性。广为使用的是一个叫做 JSON (JavaScript Object Notation)- RPC 的协议。所以钱包都是通过某个区块链 RPC 接口调用来和区块链网络进行交互。
三、助记词相关
助记词规则
- 生成一个长度为 128~256 位 (bits) 的随机序列 (熵);
- 取熵哈希后的前 n 位作为校验和 (n= 熵长度 /32);
- 随机序列+校验和;
- 把步骤 3 得到的结果每 11 位切割;
- 步骤 4 得到的每 11 位字节匹配词库的一个词;
- 步骤 5 得到的结果就是助记词串;
根据密钥之间是否有关联可把钱包分为两类:nondeterministic wallet 和 deterministic wallet。
nondeterministic wallet:密钥对之间没有关联;
deterministic wallet: 密钥对由一个原始的种子主密钥推导而来。最常见的推导方式是树状层级推导
(hierarchical deterministic) 简称 HD。
通过助记词生成种子
助记词由长度为 128 到 256 位的随机序列 (熵) 匹配词库而来,随后采用 PBKDF2 function 推导出更长的种子 (seed)。生成的种子被用来生成构建 deterministic Wallet 和推导钱包密钥。
在密码学中,Key stretching 技术被用来增强弱密钥的安全性,增加了暴力破解 (Brute-force attack) 对每个可能密钥尝试攻破的时间,增强了攻击难度。各种编程语言原生库都提供了 key stretching 的实现。PBKDF2(Password-Based Key Derivation Function 2) 是常用的 key stretching 算法中的一种。基本原理是通过一个为随机函数 (例如 HMAC 函数),把明文和盐值作为输入参数,然后重复进行运算最终产生密钥。
-
助记词句子作为密码;
-
“mnemonic” + passphrase 作为盐;
-
2048 作为重复计算的次数+HMAC-SHA512 作为随机算法 , 最终得到 BIP32 种子,512 位 (64 字节) 是期望得到的密钥长度;
同时钱包还提供了 keystore 和密码基本功能
用户最好的体验仍然会是密码方式,所以钱包还提供了 keystore 让用户导出保存,这个 Keystore 也是私钥经过加密过后的一个文件,需要你自己设置的密码才能打开文件。这样的好处是就算 keystore 文件被盗,只要你额外设置的密码够长够随机,那么短时间内私钥也不会泄露,有充足的时间转移地址里面的加密货币到其他地址。Keystore 会存储在使用的设备里,这样每次登陆只用输入相应密码即可。
助记词相关:
私钥 = 算法1(助记词)
公钥 = 算法2(私钥)
公钥hash = 算法3(公钥)
地址 = 算法4(公钥hash)
所以
地址 = 算法4(算法3(算法2(算法1(助记词))))
其中算法1、2、3、4都是公开的
钱包的核心
打开钱包主要有一下几种方式:
- 私钥(privatekey)
- keystore+密码(keystore+password)
- 助记词(mnemonic code)
Tips
一个简单的H2以太坊钱包的实现。https://github.com/w1ndyz/h2-wallet