区块链安全是密码学材料与共识秩序的合奏:材料挡住伪造、篡改、抵赖与信息层面的双花企图,共识秩序挡住算力层面的重写企图。本节做一次攻防推演,把四类经典攻击逐个撞向材料墙,随后讨论最脆弱却最常被忽视的环节——密钥管理,最后给出更换密码算法的风险清单。
电子现金要成立,必须保证同一笔钱不被重复花费。数字文件可完美复制的天性让这件事在链下无解:把付款文件复制粘贴、分别交给两家商家,对方验签全都通过、全都发货,事后才发现只有一份钱。密码学材料能判断"签名真伪",却无法判断"这笔钱此前是否已被花掉"——消费历史的唯一性,超出了任何单点密码原语的能力范围,它需要全网对"先后顺序"达成共识。这正是备料车间与熔炉工段的分工线:材料负责验真伪,熔炉负责定顺序。推演四类攻击时,请始终带着这条分工线。
**攻击一:伪造转账(冒充他人)。**攻击者构造"受害者→攻击者"的交易并乱盖签名。撞上的墙:验签用受害者的公钥,伪造签名等价于破解签名算法的难题——上节的玩具实验里"伪造验签 False"在真实参数下的放大版。判定在任意节点本地完成,秒级、无需追查。
**攻击二:篡改历史(偷改账本)。**攻击者潜入某节点改写一笔已上链交易。撞上的墙:改交易→Merkle 根变→区块头变→自身哈希变→后续所有区块的焊缝断裂。要让假账存活,必须重造此后全部区块并让网络接受——这就从"改文件"升级成了"攻熔炉",超出本车间、留给第 4 章。
**攻击三:事后抵赖(否认转账)。**签名人声称"那不是我"。撞上的墙:签名验证公开可复算,任何第三方拿公钥一验便知,不依赖签名人配合。不可否认性由"私钥唯一"背书。
**攻击四:信息层双花(同币并发两笔)。**两笔都带合法签名,都声称花掉同一笔未花费输出。撞上的墙:验签全通过——材料层无能为力!全节点交易池会同时接纳两笔合法签名交易,冲突由"哪笔先进块"裁决,即共识定序。用伪代码把裁决逻辑写清楚:
# 双花冲突的裁决:材料验真,共识定序 tx_a = {"from": "U1", "spend": "coin-77", "to": "商家甲", "sig": "valid"} tx_b = {"from": "U1", "spend": "coin-77", "to": "商家乙", "sig": "valid"} def node_behavior(tx_pool, new_tx): # 验签:两笔都真 —— 材料墙放行 if not verify_signature(new_tx): return "拒收:签名伪造" # 查引用:同一枚硬币 —— 池内标记冲突 for waiting in tx_pool: if waiting["spend"] == new_tx["spend"]: tx_pool.mark_conflict(waiting, new_tx) return "两笔均合法,等待共识定序" tx_pool.add(new_tx) return "入池等待打包" # 打包者选择:先到先得或手续费优先,被选者上链, # 另一笔因引用已消费的输出而失效 —— 顺序即裁决
商家乙若在交易未确认时就发货,就承担了双花风险;确认等待期实质是在等熔炉给出顺序结论。收银台旁贴的"请等待确认",翻译过来就是"请等共识定序完成"。
材料无懈可击时,攻击者绕开材料,直接攻击持钥的人。产业损失的大头从来不是哈希被碰撞或签名被伪造,而是私钥被盗、被骗、被弄丢。评估密钥体系时有两个量化抓手:熵与容错。用代码算一笔助记词的账:
import math # 常见助记方案:从固定词表选词,每个词携带 11 比特熵 wordlist_size = 2048 for words in (12, 15, 24): entropy = words * math.log2(wordlist_size) print(f"{words} 词助记词 -> 熵约 {entropy:.0f} 比特") # 攻击者每秒尝试一亿次碰撞的期望时间 attempts_per_sec = 1e8 space = 2 ** 128 years = space / attempts_per_sec / (3600 * 24 * 365) print(f"穷举 128 比特空间期望耗时约 {years:.1e} 年 —— 宇宙年龄的许多个数量级") # 弱口令对比:人为选的 6 位数字 weak = 10 ** 6 / attempts_per_sec print(f"六位数字口令破解耗时约 {weak:.4f} 秒 —— 熵才是护城河,不是字符数")
结论直白:熵是随机性的度量,不是长度的度量。二十四词助记词的强度建立在"真随机"上,用户自选的生日口令再长也可能被字典攻破。容错则是另一面:助记词备份让人在设备丢失后恢复资产,但备份本身成为新的攻击面——抄在云笔记里的助记词,等于把金库密码贴在公告栏。
⚠️ 现场清单:私钥永不明文出设备;签名尽量在专用硬件(隔离执行环境)内完成;备份离线分片存放;任何索要助记词的"客服""空投""验证"都是诈骗,无例外。
密码算法有服役年限。哈希与签名一旦被理论或工程进展削弱,链需要"换料"——评估一份换料方案,检查项可以固化为流程:
def assess_migration(new_algo, chain_state): checks = [] # 数学成熟度:公开密码分析的年头与强度证据 checks.append(("公开分析年限", new_algo.years_of_scrutiny >= 5)) # 实现生态:多语言库、硬件钱包支持、侧信道审计 checks.append(("实现生态", len(new_algo.production_libs) >= 2 and new_algo.hsm_support)) # 性能与体积:签名尺寸影响区块容量与手续费 checks.append(("签名体积合理", new_algo.sig_bytes <= chain_state.max_sig_bytes)) # 迁移路径:地址格式兼容、双算法过渡期、节点升级门槛 checks.append(("可灰度迁移", new_algo.has_transition_plan)) # 量子抗性(若目标为此):相对已知量子算法的强度论证 checks.append(("抗量子论证", new_algo.quantum_hardness_reported)) return [(k, "通过" if ok else "存疑") for k, ok in checks]
这份清单在第 6 章讨论后量子迁移时会再被调用。比特币的签名算法增配、以太坊对新型签名方案的长期论证,走的都是"先共存、再切换"的渐进路线——材料可以换,但换料期间的账本连续性必须由链式焊缝与共识共同担保。
备料车间到此交付全部材料:化验单(安全目标)、钢印(哈希)、私章(签名)、批量封装(Merkle 树),以及一份攻防交接单——材料挡住伪造、篡改、抵赖与信息层双花,顺序裁决与历史重写的防御移交熔炉工段。带着这份交接单进入铸造车间:下一章看这些材料如何被组装进分布式账本、区块结构与点对点网络,铸出真正跑起来的机器。