深入理解区块链 - 第1章:信任问题的本质
学习目标
通过本章学习,你将彻底理解:
- 为什么人类社会需要信任机制
- 传统信任机制的局限性和问题
- 数字世界面临的特殊信任挑战
- 密码学如何为区块链提供数学基础
- 去中心化如何从根本上解决信任问题
学习原则
- 从问题出发:先理解问题,再理解解决方案
- 深入本质:不仅要知其然,更要知其所以然
- 建立联系:理解各个概念之间的内在联系
- 思考验证:每学一个概念,都要问"为什么"
第一部分:信任的本质
1.1 什么是信任?
信任是人类社会运行的基础。但信任到底是什么?
定义:信任是相信对方会按照承诺行事,即使你无法监督。
这个定义包含三个关键要素:
- 承诺:对方做出了某种承诺
- 不确定性:你无法完全监督对方是否履行
- 相信:你选择相信对方会履行
生活中的信任例子
例子1:借钱给朋友
- 你借给朋友1000元,约定下个月还
- 你相信他会还,但你没有法律保障
- 如果他跑了,你怎么办?
- 信任成本:可能损失1000元
例子2:网上购物
- 你在网上买东西,先付钱给商家
- 你相信他会发货,但你没有见到商品
- 如果他收了钱不发货,你怎么办?
- 信任成本:可能损失货款
例子3:银行存款
- 你把钱存银行,银行承诺会还给你
- 你相信银行会还,但钱不在你手里
- 如果银行倒闭了,你怎么办?
- 信任成本:可能损失存款
信任的核心矛盾
信任的核心矛盾是:
- 需要信任:因为无法完全监督
- 信任有风险:因为对方可能违约
- 必须信任:因为社会需要合作
这个矛盾,就是区块链要解决的根本问题。
1.2 传统社会如何建立信任?
人类历史上有三种主要的信任机制:
方法1:法律和制度
原理:
- 通过法律强制对方履行承诺
- 如果违约,可以起诉
- 有政府强制执行
优点:
- 有强制力
- 相对公平
- 适用范围广
缺点:
- 需要第三方(法院、警察)
- 成本高(律师费、时间成本)
- 时间长(诉讼可能需要几年)
- 可能不公平(法律可能偏向某些群体)
- 依赖政府(如果政府腐败,法律失效)
本质问题:
- 仍然需要信任第三方(政府、法院)
- 如果第三方作恶,整个系统失效
方法2:声誉机制
原理:
- 如果违约,声誉受损
- 以后没人相信你
- 长期损失大于短期收益
优点:
- 成本低(不需要第三方)
- 速度快(立即生效)
- 自执行(违约自动惩罚)
缺点:
- 只在小范围内有效(熟人社会)
- 陌生人之间无效
- 可以造假(可以伪造声誉)
- 无法量化(不知道声誉值多少钱)
本质问题:
- 依赖社会网络
- 如果社会网络断裂,机制失效
方法3:第三方担保
原理:
- 银行担保交易
- 支付宝担保支付
- 公证处证明文件
优点:
- 降低信任成本
- 提高交易效率
- 有专业保障
缺点:
- 依赖第三方
- 第三方可能作恶
- 第三方可能倒闭
- 需要支付费用
本质问题:
- 把信任问题转移给第三方
- 但第三方本身也需要被信任
1.3 传统信任机制的根本问题
通过分析三种传统信任机制,我们发现一个共同的问题:
都需要信任第三方
无论是法律、声誉还是担保,最终都依赖某个第三方:
- 法律依赖政府
- 声誉依赖社会网络
- 担保依赖担保机构
如果第三方失效,整个信任机制失效
这就是传统信任机制的根本问题:
- 单点故障:第三方失效,系统失效
- 单点控制:第三方可以作恶
- 信任成本:需要持续信任第三方
第二部分:数字世界的信任危机
2.1 数字世界的特殊性
数字世界和物理世界有一个根本区别:
数字可以被完美复制
在物理世界:
- 你给朋友一本书,你就没有这本书了
- 你给朋友100元,你就没有这100元了
在数字世界:
- 你复制一个文件给朋友,你还有这个文件
- 你复制一个数字给朋友,你还有这个数字
这个区别带来了三个核心问题。
2.2 问题1:如何证明"我是我"?
在物理世界,你可以:
- 出示身份证
- 签名
- 按指纹
但在数字世界:
- 身份证可以伪造(PS)
- 密码可以泄露
- 生物识别可以复制
传统解决方案:
- 用户名 + 密码
- 手机验证码
- 生物识别
问题:
- 密码可以泄露
- 手机可以丢失
- 生物识别可以复制
- 都需要信任服务器(服务器可以作恶)
本质问题:
- 数字身份无法像物理身份那样"唯一"
- 需要依赖中心化服务器验证
2.3 问题2:如何防止数据被篡改?
在物理世界:
- 纸质文件修改会留下痕迹
- 可以对比原件和副本
但在数字世界:
- 数据可以完美复制
- 修改不会留下痕迹(除非有日志)
- 无法区分原件和副本
传统解决方案:
- 存在服务器上
- 有备份
- 有日志
问题:
- 服务器可以被攻击
- 管理员可以修改
- 备份也可以被修改
- 日志也可以被删除
本质问题:
- 数字数据无法像物理数据那样"不可篡改"
- 需要依赖中心化服务器保护
2.4 问题3:如何防止双重支付?
这是数字世界特有的问题,也是区块链要解决的核心问题之一。
2.4.1 什么是双重支付?
定义:双重支付(Double Spending)是指同一笔钱被花费两次或多次。
生活中的类比:
想象一下,你有一张100元的现金:
- 你给朋友A 100元,现金就没了
- 你不能再给朋友B 100元(因为你没有现金了)
- 物理世界:现金是唯一的,给出去就没了
但在数字世界:
- 你有一个数字文件,代表100元
- 你可以完美复制这个文件
- 你可以同时给朋友A和朋友B各100元
- 但实际你只有100元
- 数字世界:数字文件可以完美复制,如何防止?
2.4.2 为什么数字世界容易出现双重支付?
核心原因:数字文件可以完美复制
物理资产:
- 现金:给出去就没了,无法复制
- 商品:给出去就没了,无法复制
- 物理资产是"唯一"的
数字资产:
- 数字文件:可以完美复制
- 数字数据:可以完美复制
- 数字资产不是"唯一"的
具体例子:
例子1:数字文件
你有一个文件:money.txt
内容:"100元"
你可以:
1. 复制这个文件:money_copy.txt
2. 给朋友A发送:money.txt
3. 给朋友B发送:money_copy.txt
4. 两个朋友都收到"100元"
5. 但你实际只有100元
问题:如何防止这种情况?
例子2:数字代币
你有一个数字代币:token_001
代表:100元
你可以:
1. 复制这个代币:token_001_copy
2. 给商家A发送:token_001(购买商品)
3. 给商家B发送:token_001_copy(购买商品)
4. 两个商家都收到"100元"
5. 但你实际只花了100元,却买了200元的商品
问题:如何防止这种情况?
例子3:数字签名
你有一个数字签名:signature_001
代表:授权支付100元
你可以:
1. 复制这个签名:signature_001_copy
2. 给银行A发送:signature_001(支付100元)
3. 给银行B发送:signature_001_copy(支付100元)
4. 两个银行都扣款100元
5. 但你实际只授权支付100元
问题:如何防止这种情况?
2.4.3 双重支付的攻击场景
场景1:简单双重支付
攻击者:Alice
目标:用100元买200元的商品
步骤:
1. Alice有100元(数字文件)
2. Alice复制这个文件:100元_copy
3. Alice给商家A发送:100元(买100元的商品)
4. Alice给商家B发送:100元_copy(买100元的商品)
5. 两个商家都收到"100元"
6. Alice用100元买了200元的商品
结果:攻击成功,Alice获利100元
场景2:网络延迟攻击
攻击者:Alice
目标:利用网络延迟进行双重支付
步骤:
1. Alice有100元
2. Alice同时向两个商家发送支付请求:
- 向商家A发送:支付100元(网络路径1)
- 向商家B发送:支付100元(网络路径2)
3. 由于网络延迟,两个商家可能在不同时间收到
4. 如果两个商家都接受,双重支付成功
结果:如果网络同步不及时,攻击可能成功
场景3:分叉攻击
攻击者:Alice
目标:利用区块链分叉进行双重支付
步骤:
1. Alice有100元
2. Alice在链A上:支付100元给商家A
3. Alice在链B上:支付100元给商家B(分叉)
4. 如果两条链都被接受,双重支付成功
结果:如果网络分叉,攻击可能成功
2.4.4 传统解决方案
方案1:中心化账本(银行)
原理:
- 所有交易记录在银行的中心化账本
- 每次支付,银行检查余额
- 如果余额不足,拒绝支付
流程:
1. Alice要支付100元给商家A
2. 银行检查:Alice余额 = 100元
3. 银行记录:Alice余额 = 0元,商家A余额 += 100元
4. Alice要支付100元给商家B
5. 银行检查:Alice余额 = 0元
6. 银行拒绝:余额不足
优点:
- 简单有效
- 可以防止双重支付
缺点:
- 依赖银行(单点故障)
- 银行可以修改记录(单点控制)
- 银行可以拒绝服务
- 银行可能倒闭
方案2:时间戳服务器
原理:
- 使用时间戳服务器记录交易时间
- 如果发现同一笔钱在相近时间支付两次,拒绝
流程:
1. Alice要支付100元给商家A
2. 时间戳服务器记录:时间T1,Alice支付100元给商家A
3. Alice要支付100元给商家B
4. 时间戳服务器检查:发现时间T1已经支付过
5. 时间戳服务器拒绝:已经支付过
优点:
- 可以检测双重支付
缺点:
- 依赖时间戳服务器(单点故障)
- 时间戳服务器可以修改记录
- 如果时间戳服务器被攻击,系统失效
方案3:数字现金系统(DigiCash等)
原理:
- 使用盲签名等技术
- 银行签名后,用户可以使用
- 但银行不知道用户如何使用
流程:
1. Alice从银行获得签名的数字现金
2. Alice可以使用这个数字现金
3. 银行无法追踪使用情况
优点:
- 保护隐私
缺点:
- 仍然依赖银行
- 无法完全防止双重支付
- 系统复杂
传统方案的根本问题:
-
依赖中心化机构:
- 银行、时间戳服务器等
- 单点故障、单点控制
-
无法完全防止:
- 如果中心化机构被攻击
- 如果中心化机构作恶
- 双重支付仍然可能发生
-
信任成本高:
- 需要信任中心化机构
- 如果机构失效,系统失效
2.4.5 区块链如何解决双重支付?
核心思想:去中心化账本 + 共识机制
方案1:UTXO模型(比特币)
原理:
- 每笔交易使用UTXO(未花费的交易输出)
- 每个UTXO只能使用一次
- 如果UTXO已被使用,再次使用会被拒绝
流程:
1. Alice有UTXO_001(100元)
2. Alice要支付100元给商家A:
- 使用UTXO_001作为输入
- 创建新的UTXO_002(100元给商家A)
- UTXO_001被标记为"已花费"
3. Alice要支付100元给商家B:
- 尝试使用UTXO_001作为输入
- 系统检查:UTXO_001已被使用
- 系统拒绝:UTXO已被花费
优点:
- 完全防止双重支付
- 不依赖中心化机构
- 公开可验证
关键:
- 所有节点都有完整的UTXO记录
- 需要网络共识确认UTXO是否被使用
方案2:账户模型(以太坊)
原理:
- 每个账户有余额
- 每次支付,检查余额
- 如果余额不足,拒绝支付
流程:
1. Alice账户余额 = 100元
2. Alice要支付100元给商家A:
- 检查余额:100元 >= 100元
- 更新余额:Alice = 0元,商家A = 100元
3. Alice要支付100元给商家B:
- 检查余额:0元 < 100元
- 拒绝支付:余额不足
优点:
- 简单直观
- 完全防止双重支付
关键:
- 所有节点都有完整的账户状态
- 需要网络共识确认状态更新
方案3:共识机制保证
原理:
- 所有节点共同维护账本
- 通过共识机制确认交易
- 如果发现双重支付,拒绝
流程:
1. Alice广播交易A:支付100元给商家A
2. 节点验证:
- 检查余额/UTXO
- 如果有效,接受
3. Alice广播交易B:支付100元给商家B(双重支付)
4. 节点验证:
- 检查余额/UTXO
- 发现已被使用
- 拒绝交易B
5. 网络共识:
- 所有节点都拒绝交易B
- 只有交易A被确认
优点:
- 完全防止双重支付
- 不依赖中心化机构
- 网络共识保证
关键:
- 需要网络共识
- 如果网络分叉,可能暂时出现双重支付
- 但最终只有一条链被接受
2.4.6 区块链防止双重支付的机制
机制1:交易验证
每个节点在接收交易时验证:
1. 检查输入是否有效:
- UTXO是否存在?
- UTXO是否已被使用?
- 签名是否有效?
2. 检查输出是否合理:
- 输出金额是否合理?
- 输入金额 >= 输出金额?
3. 如果发现双重支付:
- 拒绝交易
- 不广播给其他节点
机制2:区块确认
交易被打包到区块后:
1. 区块包含所有交易
2. 如果区块中有双重支付:
- 区块无效
- 被其他节点拒绝
3. 只有有效的区块被接受
4. 交易被确认
机制3:最长链规则
如果出现分叉(可能包含双重支付):
1. 网络可能暂时分叉
2. 不同节点看到不同的交易
3. 最长链规则:
- 选择最长的链
- 放弃较短的链
- 较短链上的交易被回滚
4. 最终只有一条链被接受
5. 双重支付被防止
机制4:确认数
为了进一步防止双重支付:
1. 等待多个确认
2. 每个确认 = 后面又多了一个区块
3. 确认数越多,被回滚的概率越低
例子:
- 1个确认:可能被回滚(如果分叉)
- 6个确认:几乎不可能被回滚
- 12个确认:几乎绝对安全
比特币建议:6个确认
以太坊建议:12个确认(因为出块更快)
2.4.7 实际例子:比特币如何防止双重支付
场景:Alice尝试双重支付
初始状态:
- Alice有1个比特币(来自交易A的输出)
尝试1:支付给商家A
1. Alice创建交易B:
- 输入:交易A的输出(1 BTC)
- 输出1:0.5 BTC给商家A
- 输出2:0.49 BTC找零给Alice
- 输出3:0.01 BTC手续费
2. Alice用私钥签名
3. 广播到网络
4. 节点验证:
- 输入有效(交易A的输出存在)
- 输入未被使用
- 签名有效
5. 交易B被接受,打包到区块100
尝试2:支付给商家B(双重支付)
1. Alice创建交易C:
- 输入:交易A的输出(1 BTC)- 同一个输入!
- 输出1:0.5 BTC给商家B
- 输出2:0.49 BTC找零给Alice
- 输出3:0.01 BTC手续费
2. Alice用私钥签名
3. 广播到网络
4. 节点验证:
- 输入有效(交易A的输出存在)
- 输入已被使用(在交易B中)
- 验证失败!
5. 交易C被拒绝,不被打包
结果:
- 只有交易B被确认
- 双重支付被防止
如果Alice尝试利用网络延迟?
场景:网络延迟攻击
尝试:
1. Alice同时广播交易B和交易C
2. 由于网络延迟,不同节点可能先收到不同的交易
3. 可能出现分叉:
- 链1:包含交易B
- 链2:包含交易C
防御:
1. 最长链规则:
- 如果链1先挖出下一个区块,链1更长
- 所有节点选择链1
- 链2被放弃,交易C被回滚
2. 确认数:
- 等待6个确认
- 即使出现分叉,最终只有一条链被接受
- 双重支付被防止
结果:
- 即使利用网络延迟,双重支付也无法成功
2.4.8 为什么区块链可以防止双重支付?
原因1:去中心化账本
所有节点都有完整的账本:
- 所有交易记录
- 所有UTXO状态
- 所有账户余额
如果尝试双重支付:
- 所有节点都能检测到
- 所有节点都会拒绝
- 无法成功
原因2:共识机制
网络共识保证:
- 所有节点对账本状态达成一致
- 如果出现分歧,通过共识解决
- 最终只有一条链被接受
如果尝试双重支付:
- 网络共识会拒绝
- 只有一条链被接受
- 双重支付被防止
原因3:不可篡改
区块链不可篡改:
- 一旦交易被确认,无法修改
- 一旦UTXO被使用,无法再次使用
- 历史记录永久保存
如果尝试双重支付:
- 第一次支付被确认后,无法撤销
- 第二次支付会被拒绝
- 双重支付被防止
原因4:公开可验证
所有交易公开可验证:
- 任何人都可以查看所有交易
- 任何人都可以验证交易
- 任何人都可以检测双重支付
如果尝试双重支付:
- 任何人都能发现
- 任何人都能拒绝
- 双重支付被防止
2.4.9 总结
双重支付是数字世界的核心问题:
- 数字文件可以完美复制
- 如何防止"同一笔钱花两次"?
传统解决方案的问题:
- 依赖中心化机构
- 单点故障、单点控制
- 无法完全防止
区块链的解决方案:
- 去中心化账本
- 共识机制
- 不可篡改
- 公开可验证
区块链如何防止双重支付:
- UTXO模型:每个UTXO只能使用一次
- 账户模型:检查余额,防止超支
- 交易验证:每个节点验证交易
- 区块确认:只有有效区块被接受
- 最长链规则:最终只有一条链被接受
- 确认数:等待多个确认,提高安全性
这是区块链的核心价值之一:在去中心化的环境中,完全防止双重支付,而不依赖任何中心化机构。
2.5 中心化系统的三个致命问题
通过分析数字世界的三个核心问题,我们发现它们都依赖中心化系统。
而中心化系统有三个致命问题:
问题1:单点故障
描述:
- 如果中心服务器被攻击,数据丢失
- 如果中心服务器故障,服务中断
- 如果中心服务器倒闭,数据无法访问
例子:
- 很多创业公司倒闭,用户数据丢失
- 很多网站关闭,数据无法访问
- 很多App下架,数据无法恢复
本质:
- 所有数据依赖单一节点
- 节点失效 = 系统失效
问题2:单点控制
描述:
- 中心服务器可以修改数据
- 中心服务器可以拒绝访问
- 中心服务器可以作恶
例子:
- 公司可以删除用户数据
- 平台可以封禁用户
- 银行可以冻结账户
本质:
- 所有控制权集中在单一节点
- 节点作恶 = 系统作恶
问题3:信任成本
描述:
- 需要信任服务器不会故障
- 需要信任管理员不会作恶
- 需要信任公司不会倒闭
例子:
- 你把钱存银行,需要信任银行
- 你把数据存云盘,需要信任云服务商
- 你用社交平台,需要信任平台
本质:
- 需要持续信任第三方
- 信任成本高,风险大
第三部分:去中心化的解决方案
3.1 去中心化的核心思想
定义:去中心化是不依赖单一节点,多个节点共同维护,没有单点故障,没有单点控制。
关键要素:
- 多个节点:不是单一节点
- 共同维护:所有节点都有数据
- 无单点故障:节点失效 ≠ 系统失效
- 无单点控制:节点作恶 ≠ 系统作恶
3.2 去中心化如何解决单点故障?
传统系统
数据存储:
┌─────────────┐
│ 中心服务器 │ ← 所有数据在这里
└─────────────┘
如果服务器故障:
- 数据丢失
- 服务中断
- 系统失效
去中心化系统
数据存储:
┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐
│节点1│ │节点2│ │节点3│ │节点4│
│数据 │ │数据 │ │数据 │ │数据 │
└─────┘ └─────┘ └─────┘ └─────┘
如果节点1故障:
- 其他节点还在
- 数据依然存在
- 系统依然运行
需要所有节点同时故障 = 几乎不可能 本质:
- 数据分布在多个节点
- 节点失效 ≠ 数据丢失
- 系统更可靠
3.3 去中心化如何解决单点控制?
传统系统
控制权:
┌─────────────┐
│ 中心服务器 │ ← 完全控制
└─────────────┘
可以:
- 修改数据
- 拒绝访问
- 作恶
去中心化系统
控制权:
┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐
│节点1│ │节点2│ │节点3│ │节点4│
└─────┘ └─────┘ └─────┘ └─────┘
↓ ↓ ↓ ↓
需要网络共识才能修改
单个节点无法:
- 修改数据(需要共识)
- 拒绝访问(其他节点可以访问)
- 作恶(会被其他节点拒绝)
本质:
- 控制权分散在多个节点
- 需要共识才能修改
- 单个节点无法作恶
3.4 去中心化如何降低信任成本?
传统系统
信任对象:
- 服务器不会故障
- 管理员不会作恶
- 公司不会倒闭
信任成本:高
信任风险:大
去中心化系统
信任对象:
- 数学和密码学(客观规律)
- 代码和共识(公开透明)
信任成本:低
信任风险:小
本质:
- 从信任人/机构,转向信任数学/技术
- 数学规律不会作恶
- 代码公开,可以验证
3.5 去中心化面临的挑战
去中心化虽然解决了中心化的问题,但也带来了新的挑战:
挑战1:如何达成共识?
问题:
- 多个节点如何达成一致?
- 如何防止恶意节点?
- 如何保证数据一致性?
解决方案:
- 共识机制(PoW、PoS等)
- 通过数学和密码学保证
- 通过激励机制保证
这是区块链的核心技术之一,我们会在后续章节详细讲解。
挑战2:如何保证安全?
问题:
- 如何防止攻击?
- 如何防止篡改?
- 如何防止双重支付?
解决方案:
- 密码学(哈希、签名)
- 共识机制
- 激励机制
这是区块链的核心技术之一,我们会在后续章节详细讲解。
挑战3:如何提高性能?
问题:
- 去中心化通常更慢
- 如何提高速度?
- 如何降低成本?
解决方案:
- Layer2解决方案
- 分片技术
- 优化共识机制
这是区块链的优化方向,我们会在后续章节详细讲解。
第四部分:密码学基础
4.1 为什么需要密码学?
去中心化解决了架构问题,但如何保证安全?
答案:密码学。
密码学提供了数学保证:
- 哈希函数:保证数据不被篡改
- 数字签名:保证身份和完整性
- 非对称加密:保证通信安全
核心思想:用数学规律保证安全,而不是依赖人。
4.2 哈希函数(Hash Function)
4.2.1 什么是哈希函数?
定义:哈希函数是把任意长度的数据,转换成固定长度的数据。
哈希函数就像一个"数字指纹生成器":
- 输入:任意数据(可以是1个字节,也可以是1TB)
- 输出:固定长度的"指纹"(通常是256位,即64个十六进制字符)
- 作用:用这个"指纹"来唯一标识数据
数学表示:
H(x) = y
其中:
x:输入(任意长度)
y:输出(固定长度,如256位)
H:哈希函数
生活中的类比:
想象一下,你有一本书,你想给这本书一个唯一的"身份证号":
- 这本书可能有100页,也可能有1000页(任意长度)
- 但"身份证号"总是18位数字(固定长度)
- 不同的书有不同的"身份证号"
- 即使两本书内容几乎一样,只要有一个字不同,"身份证号"就完全不同
哈希函数就是这样工作的。
实际例子:
# 使用Python计算SHA-256哈希
import hashlib
# 例子1:短文本
data1 = "Hello World"
hash1 = hashlib.sha256(data1.encode()).hexdigest()
print(f"输入: {data1} (11个字符)")
print(f"输出: {hash1} (64个字符)")
# 输出: a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e
# 例子2:长文本
data2 = "The quick brown fox jumps over the lazy dog"
hash2 = hashlib.sha256(data2.encode()).hexdigest()
print(f"\n输入: {data2} (43个字符)")
print(f"输出: {hash2} (64个字符)")
# 输出: d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592
# 例子3:大文件(假设)
# 即使是一个1GB的文件,哈希值也还是64个字符
关键观察:
- 输入长度不同,输出长度相同:无论输入是1个字符还是1TB,输出都是64个字符
- 输入内容不同,输出完全不同:即使只改一个字符,输出也完全不同
- 输出看起来随机:输出是一串看似随机的字符,但实际上是完全确定的
为什么叫"哈希"?
"哈希"(Hash)这个词来自英文,原意是"切碎、混合"。哈希函数就像把数据"切碎、混合",然后得到一个"指纹":
- 数据被"切碎"成小块
- 这些小块被"混合"处理
- 最终得到一个唯一的"指纹"
这个"指纹"可以用来:
- 验证数据是否被修改
- 快速比较两个数据是否相同
- 作为数据的唯一标识
4.2.2 哈希函数的四个特性
特性1:确定性(Deterministic)
描述:相同输入,一定得到相同输出。
数学表示:
如果 x1 = x2,则 H(x1) = H(x2)
例子:
H("Hello") = "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
H("Hello") = "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
无论计算多少次,结果都一样。
为什么重要:
- 可以验证数据完整性
- 可以重复验证
特性2:快速计算(Fast Computation)
描述:计算哈希值很快,即使是大文件。
例子:
计算1MB文件的哈希值:< 1毫秒
计算1GB文件的哈希值:< 10毫秒
计算1TB文件的哈希值:< 1秒
为什么重要:
- 可以实时验证
- 可以处理大量数据
特性3:不可逆(One-Way)
描述:无法从输出推回输入。
数学表示:
给定 y = H(x),无法找到 x
例子:
已知哈希值:"2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
无法知道原始数据是什么。
可能是:"Hello"
也可能是:"H3ll0"
也可能是其他任何数据
为什么不可逆?
这是哈希函数最神奇的特性,也是区块链安全的基础。让我们深入理解为什么不可逆。
数学原理1:信息丢失(信息论角度)
想象一下:
- 输入可以是任意长度:1个字节、1KB、1MB、1GB、1TB...
- 输出固定长度:256位(32字节)
这就像:
- 你有一杯水(任意大小)
- 你把它倒进一个固定大小的杯子(256位)
- 如果水太多,会溢出(信息丢失)
- 如果水太少,杯子也装不满(信息丢失)
具体例子:
输入1:"Hello" (5个字节)
输入2:"Hello World" (11个字节)
输入3:"Hello World, this is a very long text..." (1000个字节)
输出:都是256位(32个字节)
问题:给你一个256位的输出,你能知道原始输入是什么吗?
答案:不能!因为:
- 可能是5个字节的"Hello"
- 可能是11个字节的"Hello World"
- 可能是1000个字节的长文本
- 可能是任何能产生这个哈希值的数据
信息已经丢失,无法恢复。
数学原理2:单向函数(密码学角度)
哈希函数在数学上是一个单向函数(One-Way Function):
正向计算(容易):
输入 → 哈希函数 → 输出
时间:微秒级
逆向计算(困难):
输出 → ??? → 输入
时间:需要尝试2^256次(宇宙毁灭都算不完)
为什么正向容易,逆向困难?
正向计算:
- 有明确的算法步骤
- 计算机可以快速执行
- 时间复杂度:O(n),n是输入长度
逆向计算:
- 没有明确的算法
- 只能暴力尝试所有可能的输入
- 时间复杂度:O(2^256),需要尝试2^256次
2^256有多大?
2^256 ≈ 10^77
这是什么概念?
- 宇宙中的原子数量:约10^80
- 2^256 ≈ 10^77,接近宇宙原子数量
即使全宇宙的计算机都用来计算,也需要:
- 时间:比宇宙年龄还长
- 能量:比太阳的能量还多
所以,从数学上,哈希函数是不可逆的。
数学原理3:碰撞抵抗(安全性角度)
即使理论上可以找到输入,但:
- 找到的输入可能不是原始输入(碰撞)
- 需要找到"正确"的输入,概率极低
- 即使找到了,也无法证明是"原始"输入
为什么重要:
哈希函数的不可逆性,使得:
-
可以隐藏原始数据:
- 存储哈希值,不存储原始数据
- 即使哈希值泄露,原始数据也安全
-
可以存储密码:
- 不存储明文密码
- 只存储密码的哈希值
- 即使数据库泄露,密码也安全
-
可以证明知道数据,但不泄露数据:
- 你可以证明你知道某个数据(通过提供哈希值)
- 但不需要泄露数据本身
- 这在零知识证明中有重要应用
-
区块链的安全基础:
- 每个区块都有哈希值
- 如果修改数据,哈希值会变
- 无法伪造哈希值(因为不可逆)
- 因此区块链不可篡改
特性4:雪崩效应(Avalanche Effect)
描述:输入微小变化,输出完全不同。
例子:
H("Hello") = "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
H("Hallo") = "d85b121619a5e7b638a8e9b4e8c8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8"
只改了一个字母(e → a),但哈希值完全不同。
为什么重要:
- 可以检测任何修改
- 即使只改1位,也能发现
4.2.3 为什么哈希函数可以防篡改?
原理:
- 计算原始数据的哈希值
- 存储哈希值
- 需要验证时,重新计算哈希值
- 对比两个哈希值
- 如果相同,数据未被修改;如果不同,数据被修改
例子:
原始数据:"Hello"
原始哈希:"2cf24dba..."
存储:数据 + 哈希值
验证时:
重新计算:"Hello" → "2cf24dba..."
对比:相同 → 数据未被修改
如果数据被修改:"Hallo"
重新计算:"Hallo" → "d85b1216..."
对比:不同 → 数据被修改
在区块链中的应用:
- 每个区块都有哈希值
- 每个区块都包含前一个区块的哈希值
- 如果修改任何区块,哈希值会变
- 后面的区块都会不匹配
- 因此无法篡改
这是区块链"不可篡改"的数学基础。
4.2.4 SHA-256的工作原理(深入理解)
SHA-256是比特币和以太坊使用的哈希函数。让我们深入理解它是如何工作的。
SHA-256是什么?
- SHA:Secure Hash Algorithm(安全哈希算法)
- 256:输出256位(32字节,64个十六进制字符)
- 设计者:美国国家安全局(NSA)
- 标准:FIPS 180-4(美国联邦信息处理标准)
SHA-256的工作流程(详细):
步骤1:预处理和填充
原始输入:任意长度的数据
填充规则:
1. 在数据末尾添加一个"1"位
2. 添加k个"0"位,使得:
数据长度 + 1 + k + 64 ≡ 0 (mod 512)
3. 添加64位,表示原始数据的长度(以位为单位)
结果:数据长度是512位的倍数
例子:
输入:"Hello" (5字节 = 40位)
填充后:
"Hello" + "1" + "000...000" (k个0) + "000...0101000" (64位长度)
总长度:512位的倍数
步骤2:分块处理
把填充后的数据分成512位的块:
块1: 512位
块2: 512位
块3: 512位
...
每个块独立处理
步骤3:初始化哈希值
初始化8个32位的变量(h0到h7):
h0 = 0x6a09e667
h1 = 0xbb67ae85
h2 = 0x3c6ef372
h3 = 0xa54ff53a
h4 = 0x510e527f
h5 = 0x9b05688c
h6 = 0x1f83d9ab
h7 = 0x5be0cd19
这些是前8个质数的平方根的小数部分
步骤4:处理每个512位块
对每个512位块,进行64轮计算:
每轮计算:
1. 使用块中的16个32位字
2. 扩展成64个32位字(使用消息调度)
3. 使用8个工作变量(a, b, c, d, e, f, g, h)
4. 进行复杂的位运算:
- 右旋转(ROTR)
- 右移(SHR)
- 异或(XOR)
- 与(AND)
- 或(OR)
- 加法(模2^32)
5. 使用64个常量(K0到K63)
6. 更新工作变量
64轮后,更新哈希值:
h0 = h0 + a
h1 = h1 + b
...
h7 = h7 + h
步骤5:输出最终哈希值
把所有块的哈希值连接起来:
h0 || h1 || h2 || h3 || h4 || h5 || h6 || h7
得到256位的最终哈希值
为什么这么复杂?
这种复杂的设计是为了:
-
雪崩效应:
- 输入的微小变化,会导致输出的巨大变化
- 即使只改1位,输出也完全不同
-
碰撞抵抗:
- 无法找到两个不同的输入产生相同的输出
- 即使尝试2^128次,概率也极低
-
不可逆性:
- 无法从输出推回输入
- 只能暴力破解,计算量巨大
实际计算示例:
import hashlib
# 计算SHA-256
data = "Hello World"
hash_value = hashlib.sha256(data.encode()).hexdigest()
print(f"输入: {data}")
print(f"输出: {hash_value}")
# 输出: a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e
# 只改一个字符
data2 = "Hello Worle" # d 改成 e
hash_value2 = hashlib.sha256(data2.encode()).hexdigest()
print(f"\n输入: {data2}")
print(f"输出: {hash_value2}")
# 输出: d85b121619a5e7b638a8e9b4e8c8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8
# 观察:只改了一个字符,但输出完全不同
为什么用SHA-256?
-
安全性高:
- 目前没有找到碰撞(两个不同输入产生相同输出)
- 即使量子计算机,也需要2^128次计算
- 被认为是安全的
-
计算快:
- 硬件优化(CPU、GPU、ASIC)
- 可以并行计算
- 适合大规模使用
-
标准化:
- 广泛使用(比特币、以太坊、TLS等)
- 经过多年验证
- 有完整的实现
-
输出固定:
- 总是256位
- 适合存储和传输
- 适合作为数据标识
在区块链中的应用:
-
区块哈希:
- 每个区块都有哈希值
- 用于链接区块
- 用于验证区块完整性
-
交易哈希:
- 每笔交易都有哈希值
- 用于Merkle树
- 用于快速验证
-
地址生成:
- 从公钥生成地址
- 使用哈希函数
- 保证地址的唯一性
-
挖矿:
- 计算区块哈希
- 找到符合条件的哈希值
- 证明工作量
4.3 数字签名(Digital Signature)
4.3.1 什么是数字签名?
定义:数字签名是用私钥签名,用公钥验证的机制。
作用:
- 证明身份:只有拥有私钥的人才能签名
- 证明完整性:数据没有被修改
- 不可否认:签名者无法否认签过名
类比:
- 就像手写签名
- 只有你能签你的名字
- 别人可以验证是你的签名
- 你无法否认签过名
4.3.2 公钥和私钥
密钥对(Key Pair):
- 私钥(Private Key):保密,只有你知道
- 公钥(Public Key):公开,任何人都可以知道
关系:
- 用私钥签名 → 任何人都可以用公钥验证
- 但无法从公钥推导出私钥
数学原理:
- 基于非对称加密
- 私钥和公钥是数学相关的
- 但无法从公钥推导私钥(单向函数)
例子:
私钥:0x1234567890abcdef...(保密)
公钥:0xabcdef1234567890...(公开)
用私钥签名 → 可以用公钥验证
但无法从公钥推导出私钥
为什么重要:
- 可以公开公钥,不泄露私钥
- 任何人都可以验证,但只有你能签名
4.3.3 如何签名?(详细步骤)
数字签名的过程比想象中复杂,让我们详细理解每一步。
步骤1:计算数据的哈希值
原始数据:"Hello World"(可能是任意长度)
计算哈希:
hash = SHA256("Hello World")
hash = "a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e"
为什么先计算哈希?
- 数据可能很大(几MB、几GB)
- 签名大数据的计算很慢
- 哈希值固定长度(256位),签名很快
- 哈希值代表数据,签名哈希值 = 签名数据
步骤2:用私钥"加密"哈希值(实际上是签名)
这里需要澄清一个概念:
不是"加密",而是"签名"
虽然技术上是用私钥对哈希值进行数学运算,但这个过程和加密不同:
加密:用公钥加密,用私钥解密(保护数据)
签名:用私钥签名,用公钥验证(证明身份)
签名过程:
signature = sign(hash, private_key)
数学上:
signature = (hash^d) mod n
其中:
- d:私钥
- n:模数(公钥的一部分)
- 这是基于RSA或椭圆曲线的数学运算
详细过程:
1. 使用私钥对哈希值进行数学运算
2. 得到签名值(通常也是256位或更长)
3. 签名值看起来像随机数,但实际上包含了:
- 哈希值的信息
- 私钥的信息
- 但无法从签名推导出私钥
步骤3:得到签名
最终签名:
signature = "3a5f8b2c9d1e4f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"
这个签名:
- 是唯一的(只有这个私钥能产生这个签名)
- 是确定的(相同数据和私钥,总是产生相同签名)
- 是不可伪造的(没有私钥无法产生有效签名)
完整流程示例:
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.backends import default_backend
# 1. 生成密钥对
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
public_key = private_key.public_key()
# 2. 要签名的数据
message = b"Hello World"
# 3. 计算哈希值(内部自动完成)
# 实际过程:
# hash = SHA256(message)
# signature = sign(hash, private_key)
# 4. 签名
signature = private_key.sign(
message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
print(f"数据: {message}")
print(f"签名: {signature.hex()}")
结果:
- 签名:一串数字(签名值)
- 数据:原始数据
- 公钥:用于验证的公钥
有了这三个,任何人都可以验证签名。
为什么不是直接签名数据?
-
效率:
- 数据可能很大(几GB)
- 签名大数据的计算很慢
- 哈希值固定长度(256位),签名很快
-
安全性:
- 哈希函数保证数据完整性
- 签名哈希值 = 签名数据
- 如果数据被修改,哈希值会变,签名验证会失败
-
标准化:
- 所有数据都先哈希,再签名
- 统一处理流程
- 便于实现和验证
关键理解:
签名不是"加密数据",而是:
- 证明身份:只有拥有私钥的人才能签名
- 证明完整性:如果数据被修改,签名验证会失败
- 不可否认:签名者无法否认签过名(因为只有他有私钥)
4.3.4 如何验证?(详细步骤)
验证签名的过程是签名的逆过程,让我们详细理解。
验证的目标:
- 确认签名是用对应私钥签的
- 确认数据没有被修改
- 确认签名者的身份
步骤1:计算数据的哈希值
收到:
- 数据:"Hello World"
- 签名:signature
- 公钥:public_key
计算数据的哈希值:
hash1 = SHA256("Hello World")
hash1 = "a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e"
步骤2:用公钥"解密"签名(实际上是验证)
同样需要澄清:这不是"解密",而是"验证"。
验证过程:
hash2 = verify(signature, public_key)
数学上:
hash2 = (signature^e) mod n
其中:
- e:公钥指数
- n:模数
- 这是签名的逆运算
详细过程:
1. 使用公钥对签名进行数学运算
2. 得到哈希值(如果签名有效)
3. 对比这个哈希值和计算出的哈希值
步骤3:对比两个哈希值
如果 hash1 == hash2:
验证通过
- 签名是用对应私钥签的
- 数据没有被修改
- 签名者身份确认
如果 hash1 != hash2:
验证失败
- 签名可能是伪造的
- 数据可能被修改了
- 签名者身份无法确认
完整验证示例:
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.backends import default_backend
# 假设我们已经有了:
# - message: 数据
# - signature: 签名
# - public_key: 公钥
# 验证签名
try:
public_key.verify(
signature,
message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
print("✓ 验证成功!")
print(" - 签名有效")
print(" - 数据未被修改")
print(" - 签名者身份确认")
except:
print("✗ 验证失败!")
print(" - 签名可能无效")
print(" - 数据可能被修改")
print(" - 签名者身份无法确认")
验证失败的几种情况:
情况1:签名是伪造的
攻击者没有私钥,尝试伪造签名:
- 计算错误的签名值
- 验证时,hash1 != hash2
- 验证失败
情况2:数据被修改了
原始数据:"Hello World"
修改后:"Hello Worle"
签名是用原始数据签的:
- hash1(原始数据)≠ hash2(修改后数据)
- 验证失败
情况3:使用了错误的公钥
签名是用私钥A签的
但用公钥B验证:
- 公钥B无法验证私钥A的签名
- 验证失败
为什么验证是安全的?
-
数学保证:
- 基于非对称加密的数学困难性
- 无法伪造签名(除非拥有私钥)
- 无法从签名推导出私钥
-
哈希保证:
- 如果数据被修改,哈希值会变
- 签名验证会失败
- 保证数据完整性
-
公开验证:
- 任何人都可以用公钥验证
- 不需要私钥
- 不需要信任第三方
在区块链中的应用:
-
交易签名:
- 每笔交易都需要签名
- 用你的私钥签名,证明交易是你发的
- 其他人用你的公钥验证,确认是你发的
-
防止伪造:
- 没有私钥无法签名
- 无法伪造交易
- 保证交易安全
-
不可否认:
- 签名验证通过,证明你签过名
- 你无法否认
- 保证交易的可追溯性
4.3.5 为什么可以证明身份?
原理:
- 只有拥有私钥的人才能签名
- 如果签名验证通过,说明签名者拥有私钥
- 因此可以证明身份
数学保证:
- 基于非对称加密的数学困难性
- 无法伪造签名(除非拥有私钥)
- 无法从公钥推导私钥
在区块链中的应用:
- 每笔交易都需要签名
- 用你的私钥签名,证明交易是你发的
- 其他人用你的公钥验证,确认是你发的
- 因此可以防止伪造交易
这是区块链"证明身份"的数学基础。
4.3.6 为什么私钥不能泄露?
如果私钥泄露:
- 别人可以冒充你
- 别人可以花你的钱
- 无法撤销
例子:
如果你的比特币私钥泄露:
- 别人可以用你的私钥签名交易
- 把你的比特币转走
- 你无法阻止(因为交易已经上链)
- 你无法撤销(因为区块链不可篡改)
保护方法:
-
永远不要泄露私钥
- 不要告诉任何人
- 不要存在网上
- 不要截图
-
使用硬件钱包
- 私钥存在硬件设备里
- 不接触网络
- 更安全
-
使用多重签名
- 需要多个私钥才能签名
- 即使一个泄露,也不影响
这是区块链安全的第一原则。
4.4 非对称加密(Asymmetric Encryption)
4.4.1 什么是非对称加密?
定义:非对称加密是用一对密钥(公钥和私钥)进行加密和解密的机制。
特点:
- 公钥加密,私钥解密
- 私钥加密,公钥解密(用于签名)
- 无法从公钥推导私钥
对比对称加密:
- 对称加密:用同一个密钥加密和解密
- 非对称加密:用不同的密钥加密和解密
4.4.2 RSA算法(简化理解)
原理:
- 基于大数分解的困难性
- 公钥 = (n, e)
- 私钥 = (n, d)
- n是两个大质数的乘积
- 从n分解出两个质数很困难
应用:
- 数字签名
- 密钥交换
问题:
- 密钥较长(2048位)
- 计算较慢
4.4.3 椭圆曲线加密(ECC)
为什么用ECC?
- 更安全:相同安全级别,密钥更短
- 更快:计算更快
- 更省空间:密钥更短
比特币和以太坊都用ECC
例子:
RSA 2048位 ≈ ECC 256位(相同安全级别)
但ECC计算更快,密钥更短
第五部分:总结和思考
5.1 核心概念回顾
通过本章学习,你应该理解:
-
信任的本质
- 信任是相信对方会按照承诺行事
- 传统信任机制都依赖第三方
- 第三方失效 = 系统失效
-
数字世界的信任危机
- 如何证明"我是我"?
- 如何防止数据被篡改?
- 如何防止双重支付?
- 都依赖中心化系统
-
中心化系统的问题
- 单点故障
- 单点控制
- 信任成本高
-
去中心化的解决方案
- 多个节点共同维护
- 无单点故障
- 无单点控制
- 降低信任成本
-
密码学基础
- 哈希函数:保证数据不被篡改
- 数字签名:保证身份和完整性
- 非对称加密:保证通信安全
5.2 关键理解
理解1:区块链的本质
- 区块链是用技术解决信任问题
- 不依赖第三方,依赖数学和密码学
- 这是区块链的根本创新
理解2:去中心化的意义
- 不是技术炫技,而是解决根本问题
- 解决单点故障、单点控制、信任成本
- 这是区块链的核心价值
理解3:密码学的作用
- 不是装饰,而是数学保证
- 哈希函数保证不可篡改
- 数字签名保证身份
- 这是区块链安全的基础
5.3 思考题
-
为什么传统系统需要信任第三方?
- 思考:能否不依赖第三方?
- 思考:区块链如何解决?
-
去中心化如何解决信任问题?
- 思考:多个节点如何达成一致?
- 思考:如何防止恶意节点?
-
哈希函数如何保证数据不被篡改?
- 思考:如果修改数据,哈希值会怎样?
- 思考:区块链如何利用这个特性?
-
数字签名如何证明身份?
- 思考:为什么只有拥有私钥的人才能签名?
- 思考:如何防止私钥泄露?
-
如果私钥丢失了会怎样?
- 思考:能否恢复?
- 思考:如何保护私钥?
5.4 下一步
完成本章学习后,你应该:
- 理解为什么需要区块链
- 理解去中心化的意义
- 理解密码学的基础
下一章:我们将深入理解比特币的工作原理,看看区块链是如何实际运行的。
附录:实践练习
练习1:计算哈希值
import hashlib
# 计算SHA-256哈希
data = "Hello World"
hash_value = hashlib.sha256(data.encode()).hexdigest()
print(f"数据: {data}")
print(f"哈希: {hash_value}")
# 修改一个字符
data2 = "Hello Worle"
hash_value2 = hashlib.sha256(data2.encode()).hexdigest()
print(f"\n修改后数据: {data2}")
print(f"哈希: {hash_value2}")
# 观察:即使只改了一个字符,哈希值完全不同
运行结果:
数据: Hello World
哈希: a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e
修改后数据: Hello Worle
哈希: d85b121619a5e7b638a8e9b4e8c8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8
观察:
- 只改了一个字符(d → e),但哈希值完全不同
- 这就是雪崩效应
练习2:生成密钥对
# 使用OpenSSL生成RSA密钥对
openssl genrsa -out private_key.pem 2048
openssl rsa -in private_key.pem -pubout -out public_key.pem
# 查看私钥
cat private_key.pem
# 查看公钥
cat public_key.pem
观察:
- 私钥和公钥是不同的
- 私钥更长,包含更多信息
- 公钥可以从私钥推导,但私钥不能从公钥推导
练习3:数字签名和验证
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.backends import default_backend
# 生成密钥对
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
public_key = private_key.public_key()
# 要签名的消息
message = b"Hello World"
# 签名
signature = private_key.sign(
message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
print(f"消息: {message}")
print(f"签名: {signature.hex()}")
# 验证
try:
public_key.verify(
signature,
message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
print("✓ 验证成功!")
except:
print("✗ 验证失败!")
# 尝试用错误的消息验证
wrong_message = b"Hello Worle"
try:
public_key.verify(
signature,
wrong_message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
print("✓ 验证成功!")
except:
print("✗ 验证失败!(这是正常的,因为消息被修改了)")
运行结果:
消息: b'Hello World'
签名: 3a5f8b2c...
✓ 验证成功!
✗ 验证失败!(这是正常的,因为消息被修改了)
观察:
- 正确的消息可以验证通过
- 错误的消息验证失败
- 这证明了数字签名可以检测数据是否被修改
学习检查清单
完成本章学习后,检查你是否理解:
- 什么是信任?为什么需要信任?
- 传统信任机制有哪些?各有什么问题?
- 数字世界面临哪些信任挑战?
- 中心化系统有什么问题?
- 去中心化如何解决这些问题?
- 哈希函数是什么?有什么特性?
- 为什么哈希函数可以防篡改?
- 数字签名是什么?如何工作?
- 为什么数字签名可以证明身份?
- 为什么私钥不能泄露?
如果以上问题你都能回答,说明你已经理解了信任问题的本质,可以进入下一章了!