第 02 讲:密码学、密钥体系与分布式账本

  • 哈希(Hash)、哈希指针(Hash Pointer)、Merkle Tree
  • 数字签名(Digital Signature)、密钥体系(Key Infrastructure)
  • 分布式账本技术(DLT)分类:公链、联盟链、许可链
  • UTXO 与账户模型的对比
  • 关键问题:为什么密码学能支撑"无中心记账"

1.1 为什么密码学能支撑"无中心记账":问题意识

  • 传统金融依赖中心化信任:银行维护账本、确认交易、仲裁纠纷
  • 无中心场景的核心挑战:没有可信任的第三方,如何建立可信性?
  • 答案:可信性不来自机构信誉,而来自数学可验证性(mathematical verifiability)
  • 密码学提供了三类底层保障,使"自证清白"成为可能
  • 讨论:如果所有参与者都可能作恶,什么机制能让诚实者不被欺骗?

1.2 三类密码学保障的分解

  • 完整性(Integrity):数据在传输或存储中未被篡改——通过 Hash 校验实现
  • 认证性(Authentication):确认消息发送者的身份——通过数字签名实现
  • 不可抵赖(Non-repudiation):发送者事后不能否认发送行为——签名+公开验证
  • 三者共同构成可验证性(Verifiability):任何人可独立检验规则是否被遵守
  • 关键认知:区块链的首要目标不是"保密",而是"公开可验证"

1.3 从"保密"到"可验证":密码学思维转型

  • 日常密码学直觉:加密 = 不让别人看(confidentiality)
  • 区块链密码学重心:签名 = 让别人验证是谁发的;Hash = 让别人验证有没有改
  • 这解释了为什么区块链使用**公钥密码(public-key cryptography)**而非对称加密为主
  • 可信来源不再是"权威节点",而是公开规则 + 公开数据 + 可重复验证
  • 讨论:如果一条公链的所有数据都是公开的,隐私从何而来?(后续课程展开)

2.1 密码学基础框架:四个核心工具总览

工具 功能 区块链中的角色
Hash 生成固定长度摘要 防篡改、交易标识、区块链接
Hash Pointer 指针 + 被指对象摘要 形成可验证的历史链条
Merkle Tree 分层摘要聚合 高效证明交易包含性
数字签名 私钥签名 + 公钥验证 资产所有权验证、授权
  • 四个工具并非独立工作,而是分层嵌套构成区块链安全基底

2.2 四工具的工作关系链

  • 交易(Transaction)→ 发送方用私钥签名 → 签名包含在交易数据中
  • 一组交易 → 组织成 Merkle Tree → 根 Hash 写入区块头
  • 单个区块 → 头中包含前一区块的 Hash Pointer → 链接成链
  • 链上任意节点可独立验证:Hash 校验完整性 + 签名校验所有权
  • 这一链条的关键属性:篡改任意节点都将导致后续所有验证失败

2.3 框架意义:密码学作为"制度替代"

  • 传统制度依赖:法律合同、审计机构、监管仲裁
  • 区块链替代路径:密码学协议取代"人治"信任
  • 这不是说密码学完美无缺——密钥管理、算法实现、量子威胁都是风险来源
  • 但密码学提供了规则的可执行性(enforceability):规则不是写在纸上,而是写在代码和数学中
  • 讨论:密码学能否完全替代制度信任?什么场景下不能?

3.1 Hash 函数的基本定义与属性

  • 定义H:{0,1}{0,1}nH: \{0,1\}^* \to \{0,1\}^n,输入任意长度,输出固定 n 位摘要
  • 三个核心安全属性(Crypto. Hash 的必要条件):
    1. 无碰撞(Collision-free):无法找到 xyx \neq y 使得 H(x)=H(y)H(x)=H(y)
    2. 隐藏(Hiding):从 H(x)H(x) 不可逆推 xx
    3. 谜题友好(Puzzle-friendly):对输出无先验偏好的输入空间
  • 雪崩效应(Avalanche Effect):输入 1 bit 变化 → 输出约 50% bit 翻转
  • 区块链中常用 SHA-256(双重 SHA-256)和 Keccak-256

3.2 Hash 计算演示:双 SHA-256 雪崩效应

