ZKP入门
2025/11/21大约 3 分钟
ZKP入门
本文适合
CTF 密码学 入门学习者。学完你能:理解 ZKP入门 的核心概念和基本用法
一句话判断
ZKP 题一旦挑战可预测、消息不绑定、commitment 可重放或 hash 输入缺失,就不再是“零知识”,而是可伪造的交互或非交互证明。
题目中常见信号
commitment - challenge - response
说明:Sigma 协议结构
使用 hash(commitment
内容 2:statement)`
内容 3:Fiat-Shamir 变换
challenge 由可控 seed 生成
说明:可预测挑战
证明没有绑定消息或上下文
说明:可重放/替换
使用弱 hash 或截断 hash
说明:可能伪造
核心概念
零知识证明要同时满足正确性、可靠性和零知识性。CTF 中常见问题不是证明系统本身,而是实现里把挑战做成可预测、把 statement 漏掉、把 commitment 复用,或者把 hash 承诺写错。
Fiat-Shamir 把交互式挑战改成哈希挑战,但前提是 hash 输入必须完整、不可操控、并绑定所有关键上下文。
最小分析流程
- 画出证明流:承诺、挑战、响应、验证公式。
- 检查 challenge 来源:随机、哈希、时间种子还是用户可控。
- 检查哈希输入:是否包含 statement、commitment、域分离标签。
- 尝试重放已有证明或替换消息。
- 若挑战可预测,直接伪造证明或预计算响应。
最小验证示例
import hashlib
statement = b"prove:42"
commitment = b"A"
challenge = hashlib.sha256(commitment + statement).hexdigest()
print(challenge)如果把 statement 去掉或改成可控输入,challenge 就会变成可预测或可碰撞的值。真实题中要检查服务端是否真的把所有关键字段都喂进了哈希。
常见利用 / 解题路线
路线总览:
- 可预测挑战:利用时间种子或弱 PRNG 预先算出响应。
- 重放攻击:复用已有证明,尤其是缺少会话绑定时。
- 哈希输入缺失:利用 omitted statement / commitment 伪造 proof。
- 弱 hash:碰撞或前缀控制导致 Fiat-Shamir 失效。
- 参数错误:小子群、错误群阶或验证公式写错。
常见失败原因
证明总是失败
排查动作:检查 statement、commitment、response 顺序
挑战值不一致
排查动作:确认哈希编码、字节顺序和域分离
重放没用
排查动作:可能绑定了会话 ID 或时间戳
伪造响应不过
排查动作:验证器可能还检查了额外约束
迷你案例
题目里证明过程是 A -> hash(A) -> z,但 hash 只输入了 A,没有输入 statement。你替换 statement 后 challenge 不变,于是可以把旧响应直接重放,服务端误以为你证明了新的命题。这个案例说明零知识证明一旦上下文绑定漏掉,安全性就会塌。