Zcash 以 zk-SNARK 为核心提供"屏蔽池":交易通过零知识证明验证合法性,金额、 sender 与 receiver 全部隐匿,隐私是可选功能;Monero 以环签名、隐形地址、机密交易为默认配置:所有交易自动获得隐私,匿名集是全体用户。前者的证明更精深但存在可信设置与"屏蔽率"问题,后者的组合更朴素但依赖参数与生态健康。本节解剖两台机器的工程组合,并用屏蔽率模拟揭示"可选隐私"的统计陷阱。
隐私机器的世界里,长期并立着风格相反的代表作:一台把隐私做成可选的高级选项,另一台把隐私做成人人默认的出厂设置。这个看似产品定位的小差异,实则是隐私工程里牵一发而动全身的战略选择。可选隐私的逻辑是"透明优先、隐私按需":普通交易走透明池(便宜、兼容),敏感交易进屏蔽池(贵、慢、强隐匿)。默认隐私的逻辑是"人人匿名才有人人隐私":所有交易自动套上保护,隐私不再是被审视的例外,匿名集因此天然是全网。
两种哲学的后果差异巨大。可选隐私的屏蔽池是全网的子集——进屏蔽池这件事本身成了信号:"这笔交易有见不得人的理由"。更糟的是屏蔽率长期低迷时,池内交易的统计特征(时间、频率)更容易被圈定。默认隐私没有这个信号问题,但代价是所有用户(包括不在乎隐私的)一起支付隐私开销,且监管摩擦更大(交易所普遍对它设防)。这一节把两台机器拆开对比,再看工程演化的相互借鉴。