import hashlib
def double_sha256(data):
    data_bytes = data.encode('utf-8')
    first_hash = hashlib.sha256(data_bytes).digest()
    return hashlib.sha256(first_hash).hexdigest()
输入 输出(Double SHA-256)
"Hello, Bitcoin Blockchain!" 353edcbbcd3b96019a142619d0783a7fdb106a6612110aad3ba18b2dc3c61568
"Hello, Bitcoin Blockchain." afaf165a00ce5e0f40fd32fd9042517397a3a5f51a0abea1d9023c86ee5c4133
  • 仅将感叹号改为句号,输出完全不同——256 bit 中无任何可辨模式延续
  • 这一性质是"防篡改可检测"的数学基础

3.3 Hash 的用途扩展与讨论

  • 用途 1——完整性校验:文件/消息的 Hash 变化意味着内容被改
  • 用途 2——唯一标识:交易 ID = 交易数据的 Hash
  • 用途 3——工作量证明(PoW):寻找 nonce 使 Hash 满足难度目标(puzzle-friendly 的工程体现)
  • 用途 4——承诺(Commitment):先公布 Hash,后公布原始值,防止提前泄露
  • 讨论:碰撞攻击(collision attack)对区块链有何威胁?SHA-256 的安全边际在哪里?

4.1 Hash Pointer 的概念与结构

  • Hash Pointer = 内存/存储指针 + 被指对象的 Hash 值
  • 传统指针:仅提供"位置"信息,不提供"内容完整性"信息
  • Hash Pointer 提供两层信息:
    • 通过指针定位数据
    • 通过 Hash 验证数据未被篡改
  • 如果被指对象的内容发生任何变化,其 Hash 改变,Hash Pointer 立即失效
  • 这构成了**篡改可检测(tamper-evident)**的基础原语

4.2 从 Hash Pointer 到区块链:链式验证

Block_{t-1}                  Block_t                      Block_{t+1}
┌──────────────┐     Hash    ┌──────────────┐     Hash  ┌──────────────┐
│ Block Header │◄────────────│ Block Header │◄──────────│ Block Header │
│ Prev Hash    │─────┐       │ Prev Hash ───┼────┐      │ Prev Hash ───┼───...
│ Merkle Root  │     │       │ Merkle Root  │    │ │    │ Merkle Root  │
│ Timestamp    │     │       │ Timestamp    │    │ │    │ Timestamp    │
│ Nonce        │     │       │ Nonce        │    │ │    │ Nonce        │
├──────────────┤     │       ├──────────────┤    │ │    ├──────────────┤
│ Transactions │     │       │ Transactions │    │ │    │ Transactions │
└──────────────┘     │       └──────────────┘    │ │    └──────────────┘
                     └──── Hash(Block_{t-1}) ────┘ │
                                                   └──── Hash(Block_t) ────┘
  • 每个区块的头部包含前一区块头部的 Hash

4.3 篡改检测的成本传导分析

  • 修改 Block_{t-1} 中的任意交易 → Block_{t-1} 的 Merkle Root 改变 → Block_{t-1} 头部 Hash 改变
  • 该 Hash 存储在 Block_t 头部 → Block_t 自身 Hash 也改变 → 连锁传导至整条链
  • 结论:攻击者若要修改历史区块,必须重算该区块之后所有区块的 Hash(以及 PoW)
  • 区块链防篡改的准确表述:不是"不能改",而是"改了必被发现且代价极高"
  • 安全假设:最长链拥有最大累计算力,攻击者无法超越诚实节点的算力总和

5.1 Merkle Tree 的结构定义

  • Merkle Tree(也称 Hash Tree)是一种二叉摘要树结构:
    • 叶节点(Leaf):数据块的 Hash(实践中通常是双重 SHA-256)
    • 中间节点(Internal Node):左子 Hash || 右子 Hash 拼接后再 Hash
    • 根节点(Merkle Root):整棵树的最终摘要,代表全部数据的承诺
        Merkle Root = H(H01 || H23)
        ┌───────────────────────┐
        │         Root          │
        └──────────┬────────────┘
       ┌───────────┴───────────┐
    H01 = H(H0||H1)        H23 = H(H2||H3)
   ┌────┴────┐             ┌────┴────┐
   │  H01    │             │  H23    │
   └─────────┘             └─────────┘
  ┌──┴──┐                 ┌──┴──┐
  H0    H1                 H2    H3
 Tx0   Tx1                Tx2   Tx3

