前言
关于比特币入门,其运行原理(理解性描述),什么是挖矿,还有一些学习资料的整理,详见此博客链接
第一章讲比特币的历史,算是导入,上面的博客链接有概括。
第二章举了使用比特币交易的例子,其中介绍了一个交易模型让我印象深刻
这个模型中,有输入和输出,输入(IN)是自己账户上可用的金额(这个金额可以由一个人转账形成的输出A,或者由多个人转账形成的输出们组成的A,B,C),而最基本的输出(OUT)分为两个部分,一个是转账给别人的,一个是找零给自己的,在进行下一次的交易的时候,这个输出中给退还给自己的一部分可以是上面的A或者A,B,C中的一个,而转账给别人的也是同理,使用比特币的交易过程,就是比特币所有权在地址(下面重点讲)的不断转让过程。
同样还是上面这张图,有个交易费项,这个交易费是给矿工的(补充了知识点:矿工除了挖到矿所得的奖励外,在比特币的交易中,还扣除了一些费用(按照整个比特币网络挖矿每4年奖励减半,将在2140年奖励归零,我觉得2140年的电脑运算速度会很快,收取的手续费和现在挖矿相比应该差不了多少)
当一笔交易由矿工选中Lucky Number并讲其放在区块链中后,随着区块链的长度不断变长,这笔交易越来越难被推翻,因为它在网络中被更多矿工和用户验证,渐渐地被整个比特币网络承认。
第三章是如何安装比特币的完整客户端,但是看到下载区块链要很多天我就放弃用第三章的方法,而是用第三章末尾推荐的bitcoin exploer工具,这是一个命令行与服务器交互以获得比特币信息的工具,对于新手来说很合适,这个工具在Windows下有现成的二进制可执行文件,但我下载不成功,转在了Linux下用源码安装,这个链接里包含了这个工具的安装以及教程。
重点:密钥、地址、钱包(第四章)
加密*简介
加密*分为:①以置换、替换为代表的古典密码*(代表:凯撒密码)=》②要求发送方和接收方都要有相同密钥的对称加密*(代表:DES加密)=》③公钥加密*:有一对公钥和私钥,公钥是公开的,网上所有人都知道的,用公钥加密的信息,只有拥有私钥的人才能解密(代表:RSA加密,椭圆曲线加密)。
在公钥加密*中,有一个称为陷门的函数h,陷门的定义就是从x->y方向容易,但是从y->x方向难,根据两个方向难度差距,定义了陷门函数的好坏,一个陷门函数,如果两方向难度差距越大,陷门函数越好,这个密码方案越难攻破,下面以RSA来举例子
如果想要攻破RSA就需要在知道公钥(n, b)的基础上,算出私钥(p,q,a),因为n=p*q,而a=b(mod fi(n))故,只用知道n=p*q中的p和q,就能得到私钥,而n=p*q又叫大整数分解问题,现在没有一个有效算法能解决该问题,所以它是安全的。
但是Bitcoin中所用的不是RSA加密,而是椭圆曲线加密算法
椭圆曲线加密算法
说是椭圆曲线其实不太准确,这个椭圆曲线和我们高中学的那个椭圆曲线不是一个东西,虽然它们方程式长得差不多,椭圆曲线方程式为:y2=x3+ax+b,画出曲线图像是下面这样,但是实际上不是线,而是一系列的(x,y)都是整数的点集,这个点集构成一个循环群,群是自带运算的,群的两个点为A,B,定义A和B的运算“+”为:过A,B点连一条直线(如果A=B,则该直线就是切线),这条直线必定与椭圆曲线交与除A、B之外的第三点C,C点关于x轴对称的那点称为D点(D点一定在椭圆曲线上,因为椭圆曲线关于x轴对称),D点就是目标点,此时有运算A+B=D【此处的+与整数里的+不一样,你也可以把此处的+叫做“这个操作”,不过为了方便,还是说+好一点】,定义整数k和曲线上的整数点A的运算k*A为执行A+A+...+A(k次),循环群:下面那张只有点的图,可以由最初开始的满足y2=x3+ax+b的点G开始,通过不断的k*G(k=1,2,...,n)生成,而k=n时G达到最大,即k=n+1时k*G=1*G,形成循环,这就是循环群,下面一张动图形象地描述了这个过程。
上面的k就是私钥,而点k*G是公钥,我不打算从数学的角度来给予椭圆曲线加密算法的陷门函数是难解决的,我们观察这样一个事实,从G点,我们能轻易地通过k得到目标点,但很难从目标点得到G点,这个单项陷门函数显然要比整数分解问题难很多,这篇文章里用了一个很形象的比喻,长度为256的密钥,从公钥中解出私钥,解RSA消耗的能量能煮沸一汤匙水,而解椭圆曲线能把地球上的所有水都煮沸,RSA密钥要达到同样的效果,需要2380bits的。椭圆曲线和RSA效率高下立判,事实上,现在很多安全协议除非在设计中用到RSA的机制,否则都已经升级为了椭圆曲线加密。
比特币地址
在上面椭圆曲线中,我们得到了公钥,对这个公钥进行Hash,就能得到唯一标识的比特币地址,在Hash处理中,用到了两个Hash函数:①SHA-256,②RIPEMD160,通过下面这样的方式构建比特币地址(为什么要两次HASH,我也不太清楚,不过我查到的资料说是RIPEMD160有缺陷,不能只用RIPEMD160,具体等看源码再说)。
HASH算法将任意长度的二进制值映射为较短的固定长度的二进制值,这个小的二进制值称为哈希值。Hash函数有两个特性:①数据一旦产生哈希值,那么就不可能通过单一的哈希值解出原始的数据。(上面的加密*只是不知道私钥难解,知道密钥易解,HASH没有密钥,不能解)②独特性,两个不同的数据是不能产生同样的哈希值,事实上,数据就算改变一个bit,HASH得到的结果也完全不同,在bitcoin中,用于验证接收者是否正确(因为比特币的转账过程,需要输入转账人的公钥,并用自己的私钥签名(别人能用你的公钥,从这个签名中知道这是你,但不知道你的私钥,方法就是加密的逆过程),从账单就能知道是你(你自己的私钥签名)转账给别人(别人的公钥)),此处我们只关心公钥做HASH用来确定收账者地址(转账,只用知道别人公钥的HASH就行了)。
SHA-256——将公钥转化为256长的bit串 链接给出代码描述
RIPEMD160——将256长的bit串HASH成160长的bit串 自行百度或者bing吧,我打算看源码的时候再看相关实现
在进行Hash处理后,得到的其实只是0,1比特串,现在需要将0,1比特串转化为我们人可读的形式,人的十个指头衍生出的十进制是现在大家最熟悉的数字运算方式,但是除此之外,数据也能表示成2进制,8进制,16进制,比如11(10进制)=1011(二进制)=13(8进制)=B(16进制),Bitcoin的实现中,用到了BASE58的进制编码方式
BASE64、BASE58、BASE58_CHECK
BASE64就是64进制了,它的字符表示是:0-9,a-z,A-Z,+,/
BASE58 的字符表示在BASE64的基础上去掉了容易让人误解的0和O,l(L的小写字母),I(i的大写字母),+,/
BASE58_CHECK 是为了在传输过程中发生错误而加入的验证位,具体验证如下:
prefix就是加在HASH之后160bits字符串的前缀(加此前缀表明使用BASE58_CHECK验证),而从checksum中抽取前面4个字节(共16bits),加在160bits的后面,这样形成的就是BASE58_CHECK形式的编码。
使用编码一是为了人类可读,二是为了传输方便,下图中的前缀声明版本号,是因为,BASE58_CHECK不光用于比特币地址的编码,还用于比特币的其他编码,如私钥的版本号就和公钥不一样。
压缩格式的公钥——为了节省空间
从前面椭圆曲线加密方案中,我们知道,公钥P(x, y)是椭圆曲线上的一个点,而椭圆曲线是个只含x, y的二元方程,这就意味着,知道x,就能求出y,唯一一点缺陷就是不知道这样求出来的y是正还是负,这可以在压缩公钥P前,通过指定P的前缀来判断,于是,此时就将P压缩成x,从P(256bits, 256bits)中节省了256bits,这样随着区块链的不断延长,就能节省大量的空间。
但是,压缩毕竟是比特币出来很久才提出的方案,压缩产生的公钥通过HASH得到的地址肯定和之前的不一样,那之前未压缩下比特币公钥下的比特币地址,就不能通过这种方式找到,为了解决这个问题,引入了“压缩格式的私钥”,实际上并不是压缩私钥,而是在私钥的前面加上前缀来标识来识别该私钥对应的公钥为压缩格式的,未加前缀的就默认非压缩格式,这样,比特币的拥有者(非其他人)就能找到自己在那个公钥下的比特币,而其他人的对该账户的转账却不受影响。
比特币钱包
在最开始比特币的设计中,将比特币的钱包作为一个私钥集合,一次性地生成100个随机密钥,然后一笔交易用一个密钥,这样随着交易的增多,即不利于钱包的转移(将私钥转移)又难维护(私钥安全性),这是最开始的非确定性(非确定性指的是随机生成私钥)钱包。
现在是确定性钱包逐渐取代非确定性的钱包,这里的确定性指,通过一个确定的种子来生成一系列,无穷的私钥,确定性钱包如下图所示
左图中,密码学上安全的伪随机数发生器需要提供一个熵(这个熵是一串随机数字,这串随机数字越没规律越好,我的理解是可以用普通的随机函数来生成),助记码是为了记住根种子而使用的,只是将跟种子的数字映射为助记码,帮助人记忆而已,通过SHA-512这个HASH函数,512的二进制串,左边256bits对应的密钥生成的公钥,和256bits的编码,在右图的下一次生成私钥时,又作了输入,加索引号的额意义是,索引号有232 =40亿种选择,每一层都能有40亿种选择,我认为能将密钥生成看作无穷,生成私钥的具体缩略图如下。
书中提到了上面那种方式是不安全的,因为公钥是公开的,只要你的父链编码被人知道了,别人很容易地就能知道,那条父链编码下的所有子链,书中给出的改进方案是用私钥替代公钥生成私钥链,这种方式又叫做硬化子密钥,如下图