密码学原理
对称加密算法
原理
对称加密: 使用同一密钥进行加密和解密
传统密码加密, 私钥算法加密, 加密速度快, 密文是紧凑的安全的
加密过程
A 同学生成明文 ->通过私钥和加密算法 ->生成密文 ->将密文通过网络传输到目的地 B 同学 ->通过同一私钥以及解密算法 ->解密为明文
对称加密算法的缺点:
两个人有一对密钥, 那么 3 个人就需要 3 个密钥, 两两之间都需要一个密钥, 人越多密钥越多, 并且为了安全起见, 密钥用过一次就会丢弃更换密钥, 就出现了一系列问题: 密钥分发, 密钥存储和管理, 缺乏对数字签名 / 不可否认的支持
常用对称算法:
DES :
l des 是一种块或分组加密算法, 20 世纪 70 年代 IBM 公司发明, 1976 年 11 月纳为美国国家标准
l DES 密钥是固定的 56bit, 不够安全
l DES 以块模式对 64bit 的块进行操作, 解释如下:
假如有一段 1G 的明文数据需要加密, 加密算法首先将这段明文数据按照 64bit 一段一段分开, 然后加密 64bit 的明文块.(如果加密的数据长度不是 64 位的倍数, 可以按照某种具体的规则来填充位.)
64bit 明文 ->初始置换 IP->在密钥控制下 16 轮迭代 ->交换左右 32bit->初始逆向置换 IP->输出 64bit 密文
DES 有两种方式 ECB 和 CBC
ECB 方式:
就是将数据按照 8 个字节一段进行 DES 加密或解密得到一段段的 8 个字节的密文或者明文, 最后一段不足 8 个字节, 按照需求补足 8 个字节 (一般补 0 或者 F) 进行计算(并行计算), 之后按照顺序将计算所得的数据连在一起即可, 各段数据之间互不影响. 这样一来相同的明文和密钥得到的是相同的密文, 经过大量的统计分析和尝试攻击, 密文很有可能被破解, 比如中文出现最多的字 "的", 可能很快就能到这个明文对应的密文.
CBC 方式:
首先将数据按照 8 个字节一组进行分组得到 D1D2...Dn(若数据不是 8 的整数倍, 用指定的补位数据补位)
第一组数据 D1 与初始化向量 IV 异或后的结果进行 DES 加密得到第一组密文 C1(初始化向量 IV 为全零)
第二组数据 D2 与第一组的加密结果 C1 异或以后的结果进行 DES 加密, 得到第二组密文 C2
之后的数据以此类推, 得到 Cn
按顺序连为 C1C2C3...Cn 即为加密结果.
简单讲就是首先将明文分组与前一个密文分组进行异或运算, 然后再进行加密, 上面提到的初始化向量 IV, 是因为当加密第一个明文分组时, 不存在前一个密文分组, 因此需要准备一个长度为一个分组的比特序列来代替前一个密文分组, 通常缩写为 IV. 这样的方式就保证了明文和密文并不是一一对应关系, 即同一组明文不一定为同一组密文. 安全性提高了很多.
虽然 des 算法是安全的, 但是 56bit 的密钥长度太短, 容易被暴力破解, 不够安全, 所以需要经常修改密钥, 防止暴力破解, 另外交换密钥的方式或者说通道, 必须是安全的, 防止密钥泄露.
3DES
3des 算法密钥长度达到了 168 位, 并且做了 3 遍 des 加密(严格意义上说是两遍), 所以暴力破解可能性很低, 达到了更高程度的安全. 但是会变慢增加延时, 不适用与语音视频的加解密.
AES
l 因为 des 算法不够安全了, 所以出现了 AES,AES 适合于高速网络, 适合在硬件上实现
l 密钥长度可以为 128bit,192bit, 或者 256bit(还能以 32bit 的倍数扩展).
l 软硬件运行效率较高, AES 可用于无线 / 语言视频加密
RC 系列
包括 RC2,RC4,RC5, 其中最常用的是 RC4
RC4 是基于流模式加密算法, 面向 bit 操作, 应用范围很广, 比如 https,WEP,WPA.
WPA2 用的 AES 算法.
轻量级加密算法, 运行速度快, 对加密硬件要求低, 以后可能会用到物联网的一些硬件设备上.
IDEA
类似于 https://baike.baidu.com/item/DES ,IDEA 算法也是一种数据块加密算法, 它设计了一系列加密轮次, 每轮加密都使用从完整的加密密钥中生成的一个子密钥. 与 DES 的不同处在于, 它采用软件实现和采用硬件实现同样快速. 速度都比 des 快.
Blowfish
Blowfish 是一个对称加密块算法, 由 Bruce Schneider 于 1993 年设计, 现已应用在多种加密产品. Blowfish 能保证很好的加密速度, 并且目前为止没有发现有效地破解方法.
易于软件快速实现, 所需存储空间不到 5KB, 适用于密钥不经常改变的加密, 比如监测水质的设备, 可能放到水中三五年不便, 就可以用 Blowfish.
国密算法
SM1,SM2 算法, 都是对称算法, 但是不能出口, 一般用到国家政务, 警务通等领域
非对称加密算法
两支对应密钥, 称为公钥和私钥, 一般是公钥加密私钥解密.
签名一般是私钥签名, 公钥验签.
加解密过程
同学 A 产生明文 ->使用同学 B 的公钥加密成密文 ->通过网络传输到同学 B->通过同学 B 的私钥解密 ->同学 B 得到明文
同学 B 的私钥始终保存在 B 的本地, 且公钥不能推导出私钥, 所以即使密文被截获, 也是很难被解密的, 安全的.
非对称加密算法的特点
加密速度非常慢, 密文非紧凑的,
公钥和私钥不相同, 通过私钥可以推导出公钥但是不能通过公钥推导出私钥.
三种用途:
加密解密
数字签名: 保证信息的不可否认性
密钥交换: 双方协商会话密钥
常用算法:
RSA 算法: 支持上面所说的三种用途
DH 算法: 只支持密钥交换
DSA 算法: 只支持数字签名
DH 算法
解决对称加密算法中密钥分发的问题: 前面提到对称算法中密钥交换的过程必须用安全通道交换, 但是很难能做到真正的安全通道, DH 算法就可以解决这个问题.
算法过程:
第一步: 同学 A 和同学 B 两个人各自生成自己的 DH 公私钥, 私钥自己保存, 公钥发送给对方.
第二步: 同学 A 用同学 B 的公钥和自己的私钥通过 DH 算法生成一个 key, 同学 B 同理生成一个 key, 最终 AB 同学生成的 key 应该是一样的, 这样就实现了密钥的交换.
这样即使公钥在传输过程中被截获了, 但是并不能从截获到的公钥推导出 key.
RSA 算法
密钥长度在 512-4096bit 之间
RSA 比用软件实现的 DES 慢 100 倍
RSA 比用硬件实现的 DES 慢 1000 倍
RSA 的主要功能: 加密, 数字签名和密钥交换
其他公钥算法
Elgamal:DH 的一种变形
椭圆曲线加密算法(ECC): 原理是给定椭圆曲线上两个点 A 和 B, 如 A=kB, 要找到整数 k 非常困难, 比特币底层就是用的这种算法. ECC 密钥更小, 与 1024 位的 RSA 密钥具有同样安全的 ECC 密钥只有 160 位
数字签名
RSA 可以提供数字签名功能, 提供认证和抗抵赖.
私钥加密的过程:
同学 A 生成明文 ->通过发送方的私钥加密成密文 ->通过网络传给 B->B 拿到密文用 A 同学的公钥解密 ->得到明文
通过这个过程, B 可以用 A 的公钥解密开密文, 就表示这段密文就是 A 发送的, A 就不能抵赖了.
数字签名过程:
发送方 A 生成明文
用接收方 B 的公钥加密这段明文, 生成密文. 同时对明文信息进行哈希计算, 得到摘要, 将摘要用发送方 A 的私钥进行签名, 得到签名值.
通过网络将密文和签名值发送给接收方 B
B 收到密文和签名后, 首先将密文用自己的私钥解密, 得到明文. 然后对明文进行哈希, 得到一个哈希值, 也就是上面说的摘要
接下来, B 继续对 A 发来的签名, 用发送方的公钥进行解密, 得到一个摘要
最后接收方 B 将两个摘要进行对比, 如果一样, 就说明消息是 A 发的并且中途没有被篡改.
上面这段可以理解数字签名的过程, 但是真实使用过程中, 并不会使用公钥加密, 一般对明文加密用的还是对称算法, 可以保证速度, 后面会讲到, 如何将对称和非对称算法结合使用.
hash 算法: 无论多长的明文数据, 经过 hash 后, 得到的都是一段定长的 128 或者 256 字节数据, 同一段明文对应同一个 hash 值, 并且算法不可逆, 即不能通过摘要值逆算出明文, 所以这里既能保证速度, 又可以保证安全.
数字证书与 CA
首先, 从上面那些加密过程中提出一个问题: 发送方 A 将明文加密的时候, 如果判断使用的加密公钥就是接收方 B 的, 而不是其他什么人的呢?
这里就引出了 CA 机构.
CA 机构: 颁发数字证书的机构, 作为电子商务交易中受信任的第三方, 承担公钥体系中公钥的合法性检验的责任. CA 中心 ( https://baike.baidu.com/item/GlobalSign ) 为每个使用公开密钥的用户发放一个数字证书, 数字证书的作用是证明证书中列出的用户合法拥有证书中列出的公开密钥.
也就是说, CA 机构给了用户 B 一个数字证书, 数字证书中包含用户 B 的信息, 公钥以及认证有效期等, 类似网络上的身份证.
哈希与 HMAC
哈希 Hash(散列函数)
将一段任意长的数据, 经过计算, 得到一段定长数据.
hash 算法有几个特点:
l 不可逆: 几乎无法从得到的 hash 结果值, 推导出原文
l 无碰撞: 两段不一样的原文, 几乎不可能得到一个同样的 hash 值.
l 雪崩效应: 原文有轻微的变化, 得到的 hash 值会产生巨大变化
使用场景:
l 发布文件的完整性(比如下载一个炒股软件, 该软件会给你一个 MD 值, 下载成功后的 MD5 值和软件告诉你的一样, 说明下载过程没有问题)
l 服务器中保存用户密码
l 数字签名
hash 算法有很多, 常用的有 MD5,SHA256
用户密码的存储:
用户名 | 密码 |
test | 123456 |
明文存储的情况下:
哈希存储:
用户名 | 密码 |
test | e10adc3949ba59abbe56e057f20f883e |
盐 + 哈希:
用户名 | 盐 | 密码 |
test | 2020-2-2 12:12:00 | 74acf6b6ef47772151b4b4666bde6c8c |
密码用明文存储, 如果你的数据库被攻击, 那么密码直接就被盗走了, 但是将密码哈希过后再存储, 即使密码被盗走了也不会有问题了. 那么为什么又会有第三种存储方式?
这里首先有一个概念叫彩虹表攻击, 彩虹表是一个预先准备好的表, 表的内容就是一些有限字符组成的固定长度的纯文本密码对应的 hash 值, 类似下面这样的表, 表的内容能达到 100G 以上, 这样就可以逆向的通过密码的 hash 找到密码的原文了.
密码 | 密码经过 MD5 算法 hash 后 |
123456 | e10adc3949ba59abbe56e057f20f883e |
432432 | d9aeba5e7bcdacec33d2504cfcbfc33b |
为了防止彩虹表攻击, 就对 hash 的明文稍微改了一下, 将密码和盐一起 hash 加密, 盐可以是一个时间, 也可以是别的什么值,
HMAC
HMAC 是一种基于 Hash 函数和密钥进行消息认证的方法
具体说就是增加一个 key 做 hash:HMAC=Hash(文件 + key)
这个 key 是双方预先都知道的.
HMAC: 可以做源认证以及完整性校验, 具体如下
同学 A 发起认证 ->到 PPPOE 服务端 ->服务端查到有保存同学 A 的用户名和密码, 返回随机数 x->同学 A 用自己的密码和随机数 x 做 hash, 将 hash 值发回给服务器 ->服务器同样做 hash, 之后比对验证.
为什么要返回一个随机数 x, 用随机数 x 和密码一起做哈希, 还是和上面说的一样, 防止彩虹表攻击.
对称加密和非对称加密结合使用
l 在对称算法中有些问题, 比如如何将同学 A 的密钥传递给同学 B, 不能做数字签名等
l 非对称算法中也有问题, 比如加密速度慢, 密文非紧凑.
因为这些优缺点, 我们应该想到, 如何将优点结合起来使用呢? 可以这样:
使用对称加密算法, 对大文件进行加密, 使用非对称加密算法对对称算法使用的密钥进行加密.
流程:
1, 同学 A 对明文进行哈希, 形成摘要 ->利用发送方 A 的私钥, 对摘要进行签名, 得到发送方签名值
2, 将明文 + 签名 + 发送方 A 的公钥或者数字证书打包起来, 使用一个随机对称密钥, 对其加密(这里使用的就是对称加密算法), 得到密文
3, 用接收方 B 的公钥对第二步中的随机对称密钥加密, 得到密钥密文, 将上一步的密文和本步骤的密钥密文打包, 形成数字信封, 发送给接收方 B
4,B 得到了两个密文, 一个是密钥密文, 一个是第 2 步骤的密文. 使用接收方 B 的私钥对密钥密文进行解密, 得到密钥.
5, 使用解开的密钥对第 2 步骤的密文进行解密. 解密得到了 3 个东西: 一个明文, 一个发送方 A 的签名, 一个发送方 A 的公钥或者数字证书.
6, 对上一步骤得到的明文进行 hash 计算, 得到摘要. 用发送方 A 的公钥对发送方 A 的签名进行解密, 得到密文中的摘要, 将两个摘要进行比对. 结果一样就说明确实是发送方 A 发的.
比特币
区块链层次与架构
层次 | 主要用到的技术 |
应用层 |
|
合约层 |
|
激励层 |
|
共识层 | 通过各种共识算法,达到共识。常用的: PoW(工作量证明)Pos(权益证明)DPOS(股份授权证明) |
网络层 | P2P 技术 |
数据层 | 密码学技术(公钥密码学) |
下三层 数据层, 网络层, 共识层是区块链的核心, 上三层就是应用层.
比特币和区块链的关系
区块链是一种技术的集合 / 思想(去中心化), 比特币是基于区块链的一种应用(移动互联网与微信的关系)
比如互联网, 最早就是诞生了 web 等应用, 后面又出现 qq, 微信, 淘宝等, 从只能传输文字, 到传输语音, 位置等. 区块链也是一样, 目前区块链交易信息是比特币, 但是也可以封装其他的内容, 将来会有各种应用, 目前最牛的只有比特币, 其次以太坊.
中心化:
目前我们做交易, 所有人的所有的交易都需要通过银行, 比如转账, 消费等; 央行可以无穷无尽印钞票, 导致通货膨胀; 银行可以随意冻结 / 没收你的资产. 所以银行就是一个中心化产物. 去中心化就是交易过程脱离银行, 完全个人对个人.
比特币就是一个完全脱离银行, 只依靠互联网运行的货币系统, 即使政府执法部门, 也无法查封或没收比特币. 比特币在人类历史上第一次用技术手段保证了私有财产神圣不可侵犯.
比特币的共识机制:
POW 工作量证明: 简单讲就是谁干的活多谁说了算
算法:
非对称密码学
比特币的特性:
硬通货: 跨境交易(包括暗网的一些黄赌毒交易, 以及正常的跨境支付汇款等)
易携带: 只需要一个私钥
隐秘性: 只暴露钱包地址; 非法用途
无货币超发: 货币紧缩(只有固定数量的比特币, 不会超发)
P2P 网络
深入理解区块链结构
区块链分为区块和链两部分
区块里面包括一笔一笔的交易, 然后将一个一个区块链接起来, 形成链式结构.
比特币的区块里面封装的是交易信息, 比如转账金额, 收款人等; 区块链还可以封装各种信息, 如证件, 私人记录, 实物资产, 留存证明等. 封装交易信息形成了比特币应用, 封装其他的信息就可以形成其他应用.
比特币结构:
每个区块包含一个区块头部和 N 个交易.
区块头部包含: 上面那个图中的版本号, 父区块哈希, Merkle 树根, 时间戳, 难度值, Nonce
版本号: 比特币的版本
父区块哈希: 区块 0 的哈希值
Merkle 树根: 区块链非常重要的数据结构, 也是一个哈希
难度值: 确保区块链不会被很快挖出来, 目前是约 10 分钟出来一个区块
时间戳: 什么时间生成的区块
Nonce: 随机数, 挖矿就是找到随机数的过程
上面都是简单说明一下, 后面有重点讲解,
比特币常用术语
去中心化的账本管理方式
每个人都有一个自己的账本, 当李四跟张三转账, 比如 100 元, 首先形成一个交易信息, 然后将这个交易信息记录到每个人的账本上, 所有人的账本自始至终是一致的. 这个账本取代了银行记账的方式.
挖矿
比特币矿工通过解决具有一定工作量的工作量证明机制问题, 来管理比特币网络 - 确认交易并且防止双重支付. 挖矿的过程就是在全网中和其他节点竞争记账的过程, 为什么要竞争记账呢? 比如上面那张图, 转账完毕, 每个人都要记账, 那么第一个记账的人就可以得到一些比特币, 所以第一个记账的人就等于挖到了矿.
百度百科: 矿工们在挖矿过程中会得到两种类型的奖励: 创建新区块的新币奖励, 以及区块中所含交易的交易费. 为了得到这些奖励, 矿工们争相完成一种基于加密哈希算法的数学难题, 也就是利用比特币挖矿机进行哈希算法的计算, 这需要强大的计算能力, 计算过程多少, 计算结果好坏作为矿工的计算工作量的证明, 被称为 "工作量证明". 该算法的竞争机制以及获胜者有权在区块链上进行交易记录的机制, 这二者保障了比特币的安全
除了上面说的奖励, 还会获得相应权利和义务: 记账的权利 (把交易记录到账本) 和广播义务(将区块全网广播)
创世区块
Block #0 2009.01.03 诞生
区块高度:
就是从 #0,#1,#2 一直加, 增加的区块数
区块深度
比如产生一个交易, 开始一段时间深度为 0, 交易可以更改 / 撤销(退换货), 隔一段时间, 深度或逐渐加深, 深度大于 6 的时候, 交易就达到了非常安全的程度, 不可再更改 / 撤销.
深度是以产生交易的区块为起点, 比如在第 10 个区块产生了这笔交易, 那么第 10 个区块就是深度 1, 第 11 个区块产生出来后就是深度 2, 第 12 个区块就是深度 3, 以此类催, 达到深度 6, 也就是创建出来第 16 个区块后, 交易就不可更改了.
交易确认
当一项交易被区块链收录后, 就是交易确认
在此区款连之后每产生一个区块, 此项交易的确认数相应加 1
比特币钱包对交易确认数有相应设置(快速 2 次确认, 非常安全 6 次确认收到钱)
UTXO 未花费的交易输出
我们都知道比特币是虚拟的, 本质上就是一串代码. 而记录比特币交易的账户模型, 就是 UTXO. 比特币系统中没有比特币, 只有 UTXO, 即系统中没有保存谁有几个比特币, 而是记录的一笔一笔的交易, 比如 A 给 B 转了 100 元, 那么区块中就多出两笔交易, 一笔是 A 减少 100 元, 一笔是 B 增加 100 元. 每一笔交易后的输出就是一个 UTXO.
举个例子, 假如我们现在钱包里有 100 块钱, 你要花 5 块钱, 然后找零 95 块. 当你拿出来 100 块大洋花出去的时候, 这 100 块就已经不能再算作 UTXO, 只有找零得到的 95 块, 才会算作 UTXO.
每笔交易都有若干交易输入, 也就是资金来源, 也都有若干笔交易输出, 也就是资金去向. 一般来说, 每一笔交易都要花费 (spend) 一笔输入, 产生一笔输出, 而其所产生的输出, 就是 "未花费过的交易输出", 也就是 UTXO. 当之前的 UTXO 出现在后续交易的输入时, 就表示这个 UTXO 已经花费掉了, 不再是 UTXO 了.
比特币存在比特币钱包中, 比特币钱包中的比特币是怎么来的呢? 是将一笔一笔的交易数加起来, 比如 A 同学先增加了 200, 又减少了 100, 又增加了 300, 那么他的比特币数量就是 200-100+300=400
比特币系统中没有账户这个概念, 也没有账户余额的概念, 只有 UTXO(被公钥锁定), 没有登录概念, 只要自己有私钥就可以使用这个比特币.
转账将消耗掉你自己的 UTXO, 同时生成新的 UTXO, 用接收 UTXO 方的公钥进行锁定.
另外还要提一下, UTXO 与传统的账户系统有什么区别. 假如有两个人, 一个是小明, 一个是小美. 小明要给小美转 100 块钱. 那么传统的账户模型是这样的: 先判断小明账户里是否有 100 块的余额, 然后在小明的账户里减少 100 块, 在小美账户里增加 100 块.
但 UTXO 的机制是这样的: 小明的账户里有 200 块钱, 他要想给小美转账, 必须将 200 块钱全部消耗掉. 所以他不仅要给小美转 100 块, 还要给自己账户转 100 块. 这样一个好处就是, 如果从第一个区块开始逐步计算所有比特币地址中的余额, 就可以计算出不同时间的各个比特币账户的余额了
比特币交易锁定与解锁全过程
交易的输出(UTXO), 包含两个东西:
l 锁定的比特币数量
l 锁定脚本(用接受者公钥的哈希)
只要接收者才能有权利花费这笔比特币, 所以用接收者的公钥进行锁定, 但是为了更安全, 比特币是用的公钥的哈希值加密的这笔比特币.
交易的输入(UTXO + 解锁脚本)
l 解锁脚本(签名和发送者公钥)
比特币锁定 / 解锁脚本工作过程
B 打算向 C 转 10 个比特币, 怎么判断 B 有权利花掉这 10 个比特币?
第一步, 判断锁定脚本: B 会提供一个 B 私钥签名和一个 B 公钥, 系统将 B 公钥进行 hash, 和锁定脚本那种的 B 公钥哈希如果相同, 就证明 B 提供的确实是 B 的公钥.
第二步, 用 B 的公钥解 B 的私钥签名, 如果能解开, 就证明确实是 B 的私钥做的签名, B 确实有私钥.
再举一个例子, 下面这个例子, 假设交易手续费为 0:
1, 用户 A 挖矿获得了 12.5BTC
这里的 12.5btc UTXO 用旷工 A 的公钥哈希进行锁定(加密)
注意: 刚挖到的比特币要 100 个区块确认后才能花.
2, 第一个交易: A 向 B 和 C 各转 5 BTC
B 多了 5 BTC 的 TUXO, 用 B 的公钥哈希进行锁定
C 多了 5 BTC 的 UTXO, 用 C 的公钥哈希进行锁定
A 去掉原来有的 12.5 的 UTXO, 换成 2.5 的 UTXO, 用 A 的公钥哈希进行锁定
3, 第二个交易: B 向 C 转 2 个 BTC
B 去掉原来的 5 BTC 的 UYXO, 改成 3BTC 的 UTXO, 仍然用 B 的公钥哈希进行加密锁定
C 多一个 2 BTC 的 UTXO
4, 第四个交易 :C 向 B 转 6 BTC
C 转给 B 之前有一个 5BTC, 一个 2BTC, 要给 B 6BTC, 就会将原来的 5 和 2BTC 的 UTXO 全部删掉, 换成 1BTC 的 UTXO 用 C 的公钥哈希加密和 6BTC
以及给 B 的 6BTC 的 UTXO 用 B 的公钥哈希加密
经过上面一些交易, 最后剩下的 UTXO, 就只有步骤 2 中 A 的 2.5BTC, 步骤 3 中 B 的 3BTC 和步骤 4 中 B 的 6BTC 以及 C 的 1BTC. 此时比特币的总和依然是最开始旷工 A 挖矿挖出来的 12.5.
交易的传播与验证
交易
交易包含两部分: 输入 n 和输出 m.n>=0,m>0
输入: 要被花费的 UTXO + 解锁脚本(私钥签名 + 公钥)
输出: 一个或多个 UTXO(币值 + 锁定脚本(公钥的哈希))
n>=0 怎么理解呢? 第一笔交易, 例如上面那个例子中的旷工 A, 挖矿得到奖励, 是没有输入的, 只有输出, 此时就是 n=0 的情况. 其他的交易都是 n>0 的情况, 你要花钱首先得有钱. 所以除了第一笔那样的交易, 其他的交易都包含两部分, 输入和输出.
m>0: 输出就是你买东西或者转账等, 给人家钱, 不可能给 0
交易传播与验证过程:
钱包软件生成交易, 并向邻居节点传播
节点对收到的交易进行验证, 并丢弃不合法交易
交易的 size 要小于区块 size 的上限
交易输入的 UTXO 是存在的(向全节点的 UTXO 数据库检索)
交易输入的 UTXO 没有被其他交易引用, 防止双花
输入的总金额>= 输出总金额
验证解锁脚本
将合法的交易加入本地 Transaction 数据库中, 并发送给临近节点.
区块的生成与连接
旷工在挖矿前要组件区块
1, 将 coinbase 交易打包进区块(每个区块的第一笔交易都是这个, 旷工挖矿挖来的 12.5BTC)
2, 将交易池中高优先级的交易打包进区块
优先级: 交易额度 * UTXO 深度 / 交易 size(类比银行)
交易 size: 防止粉尘攻击(类似银行的存款期限, 存起来不经常动, size 就小)
UTXO 深度: 防止频繁转账攻击(很久没有转账的深度更大, 转账越频繁的深度越小)
创建区块头部
区块链:
区块 0-- 区块 1-- 区块 2-- 区块 3....
区块 1 的父区块哈希是区块 0 的区块哈希
区块 2 的父区块哈希是区块 2 的区块哈希
...
这样一来只要中间有一个交易信息改变, 会导致他后面的所有区块都要变.
算出随机数 Nonce, 意味着挖矿成功, 之后将计算出来的随机数 nonce 填入区块头部, 向邻近节点传播(接力赛)
区块 0 存储的信息:
当时正是英国财政大臣第二次出手疏解银行危机之时, 表示对中心化银行和政府的不满.
相邻节点收到新区块后, 立即做如下检查:
验证 POW 的 nonce 值是否符合难度值
检查时间戳是否小于当前时间 2 小时
检查 Merkle 树根是否正确
检查区块 size 要小于区块 size 上限
第一笔交易必须是 coinbase 交易
验证每个交易
比特币代码网站: http://btc.yt/lxr/satoshi/ident?_i=CheckBlock
二叉树与 Merkle 树
树: 由多个节点组成的一种数据结构, 每个节点存储数据, 节点包括: 根节点, 父节点, 子节点, 兄弟节点
特殊树: 二叉树(方便查找)
比如有数据: 12,5,2,18,19,15,17,16,9
如下图, 第一个数 12, 放到顶端; 5 小于 12, 放到左边, 2 小于 12, 到左边, 小于 5, 放到 5 的左边, 18 大于 12, 放右边, 19 大于 12, 大于 18, 放 18 右边...
Merkle 树作用
防止数据篡改(节点存储 Hash 值)
快速验证某个交易是否存在
从叶子节点构造树
Merkle 树存储的是交易信息的哈希, 比如现在有三笔交易信息: a,b,c, 将这三笔交易做哈希得到 Ha,Hb,Hc, 就会如图中所示, 将 Ha 和 Hb 再次哈希, 生成 Hab, 因为没有 Hd, 所以将 Hc 和 Hc 做哈希, 生成 Hcc, 然后再将 Hab 和 Hcc 哈希, 生成根节点.
如何防止数据篡改的? 任何一个交易的改变, 交易的哈希就会改变, 那么上层所有的哈希都会变, 比如 Ha 改变了, 那么 Hab 也会改变, root 也会变. 所以只要根节点哈希值没变, 和头部的 Merkle 树根一致, 那么就可以保证交易都没有被篡改.
怎么验证区块是否在交易里面?
比如 a 那笔交易是张三给李四转钱的交易, 如何验证这笔交易在这个区块里, 就用 a 这笔交易的哈希 Ha 跟他兄弟节点 Hb 做哈希, 得到 Hab, 再用 Hab 和他兄弟节点 Hcc 做哈希, 得到根节点, 判断根节点和头部的 Merkle 树根一致, 就说明这个交易在这个区块中.
root 就是头部的 Merkle 树根, Merkle 树根是负责一个区块内部的所有交易的 hash, 父区块哈希是区块和区块之间的 hash. 父区块哈希是防止整个区块被篡改.
比特币存在的问题
比特币网络拥堵
跟 P2P 没有关系, 跟底层区块链有关系, 因为区块每 10 分钟生成一个导致的. 每 10 分钟就会有一个新的区块被 "挖掘" 出来, 每个区块里包含着从上一个区块产生到目前这段时间内发生的所有交易, 这些交易被依次添加到区块链中. 由于每次矿工在打包新区块时, 最多也就能打包几千条交易信息. 所以以前交易量没那么多时, 一般等到下一个区块打包完, 就能到账了, 也就是 10 分钟左右就到账了; 但是一旦交易量上去了, 那么对不起, 这次甚至下次打包新区块时, 估计都不能打包上这笔新交易了. 因为前面还有好多交易都在排着队等着被打包被验证呢!
为什么一个区块最多只能打包几千条信息?
现在一个区块的大小差不多是 1MB, 也就是 1000KB, 可以把一个区块比做一个书包的大小. 一笔交易差不多是 250B, 也就是 0.25KB, 可以把一笔交易比做一根铅笔的大小. 现在要往 1000KB 的书包里放 0.25KB 的铅笔, 能放多少根笔? 不难算出, 是 4000 根:
即, 一个区块, 最多也就包含差不多 4000 笔交易.
交易费用昂贵
交易费用给的高, 会被优先处理, 因为网络拥堵, 速度慢, 交易费用也会更高
以太坊的出现, 也会成为比特币发展的阻碍
因为有上面的这些问题, 所以目前正在考虑比特币扩容
比特币扩容
有人会问: 书包太小了, 换个大书包吧!
也有人会说: 交易能不能压缩一下啊, 铅笔再小一点!
没错, 这些都是解决目前交易拥堵的方式. 即:
1. 扩大区块的大小, 从 1MB 提升到 2MB 甚至 4MB 甚至更大.
2. 交易压缩, 将没用的信息去掉, 节约每笔交易的空间, 好让区块里能存放更多的交易.
对于第一个解决方案, 扩大区块大小, 从几年前起, 比特币社区, 矿场, 比特币主要核心开发人员之间就开始讨论了. 吴忌寒等旷工团队主张扩容, 但核心开发人员反对将区块扩容.
对于第二个解决方案, 人们确实找到了可以压缩交易的方法, 压缩的方式有两种:
1)存储一半的公钥.
这是因为私钥在生成公钥时, 采用的是椭圆曲线加密法, 最开始人们都没当回事, 后来受交易拥堵的影响, 有人关注到, 因为是椭圆算法的, 所以是对称的, 所以只需要存储一半的公钥, 就能表达出之前的意思, 这样既没有什么影响, 又能节省空间, 让一个区块包含更多的交易, 何乐而不为? 于是大家就开始接受压缩公钥的方式了.
2)隔离见证, 即将一笔交易的交易部分和签名部分拆开.
开发者们发现, 一笔 0.25KB 的交易记录中, 实际交易信息占了一小部分, 还有一部分叫做签名信息, 这签名信息占了一大部分, 于是开发者们把签名信息从交易记录中剥离出去, 单独开发了一块空间存储签名信息. 于是之前一个区块里包含了众多交易的交易信息和签名信息, 现在一个区块里只需要包含这些交易记录的交易信息就好了, 签名信息在另一个附属的块中捆绑在区块上, 一并发给其他矿工. 这样的话, 也能节省出来一部分空间.
针对隔离见证, 旷工和核心开发团队们有过两次共识, 第一次共识, 是 2016 年 2 月在香港的会议, 称为香港共识: Core 团队的代表同意在实施隔离见证后, 区块大小扩容到 2M.(前提是 95% 以上的算力旷工支持)
第二次共识, 2017 年 5 月的纽约会议, 称为纽约共识: 全网 80% 算力的矿主达成 Segwit(隔离见证)2x 扩容, 意思是只要 80% 以上的矿主同意扩容, 就将区块大小扩容到 2M.
BIP: 意思是比特币改进建议, 针对扩容就搞了如下几个 BIP:
BIP141(95% 支持就实施)+BIP 91(80% 支持即可)+BIP102(升级到 2M)
这里就看出去中心化的一点缺点: 没有中心, 没有权威, 大家都可以说话, 意见统一起来就很困难, 就比如这次扩容, 搞了三个 BIP, 来回开会, 才有一点结论出来.
Core 团队反对扩容区块的原因:
不愿意轻易更改系统, 比如银行仍使用 COBOK 语言编写的系统
防止个人不能运行全节点, 因为每个区块太大了, 总体容易激增(违背去中心化)
增加到 2M 没太大作用, 主推 闪电网络 / 侧链 解决交易拥堵
闪电网络 / 侧链 : 闪电网络的主要思路十分简单 -- 将大量交易放到比特币区块链之外进行. 核心的概念主要有两个: RSMC(Recoverable Sequence Maturity Contract)和 HTLC(Hashed Timelock Contract). 前者解决了链下交易的确认问题, 后者解决了支付通道的问题.
简单说一些交易没必要上主网络, 在链下解决就足够了. 中心化和去中心化结合.
旷工反对的原因
闪电网络将会导致交易中心化, 违背比特币点对点交易的初衷
闪电网络属于 BlockStream 公司, 大多数 Core 团队成员是 BlockStream 雇员.
如果将来绝大部分交易都在闪电网络 / 侧链, 旷工会损失交易费
Core 垄断了海外论坛, 利用社区影响力封杀反对 core 的开发者和社区成员
BCC 分叉
因为上面的一些原因, 就有人搞出来比特币的分叉, 目前主要有 BU 团队, BitcoinABC 团队.
BU 团队:
比特币无限大小: 放开区块大小限制, 一次能处理足够的数据, 提升网效率
BU 方案曾经获得全网 40% 算力支持
代码 BUG 太多, 未能获得社区广泛支持
BitcoinABC 团队, 团队成员还是来自 BU 团队:
基于 BU 代码, 打造了 BCC,2017.08.01 执行硬分叉(ViaBTC 推动)
BCC 没有 Segwit, 区块容量 8M
BCC 官网: https://www.bitcoincash.org/
比特币分叉
针对扩容有两种解决方案: 软分叉(修辅路, 侧链), 硬分叉(重新修条更宽的路)
软分叉:
是在原来基础上进行优化, 将区块提高到 2M,8M,16M, 以 SegWit 闪电网络未主流解决方案. 链上的一部分升级到软分叉后, 即使有些没有升级的, 可以互相兼容, 最终还是在一条链上.
硬分叉:
通过升级系统, 改变代码, 彻底解决扩容问题, 以 BU 为主流解决方案. 不能兼容以前的方案. 所以这个链会分成两个链, BTC/BCH,ETC/ETH.
扩容是指硬分叉, 隔离见证指的是软分叉.
比特币和以太坊都进行了硬分叉. BTC BCH ETC ETH
莱特币 利用隔离见证进行软分叉
临时分叉:
仅发生在几乎同时爆块 (同时找到满足条件的随机数) 的情况, 这种分叉是暂时的
链分叉后, 继续挖矿, 挖着挖着就会出现有一个链长一个链段的情况. 根据共识机制, 旷工最终会切换到最长链上继续挖矿
短链上的交易全部无效, 爆块旷工费(旷工费无效)
短链上的旷工就重新到长链上继续挖矿
比特币的三个地址
私钥地址
私钥地址可以产生公钥和比特币地址
只需要保存私钥, 就能够花费对应地址上的比特币
私钥的本质是随机数(比特币私钥 256 位)
私钥总数是 2256, 数据量超过了宇宙中原子总数, 很难遍历所有私钥.
比特币私钥是安全的, 并不是说不可能出现重复的私钥, 而是说不可能通过遍历的方式找到某一个特定的私钥.
比特币私钥地址 WIF(Wallet Import Format)
私钥的格式:
私钥前缀 80 + 私钥本体 + 后缀(压缩私钥后缀是 01, 非压缩私钥无后缀)+ 校验
压缩私钥 (76 位十六进制 2+64+2+8) <=>(52 位 Base58):
非压缩私钥 (74 位十六进制 2+64+8) <=>(51 位 Base58):
如何生成 WIF 私钥:
第一步, 随机选取一个 32 字节的数, 大小介于 1 ~ 0xFFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFE BAAE DCE6 AF48 A03B BFD2 5E8C D036 4141 之间, 作为私钥.
private_key= bytes.fromhex('0C28FCA386C7A227600B2FE50B7CAE11EC86D3BF1FBE471BE89827E19D72AA1D01')
第二步, 添加前缀 0x80
rk = b'\x80' + private_key
第三步, 取两次哈希的前 4 个字节(8 位十六进制), 作为校验值添加在后面
- checksum = hashlib.sha256(hashlib.sha256(rk).digest()).digest()[0:4]
- rk = rk + checksum
最后用 Base58 表示法转换一下
return base58.b58encode(rk)
如果运算正确, 得出的私钥值应该是:
KwdMAjGmerYanjeui5SHS7JkmpZvVipYvB2LJGU1ZxJwYvP98617
第一步的 64 字符是标准格式私钥 256bit,64 个字符.
WIF 格式私钥更短, 是经过 Base58 编码得到的, 叫作压缩格式私钥, 以 K 或 L 开头, 大小是 52 个字符.
未压缩格式私钥: 5 开头, 大小 51 个字符
生成自己私钥的方法:
通过某些私钥生成网站, 会存在安全性问题
掷骰子, 16 面的扔 64 次
用中文, 英文, 或汉语拼音的哈希值
http://www.fileformat.info/tool/hash.htm
公钥地址
是由私钥, 通过椭圆曲线加密算法 (ECC) 生成, 是一个 65byte 数组
压缩公钥是 02 或 03 开头 66 位(2+64):
非压缩公钥是 04 开头 130 位十六进制(2+64+64):
注意它们的第二行内容完全一样
公钥的生成:
钱包地址
钱包地址的生成过程:
1,3935a3e3751b68e04(自己随机产生一个数)(或者是生成一个助记词)
2, 填充, 得到 256bit 的私钥(private_key):
000000000000000000000000000000000000000000000003935a3e3751b68e04
3, 对私钥进行椭圆曲线算法加密(SECP256k1), 得到 64 字节的公钥(public_key):
e8977d298d194929e92b1a87a37f232f8838aaa3e14746217c46def324d7577ca273075eb4edb98c18a6e27c4549aca44620aef4567bfb35d942e7ba0edce75f
4, 添加 0x04 头(以 0x04 开头的公钥标记这是没有经过压缩的公钥), 长度变为 65 字节:
04e8977d298d194929e92b1a87a37f232f8838aaa3e14746217c46def324d7577ca273075eb4edb98c18a6e27c4549aca44620aef4567bfb35d942e7ba0edce75f
5, 对步骤 4 的公钥作 sha256 哈希加密, 得到如下摘要(长度为 32 字节):
ac40cc78422db4050f1a99c2e539a68eca62b8c8c3496c330d588d2ed794e140
6, 对步骤 5 的数据作 ripemd160 哈希加密, 得到公钥 hash(长度 20 字节):
e2d12b1c117fe64cb868a81ee3a61c74b64c59ed
以下步骤展示公钥 hash 生成钱包地址的过程:
7.1, 假设 tem_hash = SHA256(SHA256(0x00 + 公钥 hash)), 取 tem_hash 前 4 个字节: f3891721
7.2,checksum = f3891721
7.3,0x00 + 公钥 hash + checksum:
00c8db639c24f6dc026378225e40459ba8a9e54d1af3891721
7.4, 将 7.3 中的字节流进行 base58 的转换, 得到钱包地址:
1MgJHdTuHkyZ6gzzMQGkZHd4CPn6joU5GL
注: 钱包地址与公钥 hash 从转换来看, 完全可以互逆, 所以大部分情形下二者是等价的, 只是表现形式不一样而已.
轻钱包
轻钱包是比特币的非全节点, 存储空间有限, 只存储区块的头部, 空间只有 80 字节, 区块本身大小: 1M,8M
SPV 简单支付验证(Simplified Payment Verification), 这个概念出现其实很简单, 以比特币为例子, 目前节点如果存储完整的区块链数据那么有几百 G, 一般的个人终端上无法满足这个量级的存储空间, 而且这个数据量还会一直增加, 那么针对个人的终端需要一种简单的验证模式, 相应就出现了 SPV, 比如 MultiBit 这种轻量级钱包用的就是 SPV 模式.
轻钱包只存储区块头部, 不存储区块信息, 但是 UTXO 在区块内, 所以如果想要交易, 必须向邻近的全节点的区块链发送交易信息.
轻钱包的 SPV 验证
当 SPV 节点收到一个交易请求, 其实节点是无法证实对端节点的可靠性的, 那么在一个交易发起过程中, 一般会包括对端节点的支付 UTXO, 对端节点的签名, 交易金额, SPV 节点的地址. SPV 节点验证通过支付验证, 检查区块头信息来确认发生这个交易的是否在区块链中, 并且在当前的区块链系统中有多少区块进行确认. 这里啰嗦下区块头, 区块头中包括 prev_block_hash 和 merkle_root_hash 这两个最为重要的验证值.
1.SPV 节点通过 getheaders 从相邻的全数据节点获得区块头信息(这里涉及一个问题, SPV 对特定的几个交易选择读取, 无疑会透露钱包地址信息)
2. 计算当前交易的 HASH 值.
3. 用计算后后的 HASH 值, 去比对定位 block head, 确定是否存在目前的最长一条链接上.
4. 从区块中获取构建 merkle tree 所需的 hash 值, 并计算 merkle_root_hash
5. 计算结果如果一致说明交易真实存在.
6. 根据 block header 来确认有多少区块确认交易.
什么是挖矿 / 矿池
挖矿:
以抛硬币为例:
正面朝上: 1
反面朝上: 0
立起来: X
谁抛出如下组合, 奖励 50 比特币:
11110000XX11110000XXXXXXX0101010101X01X1010X..
利用电脑 CPU 跑程序计算, 一秒抛 2 次, 专用 GPU 显卡, 一秒抛 200 次
单位时间抛硬币次数可以理解成算力, 算力越大, 抛中可能性越大.
挖矿就是寻找上面的组合的过程.
矿池
挖矿的本质: 维护比特币网络, 大家得记账, 不能白记, 得给奖励, 最初奖励 50 个比特币, 每 4 年减半.
比特币挖矿: 消耗计算机 + 电力
黄金挖矿: 消耗人力
挖矿底层机制
比特币系统里为什么要设计挖矿?
增加恶意行为的成本. 比如黑客, 想要挖矿, 必须去购买很多大型设备
争夺记账权利, 获取奖励(总共 2100 万枚比特币, 都是靠挖矿来挖来的)
挖矿流程图
挖矿难度调整
每 2016 个区块调整难度
新目标值 = 当前目标值 *(过去 2016 区块用时分钟 / 20160 分钟)
目标值与难度值成反比(计算公式异常复杂)
区块链共识算法和激励机制
什么是区块链共识机制?
区块链具备: 去中心化特性
没有类似银行的记账机构, 全网节点怎么打成共识 / 一致?
POW: 通过评估你的工作量来决定你获得记账权的概率, 算力越大, 记账几率大 --- 比特币
POS: 通过评估你持有代币数量和时长, 决定你记账的几率 (币天)--- 点点币
不浪费电力 51% 攻击更难
POW+POS: 用 POW 发行新币, 用 POS 维护区块链网络安全
DPOS: 选定 "人大代表" 记账 ---EOS 选 21 个根节点记账, 委托选出来的这 21 个代表去记账, 其他的人不能记.
比特币共识机制 工作量证明 POW
怎么证明你英语好 / 网络牛人? CET6/CCIE 证书
POW(Proof of Work)
通过付出大量的工作代价来证明自己是非恶意节点
计算出一个难题的随机数答案(nonce), 如同掷骰子
获取记账权利
打包交易并通知其他节点
POS(Proof of Stake) 股权证明机制
POS 根据你持有代币的量和时间(币天), 给你发利息的一个制度
比如你持有 100 个币, 总共持有了 30 天, 那么, 此时你的币天就为 3000
如果你发现了一个 POS 区块, 你的币天就会被清空为 0
你每被清空 365 币天, 你将会从区块中获得 0.05 个币的利息
假定利息可理解为年利率 5%, 利息 = 3000 * 5% / 365 = 0.41 个币
问题: 大股东控制, 造成中心化. 人性: 有钱人犯罪率低
总结
POW 通过挖矿奖励, 交易费激励大家维护比特币节点
POS 则由大股东负责维护区块链节点, 产生利息
DPOS 选举 "人大代表" 记账, 维护区块链
拜占庭将军问题
拜占庭将军问题 (Byzantine failures), 是由莱斯利. 兰伯特(Leslie Lamport) 提出的点对点通信中的基本问题.
拜占庭问题的最初描述是: n 个将军被分隔在不同的地方, 忠诚的将军希望通过某种协议达成某个命令的一致(比如一起进攻或者一起后退). 但其中一些背叛的将军会通过发送错误的消息阻挠忠诚的将军达成命令上的一致. Lamport 证明了在将军总数大于 3m, 背叛者为 m 或者更少时, 忠诚的将军可以达成命令上的一致.
背景:
拜占庭帝国派出 10 支军队, 去包围一个强大的敌人
至少 6 支军队同时进攻才能攻下, 不然会失败, 损兵折将
难题: 一些将军可能是叛徒, 会发布假的 (相反的) 进攻意向
目的: 将军需要找到一种共识机制, 可以远程协商, 一起进攻 / 不进攻
解决方案 PBFT (Practical Byzantine Fault Tolerance, 实用拜占庭容错算法)
每个节点向所有其他节点发送消息
每个节点根据收到的所有消息来决定最终的策略
缺点: 每个节点向全网节点发送大量的消息, 因为这个缺点, 所以不适合在比特币世界里用, 容易造成网络堵塞.
这个算法有解前提: n>=3m+1(n 为将军总数, m 为叛徒数量)
m<= ( n-1 )/3
整理了一下前段时间学习的区块链的视频内容, 老师讲的挺好的, 感觉确实理解了很多
来源: https://www.cnblogs.com/sy_test/p/12381489.html