5.2 包含性证明(Inclusion Proof)机制

  • 证明某笔交易(如 Tx2)在区块中,需提供:
    1. Tx2 本身的 Hash(H2)
    2. 从叶到根路径上的兄弟节点 Hash:H3、H01
  • 验证步骤:Root=?H(H01    H(H2    H3))Root \stackrel{?}{=} H(H01 \;||\; H(H2 \;||\; H3))
  • 时间复杂度:验证 nn 个交易的 Merkle Tree 只需 O(logn)O(\log n)
    • 区块含 2000 笔交易 → 仅需约 11 个 Hash 即可完成证明
  • 与全量下载(O(n)O(n))相比,效率提升数个数量级

5.3 Merkle Tree 的轻节点意义与讨论

  • 全节点(Full Node):下载全部交易,可独立验证一切
  • 轻节点(Light Client / SPV):仅下载区块头(80 字节/区块),通过 Merkle Proof 验证特定交易
  • 实际意义:移动钱包、浏览器插件钱包等资源受限设备可参与网络验证
  • Merkle Tree 的结构使得可扩展性可验证性不必二选一
  • 讨论:如果 Merkle Tree 的某个叶节点 Hash 碰撞了,会发生什么?这个概率有多大?

6.1 数字签名的形式化定义

  • 数字签名方案由三个算法构成:
    1. 密钥生成 (sk,pk):=generateKeys(keysize)(sk, pk) := \text{generateKeys}(keysize)
      • sksk(私钥):签名者秘密保存
      • pkpk(公钥):公开,供任何人验证
    2. 签名 σ:=sign(sk,m)\sigma := \text{sign}(sk, m)
      • 使用私钥对消息 mm 生成签名 σ\sigma
    3. 验证 verify(pk,m,σ){True,False}\text{verify}(pk, m, \sigma) \to \{\text{True}, \text{False}\}
      • 使用公钥验证签名是否由对应私钥生成
  • 正确性要求:verify(pk,m,sign(sk,m))==True\text{verify}(pk, m, \text{sign}(sk, m)) == \text{True}

6.2 签名提供三层安全保证

安全属性 含义 攻击场景
认证(Authentication) 证明消息来自 sksk 持有者 攻击者无法伪造他人签名
完整性(Integrity) 消息被改后签名立即失效 中间人篡改交易内容
不可抵赖(Non-repudiation) 签名者不能否认签名行为 用户声称"我没发过这笔交易"
  • 注意:不可抵赖性在区块链语境中有微妙差异——私钥丢失或被盗,签名仍然有效
  • 因此区块链中"私钥即所有权"既是力量也是风险

6.3 区块链中的签名应用场景

  • 交易授权:只有拥有对应私钥的人才能花费该地址的 UTXO
  • 脚本级验证:Bitcoin 的 Script 中 scriptSig 提供签名,scriptPubKey 指定验证条件
  • 消息签名:证明某地址持有者对某消息的认可(如认证身份、签署协议)
  • 关键认知:区块链上的"所有权"本质上等于私钥控制权——没有私钥就没有控制权
  • 讨论:多重签名(multisig)如何改变信任模型?mofnm-of-n 场景的适用性?

7.1 私钥、公钥、地址的生成关系链

私钥 (Private Key)
   │
   ├── 随机生成(256 bits,通常为 64 hex 字符)
   │      └── 本质是一个在有限域上的随机数
   │
   ├──→ 椭圆曲线乘法(secp256k1)
   │
   ├──→ 公钥 (Public Key)
   │      └── 由私钥唯一确定,但反向不可行(椭圆曲线离散对数问题)
   │
   ├──→ SHA-256 → RIPEMD-160 → Base58Check 编码
   │
   └──→ 地址 (Address)
          └── 公钥的压缩/编码版本,用于接收资产

7.2 地址生成的完整流程(Bitcoin 示例)

