区块链钱包的基本类型和特点以及工作原理介绍
扫描二维码
随时随地手机看文章
大家刚开始使用钱包的时候都会被助记词、Keystore、私钥、地址、公钥等各种概念搞得云里雾里,这些概念和传统世界的银行卡和密码简单的两个概念完全不一样,只能按照钱包软件的提示需要怎么做就怎么做,却无法知道缘由,有点儿死背书的感觉,本篇的主旨就是帮大家捋一捋:作为一款区块链钱包,是如何工作的,如何生成密钥、助记词、Keystore等。先把结论置顶:
区块链钱包实现的技术原理用一句话表示就是:钱包助记词生成了种子(Seed),种子(Seed)生成了私钥,私钥推导出公钥,公钥节选部分成了钱包地址。同时钱包提供了keystore,它也是私钥加密后的文件,可以配合正常的密码使用,便捷了用户的钱包使用。
区块链的诞生,不仅仅是通过代码和智能合约来将生产组织进一步扁平化,从而达到优化中间过程、精简中介的作用,更是产生了一个新的经济模式,创建了一种新的生产关系,这种理念上的变革远远大于技术本身带来的影响,它最让人着迷的地方莫过于利用人性的特点,建立的一套自治的经济激励机制,并诞生了一个新型的价值载体cryptocurrency(笔者习惯区分Coin和Token,可参见文章区块链基础概念 - 理解COIN和TOKEN)。
Cryptocurrency显然不同于传统的货币,它是通过一定的加密算法计算出来的数字货币,也就是说电子化会是它的本质属性,这样它的存储问题就会是一个热门的研究领域,具体来讲就是我们常说的区块链钱包。当然,这里需要强调的是,区块链钱包并不是存储着大家的cryptocurrency,它是在链上存储的,钱包主要存储的是私钥,它是用户对链上cryptocurrency的所有权凭证,这是一个不记名、不可挂失的凭证。从开发者的角度看,钱包的作用就是管理用户的私钥、通过私钥签名交易管理用户在区块链上的数字货币Cryptocurrency Address + Private key = Cryptocurrency Wallet。
以上属于对钱包相对传统的一个定义,笔者最近结识到AlphaWallet的联合创始人&CEO Victor Zhang对钱包的理解非常的独树一帜和有见解:区块链钱包,其实更好叫做区块链客户端,其中“钱”只是其中一个应用场景。当然他们这个团队主要focus在带有智能合约的公链钱包,目前主要就是ETH了,以其作为基础衍生出众多应用场景供使用,而不是传统理解的钱包概念了。笔者以前一直觉得在未解决Cryptocurrency价值波动前,钱包的用户大规模朝潮还很久远,不能与交易所抗衡,但终究有一天王位会转移给钱包。在听了Victor的见解之后,笔者突然觉得视野更加开阔。BTW,他们团队还是ERC875的执笔,对技术的追求和开发很有造诣,是个值得关注的团队!
【区块链钱包基本类型和特点】
区块链钱包的分类和描述依照所涉及的概念不同会有所区别,从其本质特点上来讲,可用下图来表示:
区块链钱包本质特点划分
区块链钱包和区块链一样,也可以分为去onchain钱包和offchain钱包(如今很多人习惯称之为中心化钱包和去中心化钱包,虽然方便无基础的人形象理解,但是整个概念和精髓却会被误解),它们本质区别在于钱包私钥的存储方式和地点,私钥存储在用户手中,钱包商无获取途径,用户可以实时使用链上资产的称之为onchain钱包;而私钥存储在钱包商或者交易所手中,用户不能直接使用链上资产而需要通过第三方才能动的称之为offchain钱包。具体来讲:
1.onchain钱包——全节点钱包
私钥存储在用户手中,同时全节点钱包还保存了所有区块的数据,这样就可以在本地直接验证交易数据的有效性。大部分全节点钱包也具备挖矿功能,它自身也是区块链网络中的一个节点,如BTC的Bitcoin Core;ETH的Mist,Parity等。
优点:
一般属于官方为区块链设计的钱包,直接onchain,不需要经过第三方发起交易,保证了基本安全性;
由于前节点下载到本地,所以会更快验证交易信息。
缺点:
也因为下载了所有节点,所以占用很多硬盘空间(Mist现在达到了80G,笔者下了好几天也失败了;Bitcoin Core据说是150G);
每次使用前需要同步数据;
新手的使用体验不够好;
不支持多种数字资产;
往往都是电脑版本。
2.onchain钱包——SPV轻钱包
私钥存储在用户手中,但不保存所有区块的数据,只保存跟自己相关的数据,所以体积很小,可以运行在电脑,手机,网页等地方。如Blockchain, imtoken等。
优点:
用户体验很好,尤其对于新手
很多轻钱包都支持多种数字资产
体积小,不占空间
缺点:
交易验证会稍微慢一点
3.offchain钱包——通过中心服务器访问区块链网络的钱包
该类型钱包的划分有一定争议,主要在于钱包数据传输的方式是可以扩展选择区块链节点还是必须通过钱包服务方的服务器,如果是后者就存在私钥存储在中心化服务器的风险,目前有很多区块链钱包体验都很不错,甚至很流畅,由于不开源无法排除该类风险。笔者推断比特购钱包应该属于此类。
优点:
同SPV轻钱包
用户体验会比onchain钱包好
缺点:
存在安全风险(虽然真正致力做区块链的钱包企业哪怕即使通过自己的服务器将交易信息发送到节点上,即不会作恶,但是不能排除可能有作恶的人可以使用这种方式获得用户密钥)
会比onchain钱包交易验证更慢,但是用户可能体会不到。
4.offchain钱包——第三方托管钱包
完全依赖运行这个钱包的公司和服务器,存在某个组织或者个体的钱包地址里,中心化交易所里的Cryptocurrency就是在offchain钱包(交易所)里保存的。
优点:
私钥忘记了可以找回
平台会把私钥安全做的不错
一般以企业作为信用背书
缺点:
你的私钥控制在平台手上,平台“做坏事”你是无法阻止的,即作恶风险
平台关闭后你的币就没有了,即跑路风险
当然,根据不同的表现形式,我们还可以有不同的划分:
这种划分理解就比较简单了,电脑单机版的钱包,如前面提到的全节点钱包基本以此类为主;手机钱包和在线钱包以SPV轻钱包为主,前者以手机APP为主要表现形式,后者是网页插件,如MyEtherWallet, MetaMask等。硬件钱包是为了增强安全性,通过专门设计的安全硬件来离线保存储私钥,隔绝黑客入侵。
所以,电脑钱包、手机钱包、在线钱包一般体现的都是实时可用性,它们更多被称之为热钱包,即实时在线,这样就存在被黑客攻击的风险;于是硬件钱包作为常年离线保存,更多称之为冷钱包,即离线保存。
但是硬件钱包往往需要购置单独的硬件设备,所以在成本上会付出更多,同时使用的便利性也不如热钱包,因为实时在线可用。当然也有使用优盘来自己制作硬件钱包的,一方面制作过程比较繁琐,同时每次转账支出时会比较繁琐,适用于比较有基础的人士。
优点:
安全,私钥不触网,黑客无法通网络攻击。另外设备都有PIN码保护,即使在物理环境中设备被盗走,也无法打开你的钱包;
易备份,设备在初始化配置的时候会生成助记词(一般为12个或者24个单词),而助记词就是你私钥的备份,当你的设备丢失或者损坏以后,可以够买新的设备然后通过助记词来恢复私钥;
多币种同时管理,现在绝大多数的硬件钱包,不仅仅可以管理比特币,像莱特币、以太坊、比特现金等数字货币都可以同时管理。
缺点:
不免费,你要为硬件付费;
无法独立使用,硬件钱包都是隔绝网络的,所以需要配合联网的客户端(Chrome 插件、桌面客户端、手机客户端等)来完成收币和发币。不过为了安全牺牲一些方便些也是值得的,毕竟一个比特币8000刀,丢半个都疼。
【区块链钱包实现技术原理】
理解区块链钱包实现技术原理,先要理解:
1.私钥、公钥和地址产生的方法,这是区块链的相关知识;
2.接着理解如何使用API进行远程调用等基础概念,这是传统IT行业相关知识;
3.最后就是钱包设计相关的助记词, keystore和密码的概念,它和区块链公钥、私钥和地址产生的方式思路一样,但是整个过程属于区块链钱包设计过程,不能与区块链的相关知识混淆。
一、私钥、公钥和地址产生的方式(以BTC为例):
1.比特币私钥其实是使用SHA-256生成的32字节(256位)的随机数,有效私钥的范围则取决于比特币使用的secp256k1 椭圆曲线数字签名标准。
2.在私钥的前面加上版本号,后面添加压缩标志和附加校验码,(所谓附加校验码,就是对私钥经过2次SHA-256运算,取两次哈希结果的前四字节),然后再对其进行Base58编码,就可以得到我们常见的WIF(Wallet import Format)格式的私钥。
3.私钥经过椭圆曲线乘法运算,可以得到公钥。公钥是椭圆曲线上的点,并具有x和y坐标。公钥有两种形式:压缩的与非压缩的。早期比特币均使用非压缩公钥,现在大部分客户端默认使用压缩公钥。
从私钥推导出公钥、再从公钥推导出公钥哈希都是单向的,也就是采用不可逆算法。
椭圆曲线算法
4.公钥产生后,将公钥通过SHA256哈希算法处理得到32字节的哈希值;后对得到的哈希值通过RIPEMD-160算法来得到20字节的哈希值 ——Hash160
5.把版本号[2]+Hash160组成的21字节数组进行双次SHA256哈希运算,得到的哈希值的头4个字节作为校验和,放置21字节数组的末尾。
6.对组成25位数组进行Base58编码,最后得到地址。
下图以非压缩格式的65字节公钥示意上述过程:
二。远程过程调用(RemoteProcedure Call, RPC)
它是一个计算机通信协议。该协议允许运行于一台计算机的程序调用另一台计算机的子程序,而程序员无需额外地为这个交互作用编程。RPC 的主要功能目标是让构建分布式计算(应用)更容易,在提供强大的远程调用能力时不损失本地调用的语义简洁性。广为使用的是一个叫做 JSON(JavaScript Object Notation)- RPC 的协议。所以钱包都是通过某个区块链RPC接口调用来和区块链网络进行交互。
这里列出主流项目相关的 RPC 接口以及开源钱包项目,以供参考。
Bitcoin:
1.RPC
Original Bitcoin client/API calls list
API reference (JSON-RPC)
JSON RPC API
2.Wallet
Bitcoin Core,官方出品
bitcoinj,比特币协议 Java 版
bither,简单安全的比特币钱包
Electrum,全平台轻钱包
bread,iOS 钱包
Mycelium,Android 钱包
Copay,同时支持 Bitcoin 和BitcoinCash
bitcoin-wallet,又一款 Android 钱包
DotNetWallet,.NET 实现的钱包
Coinpunk,基于浏览器的钱包
btcwallet,Go 实现的钱包
Ethereum/ERC20
1.RPC
JSON RPC
JSON RPC API
Management APIs
ethjsonrpc
web3.py
2.Wallet
go-ethereum,以太坊协议 Go 版
Mist,官方出品
Parity,支持 Windows、Mac、PC 的钱包
MetaMask
MyEtherWallet,基于浏览器的钱包
eth-lightwallet,轻量级 JavasSript 版本钱包
ethaddress.org,纸质版钱包生成器
Neureal wallet,支持 Windows、Mac、PC 的钱包
其他
1.Zcash
Zcash,官方出品
2.BitShares
BitShares,官方出品
3.Sia
Sia,官方出品
4.Nem
NanoWallet,官方出品
5.Dash
Dash,官方出品
6.Qtum
Qtum Core Wallet,官方出品
7.Litecoin
Litecoin,官方出品
8.IOTA
IOTA Wallet,官方出品
9.Monero
Monero,官方出品
10.GXS
GXS Wallet for mobile,官方出品
11.EthereumClassic
Ethereum Classic Wallet,官方出品
三、钱包设计相关的助记词(mnemonic),keystore和密码的概念
私钥一般太难记忆了,使用也不方便,所以从钱包设计的角度,就为简化操作同时不丢失安全性,就出现了助记词的方法。
一般情况下,助记词由一些单词组成,只要你记住这些单词,按照顺序在钱包中输入,也能打开钱包。
根据密钥之间是否有关联可把钱包分为两类:nondeterminisTIc wallet 和 determinisTIc wallet。
nondeterminisTIc wallet:密钥对之间没有关联;
determinisTIc wallet: 密钥对由一个原始的种子主密钥推导而来。最常见的推导方式是树状层级推导 (hierarchical deterministic) 简称 HD。
比特币钱包 (Bitcoin Core) 生成密钥对之间没有任何关联,属于 nondeterministic wallet ,这种类型的钱包如果想备份导入是比较麻烦的,用户必须逐个操作钱包中的私钥和对应地址。
deterministic wallet基于BIP32(Bitcoin Improvement Proposal 32) 标准实现,通过一个共同的种子维护n多私钥,种子推导私钥采用不可逆哈希算法,在需要备份钱包私钥时,只备份这个种子即可。
通过9个步骤即可生成钱包助记词和种子,其中步骤1~6生成助记词,步骤7~9把前六步生成的助记词转化为BIP32 种子:
生成助记词:
规定熵的位数必须是 32 的整数倍,所以熵的长度取值位128 到 256 之间取 32 的整数倍的值,分别为 128, 160, 192, 224, 256;
校验和的长度为熵的长度/32 位, 所以校验和长度可为 4,5,6,7,8 位;
助记词库有 2048 个词,用 11 位可全部定位词库中所有的词,作为词的索引,故一个词用 11 位表示,助记词的个数可为 (熵+校验和)/11,值为 12,15,18,21,24
助记词规则
1.生成一个长度为 128~256 位(bits)的随机序列(熵);
2.取熵哈希后的前n位作为校验和(n= 熵长度/32);
3.随机序列+校验和;
4.把步骤3得到的结果每 11位切割;
5.步骤4得到的每11位字节匹配词库的一个词;
6.步骤5得到的结果就是助记词串;
钱包生成助记词方法
通过助记词生成种子
助记词由长度为128 到 256 位的随机序列(熵)匹配词库而来,随后采用PBKDF2 function推导出更长的种子(seed)。生成的种子被用来生成构建 deterministic Wallet 和推导钱包密钥。
在密码学中,Key stretching技术被用来增强弱密钥的安全性,增加了暴力破解 (Brute-force attack) 对每个可能密钥尝试攻破的时间,增强了攻击难度。各种编程语言原生库都提供了 key stretching 的实现。PBKDF2(Password-Based Key Derivation Function 2)是常用的 key stretching 算法中的一种。基本原理是通过一个为随机函数(例如HMAC 函数),把明文和盐值作为输入参数,然后重复进行运算最终产生密钥。
为了从助记词中生成二进制种子,BIP39 采用 PBKDF2 函数推算种子,其参数如下:
7.助记词句子作为密码;
8.“mnemonic” + passphrase 作为盐;
9.2048 作为重复计算的次数+HMAC-SHA512 作为随机算法,最终得到BIP32 种子,512 位(64 字节)是期望得到的密钥长度;
DK = PBKDF2(PRF, Password, Salt, c, dkLen)
助记词生成种子
主私钥和主链码:
首先是从根种子生成主密钥 (master key) 和主链码 (master chain code)
种子生成密钥
上图中根种子通过不可逆HMAC-SHA512算法推算出512位的哈希串,左256位是Master Private key(m),右256位是master chain code,通过m结合推导公钥的椭圆曲线算法能推导出与之对应的264位master public Key (M)。chain code作为推导下级密钥的熵。
同时钱包还提供了keystore和密码基本功能
用户最好的体验仍然会是密码方式,所以钱包还提供了keystore让用户导出保存,这个Keystore也是私钥经过加密过后的一个文件,需要你自己设置的密码才能打开文件。这样的好处是就算keystore文件被盗,只要你额外设置的密码够长够随机,那么短时间内私钥也不会泄露,有充足的时间转移地址里面的加密货币到其他地址。Keystore会存储在使用的设备里,这样每次登陆只用输入相应密码即可。
【总结】
所以区块链钱包实现的技术原理用一句话表示就是:钱包助记词生成了种子(Seed),种子(Seed)生成了私钥,私钥推导出公钥,公钥节选部分成了钱包地址。同时钱包提供了keystore,他也是私钥加密后的文件,可以配合正常的密码使用,便捷了用户的钱包使用。
所以,理解了一个钱包的生成原理之后就会更加理解下面几种钱包丢失的情况:
1.地址忘了,可以用私钥、助记词、keystore+密码,导入钱包找回。
2.密码忘了,可以用私钥、助记词,导入钱包重置密码。
3.密码忘了,私钥、助记词又没有备份,就无法重置密码,就不能对代币进行转账,等于失去了对钱包的控制权。
4.密码忘了,keystore 就失去了作用。
5.私钥忘了,只要你钱包没有删除,并且密码没忘,可以导出私钥。
6.私钥忘了,还可以用助记词、keystore+密码,导入钱包找回。
7.助记词忘了,可以通过私钥、keystore+密码,导入钱包重新备份助记词。
8.keystore忘了,只要你钱包没有删除,密码没忘,可以重新备份keystore。
9.keystore 忘了,可以通过私钥、助记词,导入钱包重新备份 keystore。
【私钥重复疑惑】
最后问题来了,根据私钥产生的机制就会有重复的可能。
私钥有32个字节(1字节=8位二进制),所以私钥的总数是2^(8*32)=2^256个≈10^77个。假设全宇宙都在穷举私钥:
假设宇宙有一亿个星系,
每个星系有一亿颗恒星,
每颗恒星有一亿颗人造卫星,
每颗人造卫星上有一亿台超级计算机,
每台超级计算机有一亿个CPU,
每个CPU每秒可以穷举一亿个私钥。
假设有一亿个私钥的地址上有BTC(每个地址平均0.21BTC),那么,多久可能穷举出一个有币的私钥为:
10^77(私钥总数)/10^8(有币私钥)/10^8(星系)/10^8(恒星)/10^8(卫星)/10^8(超级计算机)/10^8(CPU)/10^8(每秒穷举)=10^21秒。
10^21秒/3600秒/24小时/365天=317098亿年。
现在宇宙年龄为138.2亿年,相对来说,假如全宇宙都在穷举私钥,每1000倍宇宙年龄,可以期望穷举到0.21 BTC。
以上查询得到的计算方式只是说明概率很小很小,小到可以忽略不计,但是随着时间轴的累积,加上现在不仅仅是BTC,还有各种各样的新公链,如果都使用同样的私钥生成地址的规则,有概率就意味着最终无线长时间总会出现重复的情况。而且概率学的范畴无法预测到偶然事件:如就偶然撞上了一次重复事件。
所以,笔者理解:只能说刻意去穷举私钥投机的方式是不具备性价比(完全不可取或者说代价惨重)的,在这样的默认假设下,万一出现偶然事件,生成钱包地址时会进行网络验证,如果发现重复(注意理论上即使地址重复也未必私钥会重复,但是算法上通过限制私钥生成的范围来保证不会有两个私钥对应同一公钥的情况,所以还是可以理解成私钥和地址一一对应)就重新生成新的,并不会出现资产损失的可能。