Zcash 屏蔽交易的核心流程:付款方构造"值承诺"(金额藏在承诺里)与一枚 zk-SNARK 证明,证明内容是"我花掉的票据确实存在且归我、输入输出金额平衡、金额非负、票据未被花过"——矿工验证证明与承诺的一致性,全程不知金额与对手方。收款方凭私有密钥从备注密文中解出自己的票据。Monero 的组合拳上一节已拆:环签名藏发送者、隐形地址藏接收者、机密交易藏金额、密钥映像防双花。用参数对照表收拢两台机器:
| 维度 | Zcash(屏蔽池) | Monero(默认隐私) |
|---|---|---|
| 发送者隐藏 | SNARK 证明归属,无签名暴露 | 环签名(环大小协议定,逐代扩大) |
| 接收者隐藏 | 屏蔽地址 + 私有备注 | 一次性隐形地址 |
| 金额隐藏 | 值承诺 + 非负区间证明 | Pedersen 承诺 + 区间证明 |
| 防双花 | 票据作废列表(空值集合) | 密钥映像集合 |
| 信任仪式 | 历代参数需多方仪式 | 无 |
| 交易体积 | 证明短,历史版本曾较大 | 恒较大,费用压力 |
| 隐私默认值 | 可选(演化中转默认) | 强制 |
"可选隐私"最深的坑不在密码学,在统计。用模拟把屏蔽率的信号学摊开——观察者如何用"进池率"本身圈定嫌疑人:
import random def shielded_signal(total_users=10000, suspicious=200, shield_rate_normal=0.05, shield_rate_suspicious=0.8, days=30): """普通用户与高敏用户的屏蔽池使用率差异 -> 贝叶斯圈定""" flagged = [] for u in range(total_users): is_suspicious = u < suspicious rate = shield_rate_suspicious if is_suspicious else shield_rate_normal shielded_days = sum(random.random() < rate for _ in range(days)) # 观察者规则:屏蔽交易占比超过一半的用户进入名单 if shielded_days > days * 0.5: flagged.append(is_suspicious) tp = sum(flagged) fp = flagged.count(False) return tp, fp random.seed(21) tp, fp = shielded_signal() print(f"名单共 {tp + fp} 人,其中高敏 {tp} 人,普通人被误圈 {fp} 人") precision = tp / (tp + fp) print(f"精确率 {precision:.0%} —— 但更重要的社会效应:进池=招眼的寒蝉效应")
读数之外还有寒蝉效应:当"进屏蔽池"本身成为嫌疑指标,理性用户会回避屏蔽功能,屏蔽率进一步下滑,匿名集恶性循环缩水——这就是可选隐私的自毁回路,也是 Zcash 后来推动钱包默认屏蔽、统一地址(让透明与屏蔽地址不可区分)的动因。Monero 的默认路线天然免疫此坑,但它的历史包袱在"陈旧环":早期交易的环很小,随着分析技术进步,多年前的交易可能被事后剥掉部分掩护——隐私是"当时的",不是"永久的",协议因此引入防陈旧环机制(拒绝过旧的输出进环)。
陈旧环的侵蚀过程值得用代码看清楚——它是"隐私是当时的"这句话的数学注脚:
def ring_erosion(current_ring_sizes, years_passed, deanon_rate=0.06): """历史环成员逐年被去匿名,真实签名者暴露概率上升""" remaining = {tx: size for tx, size in current_ring_sizes.items()} history = [] for y in range(1, years_passed + 1): for tx in remaining: remaining[tx] = max(1, round(remaining[tx] * (1 - deanon_rate))) avg = sum(remaining.values()) / len(remaining) exposed = sum(1 for v in remaining.values() if v <= 2) history.append((y, avg, exposed)) return history rings = {f"老交易{i}": 11 for i in range(1000)} # 早期协议的默认环 for y, avg, exposed in ring_erosion(rings, years_passed=8): print(f"第 {y} 年后平均有效环 {avg:5.1f},近乎裸奔的交易 {exposed:4d} 笔")
逐年输出里,平均有效环持续缩水、部分老交易的有效掩护跌破临界——防陈旧环机制(拒绝过旧输出再入环)防的正是这种"被时间剥衣服"的攻击,但已经上链的旧交易无法回炉,隐私缺陷随历史永久存档。
Zcash 侧:可信设置从"六人仪式"演进到大规模多方参与(数百参与者,单人诚实即安全),仪式本身的公开审计成为社区年度事件;电路升级频密,历史上一次旁路漏洞(允许伪造证明的电路缺陷)被负责任披露后以硬分叉修复,成为"电路即攻击面"的教科书案例;证明生成算力随电路复杂度上升,轻设备体验靠外包证明与递归聚合改善。Monero 侧:每笔交易拖着整个环的公钥与承诺,体积与费用长期高于透明链,扩容靠环形防弹证明(压缩区间证明体积)逐代改良;因默认隐私,头部交易所普遍限制其出入金,流动性与合规摩擦成为生态现实成本;随机数与环成员选择的细节曾出过统计缺陷(曾有一段时间约一成交易因"零混杂环"被精确去匿名),教训写进了成员选择算法。
⚠️ 选型与审计的两条现场经验:其一,评估隐私链别只看白皮书的密码学清单,要看默认参数与实际使用数据——环大小、屏蔽率、参与地址数,统计现实比数学上界诚实;其二,对"完全匿名不可追踪"的宣传保持职业怀疑,两条产线的历史都证明:攻击面通常出现在实现细节与生态使用模式,而非数学核心。
💡 判词:可选隐私死于信号,默认隐私死于摩擦;两条产线的演化方向,都是在自己的死法上打补丁。
针对这两台机器的公开攻击名录值得过目:对 Monero 的时空分析(时间接近 + 金额承诺旁路的启发式缩小候选集)、陈旧环剥离(利用历史小环交易缩小后续匿名集);对 Zcash 的屏蔽池侧信道(进池出池时间关联、屏蔽-透明转账的时序)、以及针对可信设置废料的理论风险;对两者共通的流量分析与蜜罐渗透。防御与攻击同步进化,但结论稳定:协议给出的是上界,使用模式决定成色——隐私是全网协作的统计产物,从来不是单个用户的私事。下一章它将以新身份(扩容引擎)再次登场。
技术拼图齐了。检验科的最后一站不是仪器,是边界:隐私的法规、伦理与社会影响——技术能做的与人类社会允许做的,在哪里谈判、在哪里握手。