1. 私钥 (32 bytes) → secp256k1 → 公钥 (64 bytes 或 33 bytes 压缩)
2. 公钥 → SHA-256 → RIPEMD-160 → Hash160 (20 bytes)
3. Hash160 + 版本前缀 (0x00 主网) → 双重 SHA-256 → 取前 4 bytes 作为校验和
4. 版本前缀 + Hash160 + 校验和 → Base58Check 编码 → 地址
# 关键步骤摘要
hash160 = RIPEMD160(SHA256(public_key_bytes))
checksum = SHA256(SHA256(version_prefix + hash160))[:4]
address = Base58Check(version_prefix + hash160 + checksum)
  • Base58 排除了易混淆字符(0 O I l),减少人工抄写错误
  • 校验和可以检测约 99.99% 的输入错误

7.3 钱包的本质:密钥管理工具

  • 钱包 ≠ 装币容器——币在链上(UTXO 集或账户状态),钱包管理的是密钥
  • 钱包的核心功能:
    • 生成并安全存储私钥
    • 派生公钥和地址
    • 构建并签名交易
    • 查询链上状态(余额、交易历史)
  • 分层确定性钱包(HD Wallet, BIP-32):从单一种子(seed)派生出海量密钥对
    • 种子 → 助记词(mnemonic, BIP-39)→ 便于人类备份与恢复
  • 安全底线:私钥丢失 = 控制权永久丧失,无"密码找回"机制

8.1 签名验证实验:原始消息的正确路径

设置:Alice 使用自己的私钥对交易消息签名

消息 m = "Alice 向 Bob 转账 1 BTC"
私钥 sk_Alice → 签名 σ = sign(sk_Alice, m)

验证:verify(pk_Alice, m, σ) → True  ✓
  • 验证通过意味着:
    1. σ 确实是由与 pk_Alice 配对的私钥生成
    2. m 在签名之后未被修改
  • 这是区块链交易广播前的基本操作

8.2 篡改实验:消息变更导致验证失败

攻击场景:攻击者截获交易,试图修改转账金额

原始消息 m  = "Alice 向 Bob 转账 1 BTC"
篡改消息 m' = "Alice 向 Bob 转账 10 BTC"  (金额篡改)
签名 σ 不变(攻击者没有 Alice 的私钥)

