区块链——安全解决方案集大成者
一、区块链简史
区块链是面向数字货币记账系统(Bitcoins)设计的密码解决方案
中本聪认为:去中心化是必然的!
比特币是精心设计打造的P2P数字货币记账系统 (去中心化 人人都可以记账)
比特币的两个主要支撑技术:区块链-密码技术解决方案 P2P网络-去中心化记账的网络技术设施
去中心化的记账
·账本公开机制-每人手里都可能有一份账本,都是真的。
·账本上不再记载每户参与者的余额,而只记载每一笔交易。即记载每一笔交易的付款人、收款人和付款金额。只要账本的初始状态确定,每一笔交易记录可靠并有时序,当前每个人持有多少钱是可以推算出来的。(每个人自己也可以为自己的钱包记账,方便快速查询余额)
·账本由私有改为公开,只要任何参与者需要,都可以获得当前完整的账本,账本上记录了从账本创建开始到当前所有的交易记录。
·基本假设:大家必须诚实守信,或者说一半以上的人需要诚实守信,即承认真的账本确定是真的,即使有少部分人(一半以下)集体伪造账本,本着少数服从多数的原则,真的账本仍让不会被替代。
区块=账本
区块链的实质:账本就是比特币系统中的区块,多个区块连接在一起是区块链
一个区块记录着多笔交易
区块是有顺序的,一个区块会有唯一的父区块
区块和区块链最重要的安全需求是 完整性
二、两个方面的完整性
交易历史的完整性:整个账本链条(区块链)的完整性
·交易发生后不可逆,交易历史完整,可追溯
交易本身的完整性
账本(区块)上的所有交易记录完整
·不可篡改
解决:Digital Signatures and Cryptographic Hash 数字签名和密码方式的哈希函数
区块 包含两个部分:
区块头(head):
·记录当前区块的元信息
·前一区块头Hash->交易历史的完整性
·Merkle树根Hash->交易本身的完整性
区块头是固定的80个字节 Nonce(Number once) Hash一般用SHA-256算法 生成256bit的哈希值 也就是32个字节
区块体(body):
·记录实际交易数据等
区块 和 区块之间 就像链条一样 彼此连接在一起
链条上所有的区块都记录前一个的Hash 当前一个被更改/删除/替换 Hash变了 就验证不上了
交易本身的完整性
Merkle树是一种HASH二叉树,它是一种用做快速归纳和校验大规模数据完整性的数据结构
生成整个交易集合的数字之吻,提供了一种校验区块是否存在某交易的高效途径
至多计算2*log2(N)就能检查出任意数据元素是否在该树中,该数据结构非常高效 (because这是一个二叉树)
在比特币的Merkle树中,交易被两次使用SHA-256算法,因此其HASH算法也被称为double-SHA256
Merkle树
HA=SHA256(SHA256(交易A)) HAB=SHA256(SHA256(HA+HB)) 所以说 Merkle根实际上是整个交易集合的Hash
怎样验证交易K是否存在于区块中?
先算出HK,······蓝色的HASH是查询出来的,绿色的HASH是计算出来的;计算出来最后的根,同区块头中Merkle树根进行比较,如果相同,那么说明交易存在与该区块中。
蓝-查出来 绿-算出来
区块链的参与者有两类:FULL PEER & SPV CLIENT
Full Peer 存储完整的Block,包括Block Size + Block Header + Transsaction Counter + Transactions
SPV(Simplified Payment Verification)Client,只存储精简的Block:Block Size + Block Header
总结
交易历史的完整性,由区块头的前一区块头HASH保障 交易本身的完整性,由区块头的Merkle树根HASH保障 (不是所有的区块都有Merkle数据结构,只有在Full Peer区块中才有)
三、工作量证明
谁来生成区块(记账)——矿工
比特币参与者可以有两个身份:交易者,矿工
·参与者可以同时兼有这两个身份
矿工从事比特币“挖矿”活动:即将最近发生的交易记录在账本上(生成区块,并加入到链条中)
矿工有一定可能性获得报酬
矿工可以随时退出,也可以随时有新的矿工加进来(P2P系统的特性)
挖矿是有一定难度的(有一定计算量),矿工之间存在着竞争关系
矿工挖矿的动机:比特币奖励
谁先创建了新的区块,谁就能拿到比特币
随着交易和矿工的活动,比特币的数量不断增加。
矿工的工作:
收集交易单
每笔交易的付款人,不但要将交易单给到收款人,还要同时把交易单投递到每个矿工小组的收件箱里
矿工定期到自己收件箱里把收集到的交易单一并取出
填写账本:
按笔填写交易记录
填写区块头,前一区块头HASH值,Nonce值等
Nonce值可任意填一个数字
确认新区块/账本:
某矿工生成了一个区块,为了得到奖励,必须立刻请其它矿工确认自己的工作,所以这个矿工必须将有效区块,快马加鞭送到其他矿工手里请求确认
系统规定当某个矿工接到其他矿工送来的新区块时,必须立即停下手里的挖矿工作进行确认
需要确认的信息有三个:
区块HASH满足难度值要求
区块的前一个区块有效:前一区块确实是自己的最后一个区块,且HASH正确
交易清单有效一一如付款人有余额
工作量证明(Proof-of-work)
新区块必须满足两个条件:1、新区块记录的交易还有待系统(其他矿工)的确认 2、新区块头的HASH值必须满足计算量的要求
当矿工给链上加上自己的区块,并且已经有着矿工沿着这个区块继续挖矿时,称这个区块已经被其他矿工认可了
新区块头的HASH必须满足计算量要求,即:
·矿工需要选择合适的随机数 Nonce,使得:H(prev_hash,Nonce,Merkle_root,:其他头部字段)<E (注意Prev_hash,Merkle_root,.....很多都不能变,能变的是Nonce,所以 不停的修改Nonce值,让它符合E的难度规定)
E是系统规定的难度值,如:
0X00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
Verification is easy. But proof-of-work is hard
考虑长度256的bit序列
For N zeros , because the SHA-256 output is effectively random , gettingzero bits = same as flipping a coin and getting N heads in a row
For N zeros , have to try 2 N/ 2 Nonces。。。
·N = 1 . . Try 1 nonce
·N = 16 . Try 32768 nonces
·N = 32... Try 2 billion nonces
Winning a block proves the miner did work
for example:
设计这么复杂的算法,就是为了维持区块生成速度不要太快。
难度值设置原则:区块链被设计为平均每10分钟生成一个新区块
需要定期更新难度值E(每隔2016个区块): 难度值定期更新原则
全网均会自动统计过去2016个区块生成耗时,重新计算出下一个2016个区块难度值的目标值
按10分钟一个区块生成速度,2016个区块生成时间为2016*10分钟=14天
新目标值=当前目标值*实际2016个区块出块时间/理论2016个区块出块时间(14天)。
4、共识机制
完整性:不可篡改
基于假设:51%以上的参与者是诚实的。
因为矿工是并行工作的,所以可能同时收到两个合法的区块
这些区块:它们都基于当前这个矿工的区块链的的最后一个区块
并且区块内容都完全合法(即所记录的交易有效)
区块头HASH满足难度值要求
所以我们不应该以线性方式组织账本,而应该以树状组织账本,任何时刻,都以当前最长分支作为主账本,但是保留其它分支
看谁变得更长,谁变得更长就认可谁
为了防止区块链变成树,我们规定:
收款人在公告挂出时不能立即确认交易完成,而是应该再看一段时间,等各个挖矿小组再挂出6张确认区块,并且之前的区块没有被取消,才能确认钱已到账
挂六张确认区块 的 目的 是为了防止对区块链的攻击
double-spending
收款人确认收款后,从另一条分支上建立另外的交易单,取消之前的付款,而将同一笔钱再次付款给另一个人
抵御原理:
从前面我们知道:生成有效区块不是那么简单的,要花费大量计算量。
如果某区块包含你收到钱的确认,并且在后面又延续了6个区块,那么攻击者想要在落后6个的情况下从另一个分支赶超当前主分支是非常困难的,除非攻击者拥有非常多的算力,超过其他所有诚实矿工的算力之和
所以区块链当参与者越多 他越安全
那挖矿活动导致比特币数量一直増加下去,岂不是会严重通货膨胀?
刚开始协议每生成一页账本(一个区块),奖励矿工50个比特币
后面,每当账本增加21,000页,奖励就减半,例如当达到210,000页后,每生成一页账本奖励25个比特币,420,000页后,每生成一页奖励12.5个,依次类推
等账本达到6,930,000页后,新生成账本页就没有奖励了。此时比特币全量约为21,00000个,这就是比特币的总量,所以不会无限增加下去
没有奖励后,就没人做矿工了,岂不是没人帮忙确认交易了?
到时,矿工的收益会由生成区块所得变为收取手续费。
例如,你在转账时可以指定其中1%作为手续费支付给生成账本页的矿工,各个矿工会挑选手续费高的交易单优先确认(到那个时候,比特币规模很大,交易也就很多)
怎样防止纂改?
因:区块HASH=SHA256(SHA256( version+ prev_hash+ Merkle_root+时间戳+当前难度+ Nonce),
攻击1:改变区块内交易记录,那么 Merkle根对应不上
攻击2:攻击者改变交易记录和 Merkle根,那么区块HASH对应不上
攻击3:某坏矿工没有到达难度要求就提交了区块,那么任何人根据难度要求的计算公式进行验证都会发现错误,或者说只要51%的人都承认错误即攻击失败
攻击4:攻击者改变了区块内容和区块HASH,那么会导致本区块的下ー个区块头内保存的 prev_hash对应不上,51%的人都承认错误那么攻击失败
攻击5:假设攻击者掌握了51%甚至更高的算力,那么成为ー个合法的良民收益会更大更安全
五丶公钥密码实现身份标识、交易的签名
公开密钥,主要在用于交易记录里面
交易记录及其过程
对于每笔交易(有唯一编号),付款人签名,签名块放在交易记录中SIGNED付款人的私钥(当前交易+收款人的 Public key)
任何人可以验证
任何人都可以追踪交易历史
比特币没有找零交易 输出等于输入
交易账本
公钥密码:交易完整/可认证/抗抵赖
例如对交易3的有效性验证:
交易3包含:1.输入和输出,2.Bob对交易的签名,3.Bob公钥
交易3的输入来自交易2的输出0
然后验证者把Bob的公钥转换为钱包地址(见下页),和交易2的输出0的钱包地址(被交易2的付款人签过名的)做对比,
若是不相等,则为无效交易
若相等,则用Bob的公钥验证签名,验证通过,则
1)证实Bob的确拥有交易2的输出0的钱
2)本次交易是由Bob发起的
3)保证了本次交易的完整性
最后检查一下输入的钱是否大于等于输出的钱
SECP256K1是基于椭圆曲线的密码算法
RIPEMD160是哈希算法
公钥算法是SECP256K1(基于ECC),考虑到算法强度比较强和的公钥比较短
匿名性
虽然每个人的公钥是匿名的,但账本是公开的,能看到比特币拥有者的公钥,岂不是他的所有账目都查出来了
1.每个公钥后面真实的人的身份是保密的 2.并且他可以拥有无限多的公钥
如果每一次交易用不同的公钥,这样就追查不到同一个人的所有账目了
总结
完整性 Integrity→Digital Signatures and Cryptographic Hash Is the coin double-spent? Can an attacker reverse or change transactions?
身份标识 Authentication→Public Key Crypto: Digital Signature Am I paying the right person? Not some other impersonator?
隐私保护 Privacy→Pseudonymity(参与者可拥有多个公钥) Are my transactions private? Anonymous?
可用性 Availability→Broadcast messages to the P.2 P networkDistributed storage Can I make a transaction anytime I want?