我们知道在公钥加密体系中, 由私钥推出公钥很容易反过来却是不可能的, 借助一些伟大的数学算法可以实现这一特性, 比特币使用的算法叫做椭圆曲线算法.
在比特币中私钥就是一个 256bit 的数字, 得到这个数字的方法有很多, 最简单的就是随机法, 比如掷硬币 256 次, 将结果作为私钥. 得到了私钥之后对其执行椭圆曲线算法, 我们就得到了对应的公钥, 公钥是一对 (x,y) 坐标, x 和 y 都是 256bit 的数字, 但是对每个 x, y 都只有两个取值, 并且这两个值互为相反数, 所以公钥的长度有两种情况:
- 512bit --- 同时记录了 x, y
- 257bit --- 记录 x 以及 y 的符号, 这需要一点点额外的运算算出 y [[https://bitcoin.stackexchange.com/questions/2013/why-does-the-length-of-a-bitcoin-key-vary][参考]]
公私钥编码
如果用 2 进制, 即便是 16 进制来写出公钥或私钥的话, 那结果是很长的, 比较不方便. 因此我们所见到的公私钥一般都是格式化过或压缩过的.
从 bitcoin core 开始, 比特币客户端使用的格式有 WIF (Wallet Import Format) 以及 WIF-compressed. WIF 格式使用 Base58 编码公私钥.
使用 libbitcoin-explorer 工具我们能够方便的在公私钥的各种格式之间进行转换.
私钥加密
对用户来说私钥是最关键的东西, 为了防止私钥泄露, 往往建议对私钥对称加密后再存储, 这样由于设备里存的是私钥的密文, 即使设备丢失了, 别人不知道密钥也解不出私钥.
那么采用什么样的加密算法, 直接加密私钥还是加密 WIF 呢? 为了方便钱包在各种钱包客户端中备份转义, 人们制定了 BIP-38 规范, BIP-38 规范对私钥加密主要做了如下约定:
- 使用 AES 对称加密算法
- BIP-38 的输入是私钥 (一般是 WIF 格式) 和用户设定的密钥
- BIP-38 的输出是 Base58Check 编码后的密文
比特币地址
比特币地址是对公钥做两次哈希的结果, 两次哈希的结果会得到一个 160bit 的值, 通常也会对这个值做 Base58Check 编码, 将编码后的值作为地址.
所以可以看到, 比特币里面几乎凡是涉及到要展示的东西, 都要 Base58Check 编码一遍.
如何保证自己的比特币不丢失?
现在我们知道了, 对于我们来说最重要最关键的就是私钥, 比特币钱包花样很多, 但本质上它们也都在管理私钥, 管理好自己的私钥就能保证资金的安全. 因此, 针对我们使用钱包的过程中, 我总结了如下的几点建议:
选择支持通用加密格式的钱包, 比如支持 BIP-38 的钱包. 小众的钱包可能有自己的钱包格式甚至加密私钥的格式, 这会使得以后不方便导入到其他钱包客户端
选择的钱包一定要能够导出你所有的私钥, 不管是 hex 格式还是 WIF 格式. 你应当周期性的备份这些私钥到你的离线设备上, 或者 Dropbox 上
钱包文件不要太复杂, 钱包文件应当只包含私钥公钥相关的信息
在 2, 3 两点上有必要说一下 wallet.dat 文件, wallet.dat 是 bitcoin core 官方的钱包文件格式, 我们说的 "备份钱包" 在 core 中也就是备份 wallet.dat 文件. 然而在经过一番研究之后我特别不喜欢这个格式, 首先它不仅仅包含了私钥信息, 还包含了最近的交易信息, 这使得这个文件的尺寸比较大, 备份起来实际上还备份了一些不必要的交易, 因为交易信息的保存应该是区块的事情; 其次这个文件是 binary 的, 并且 core 客户端也没有提供命令来查询 wallet.dat 中的地址和私钥, 总之我即不能方便的用文本编辑器查看我的私钥, 也不能借助 core 客户端查看私钥.
说白了其实就一个原则: 不管使用什么钱包客户端, 一定要确保能够对自己的私钥有完全的掌控权!
the end
最近打算换比特币钱包, 所以在考量比较各种钱包的优缺点, 不知有没有人有兴趣了解呢? 有的话后面我就献丑再写一篇比较各种比特币钱包客户端的帖子吧! 嘿~