验证:verify(pk_Alice, m', σ) → False  ✗
  • 验证失败的原因:签名 σ 是消息 m 的签名,对 m' 无效
  • 攻击者无法生成新的有效签名(没有私钥),因此篡改被检测
  • 关键结论:签名同时保护了"谁发的"和"发了什么"

8.3 实验扩展与讨论

  • 如果攻击者同时修改消息和签名(用自己的私钥重签名)?
    • 验证时公钥会被替换吗?——不会,因为公钥由交易来源地址确定
    • 除非攻击者控制了 Alice 的完整身份链条,否则无法伪装
  • 重放攻击(Replay Attack):将同一笔签名交易在另一条链上广播
    • 对此 Bitcoin 采用 SIGHASH 类型 + 链标识符防御
  • 讨论:若某人声称"我的私钥被盗了,这笔转账不是我本人的意愿",区块链如何应对?

9.1 DLT 的分类框架:从准入维度理解

  • 分布式账本技术(DLT) 是区块链的上位概念,包含多种实现方式
  • 准入与权限维度,可分为三大类:
分类 读取权限 写入权限 共识参与者
公链(Public) 任何人 任何人(需满足共识条件) 任何人
联盟链(Consortium) 受限或公开 授权节点 联盟成员
许可链(Permissioned) 受限 授权节点 受信任节点集合
  • 分类本质是信任假设的连续谱,而非二分法

9.2 三类链的对比矩阵

维度 公链(Bitcoin/Ethereum) 联盟链(Hyperledger) 许可链(R3 Corda / Quorum)
去中心化程度 高(数千节点) 中(数十节点) 低(数节点)
性能(TPS) 低(7–30) 中(数百–数千) 高(数千–数万)
确定性终局 概率性(需确认数) 即时终局 即时终局
治理结构 社区/协议规则 联盟治理 单一组织/多组织
身份匿名性 伪匿名 已知身份 已知身份
典型场景 开放金融、数字资产 供应链、贸易融资 银行间清算、CBDC

9.3 场景驱动的链选型分析

  • 判断框架(WEF Blockchain Decision Tree 启发):
    1. 是否需要共享数据库?→ 否 → 不需要 DLT
    2. 参与者是否已知且可信?→ 是 → 许可链/联盟链
    3. 是否需要无许可参与?→ 是 → 公链
    4. 数据是否需要公开验证?→ 是 → 公链
  • 产业区块链("链上无币"路径)倾向于联盟链/许可链
  • DeFi / 加密金融倾向于公链——开放性本身就是功能需求
  • 讨论:是否存在混合架构——公链做结算,联盟链做应用层?

10.1 UTXO 模型的深入拆解

  • UTXO = Unspent Transaction Output(未花费交易输出)
  • 核心规则:
    • 每笔交易消耗之前的 UTXO(输入),创建新的 UTXO(输出)
    • 一个 UTXO 只能被花费一次(双花保护的核心)
    • 输入总额 ≥ 输出总额(差额 = 交易手续费)
  • 类比:像现金交易——你手里的每张钞票都是一个"UTXO"
    • 买 $3 咖啡时,你不能撕开 $5 钞票,而是支付整张 $5,找回 $2
交易 1 (Alice → Bob):    输入: UTXO_A($5)    输出: UTXO_B1($3), UTXO_B2($2 找零)
交易 2 (Bob → Carol):    输入: UTXO_B1($3)    输出: UTXO_C($3)

10.2 账户模型的深入拆解

  • 账户模型(Account Model):系统维护全局状态(state),每个地址直接记录余额
    账户 Alice:  余额 5.0 ETH | Nonce 3
    账户 Bob:    余额 1.2 ETH | Nonne 0
    账户 Contract_X: 代码+存储状态
    
  • 交易逻辑:send(from, to, value, data) → 更新余额 + 可选执行合约代码
  • 类比:像银行账户转账——直接借记 sender、贷记 receiver
  • 代表:Ethereum 及其 EVM 兼容链

10.3 UTXO vs 账户模型:对比分析与讨论

维度 UTXO 模型 账户模型
状态粒度 离散输出单元 连续余额 + 合约状态
双花检测 显式(输出是否被花费) 隐式(Nonce 机制)
隐私性 较高(地址可生成多对) 较低(地址余额可追溯)
可编程性 受限(Bitcoin Script) 强大(EVM 图灵完备)
并行处理 天然支持(无冲突 UTXO 可并行) 顺序执行(共享状态冲突)
  • Bitcoin 选择 UTXO → 安全优先、隐私友好、可审计性更强
  • Ethereum 选择账户模型 → 可编程优先、状态管理更灵活
  • 讨论:如果设计一条新链,你会选择哪种模型?为什么?

11.1 Ethereum 的两种账户类型

  • 外部拥有账户(EOA, Externally Owned Account)
    • 由私钥控制
    • 可以发起交易(转账、调用合约)
    • 状态字段:balance, nonce
  • 合约账户(CA, Contract Account)
    • 由合约代码(smart contract code)控制
    • 不能主动发起交易,只能由 EOA 或其他合约调用触发
    • 状态字段:balance, nonce, storage, codeHash
  • 总量:截至 2025 年,Ethereum 已有超过 3 亿个账户

11.2 交易驱动的状态转换机制

状态 S_t                   交易 Tx                   状态 S_{t+1}
┌──────────────┐        ┌────────────────┐        ┌──────────────┐
│ Alice: 5 ETH │        │ from: Alice    │        │ Alice: 4 ETH │
│ Bob:   2 ETH │   →    │ to: Bob        │   →    │ Bob:   3 ETH │
│              │        │ value: 1 ETH   │        │              │
└──────────────┘        │ data: optional │        └──────────────┘
                        │ nonce: 7       │
                        │ sig: ...       │
                        └────────────────┘
  • 状态转换函数:St+1=Apply(St,Tx)S_{t+1} = \text{Apply}(S_t, Tx)
  • 如果 Tx 调用合约:EVM 执行合约字节码,产生更复杂的多步状态变更
  • 状态的每次变更都是确定性的(deterministic):相同输入必定产生相同输出

11.3 Ethereum 账户模型对 DeFi 的意义

  • 账户模型的核心优势:可组合性(Composability)
    • 一个合约可以调用另一个合约(合约间消息传递)
    • 借贷、DEX、稳定币等协议可像"乐高积木"般组合
  • 全局状态统一管理:无需像 UTXO 那样逐一追踪输出
  • ERC-20 标准:统一了代币合约的接口,使不同代币在钱包和 DEX 中可互换使用
  • Ethereum 的设计选择不是偶然——它的目标是世界计算机(World Computer),不仅仅是电子现金
  • 讨论:账户模型的可组合性是否也带来了更大的攻击面?(如重入攻击、预言机操纵)

12.1 本讲实验说明:钱包创建与签名验证

  • 实验目标:通过实际代码操作理解密钥体系的核心机制
  • 环境要求:Python 3 + ecdsa / hashlib 库(或在线工具)
  • 核心任务链
    1. 生成密钥对(私钥 + 公钥)
    2. 从公钥推导地址
    3. 对交易消息签名
    4. 验证签名的有效性
    5. 篡改消息内容,观察验证失败

12.2 实验步骤与关键代码(基于 Bitcoin 类实现)

Step 1: 生成密钥对
  sk = SigningKey.generate(curve=SECP256k1)
  pk = sk.get_verifying_key()

Step 2: 生成地址
  hash160 = RIPEMD160(SHA256(pk_bytes))
  address = Base58Check(0x00 + hash160 + checksum)

Step 3: 签名交易
  message = "Alice 向 Bob 转账 1 BTC"
  signature = sk.sign(SHA256(message))

Step 4: 验证签名
  pk.verify(signature, SHA256(message))  → True

Step 5: 篡改测试
  pk.verify(signature, SHA256(tampered_message))  → False
  • 提交物:截图(显示密钥、地址、签名、验证结果)+ 文字说明

12.3 实验后的思考问题

  • 核心概念对应
    • 私钥 → 控制权(私钥泄露意味着什么?)
    • 公钥 → 验证工具(为什么可以公开?)
    • 地址 → 收款标识(同一个私钥可以生成多个地址吗?)
  • 安全边界
    • 助记词的 12/24 个单词如何恢复完整私钥?
    • 如果私钥文件损坏,有什么恢复手段?没有的话怎么办?
  • 进阶讨论
    • 多重签名(multisig)如何改变"私钥即所有权"的模型?
    • 硬件钱包(Ledger/Trezor)比软件钱包多提供什么安全保障?
  • 讨论:私钥如果存储在交易所服务器上,用户是否还拥有"所有权"?

本讲总结:关键概念地图

密码学基础 (Cryptography Foundation)
  ├── Hash ──────────→ 完整性校验 + 唯一标识 + 区块链接
  ├── Hash Pointer ──→ 可验证链条(篡改检测传导)
  ├── Merkle Tree ───→ 高效包含性证明(轻节点支持)
  └── 数字签名 ──────→ 认证 + 不可抵赖 + 交易授权
         │
         └── 密钥体系 ──→ 私钥=控制权 → 公钥=验证 → 地址=标识
                                │
                分布式账本分类 ←─┘
                  ├── 公链 (开放/无许可/PoW/PoS)
                  ├── 联盟链 (多机构/许可共识)
                  └── 许可链 (权限受控/高吞吐)
                                │
                    UTXO vs 账户模型 ←── Ethereum 引入
                    (离散输出)  (全局状态)   合约账户(CA)

本讲阅读与预习指引

  • 必读
    • 旧讲义 p.106–115(密码学与签名代码)
    • Ethereum.org:"Accounts" 技术文档
  • 选读
    • Narayanan et al. "Bitcoin and Cryptocurrency Technologies" Ch.1–2
    • WEF "Blockchain Beyond the Hype" Decision Tree
  • 预习思考(第 3 讲 Bitcoin 机制设计):
    • 拥有了密码学工具后,如何设计一个"点对点电子现金"系统?
    • 如何防止同一笔钱被花两次(双花攻击)?
    • 在没有中心节点的情况下,谁来决定下一个区块由谁产生?

- 答:区块链无法区分"本人签名"与"私钥被盗后的签名"——这是不可抵赖性的边界