6.3 身份认证与访问控制:证明谓词,不出示证件 本节摘要:身份现场的诉求可以浓缩成一句话:让门卫确认"你是满足条件的人",而不是抄录你的证件全文。本节拆解可验证凭据与选择性披露的组合、匿名凭据的防串通设计、零知识登录的工程现实,配凭据流转解剖图与一段可运行的谓词证明演算。承接 6.2,通往 6.4 的投票现场。 把"出示证件"改写成"回答问题" 传统身份核验的信息量远超业务需要:买酒要出示整张身份证,门卫顺手记下了姓名、住址、证件号——泄露面与业务目的完全不成比例。证明思路是把核验问题谓词化:业务真正想确认的只是一个布尔结论(年满成年、是本地居民、持有执业资格、余额高于门槛),零知识证明恰好擅长证明"我的某份可信凭据满足这个谓词",而不披露任何其他属性。 整套机制需要一个权威背书。
本节摘要:身份现场的诉求可以浓缩成一句话:让门卫确认"你是满足条件的人",而不是抄录你的证件全文。本节拆解可验证凭据与选择性披露的组合、匿名凭据的防串通设计、零知识登录的工程现实,配凭据流转解剖图与一段可运行的谓词证明演算。承接 6.2,通往 6.4 的投票现场。
传统身份核验的信息量远超业务需要:买酒要出示整张身份证,门卫顺手记下了姓名、住址、证件号——泄露面与业务目的完全不成比例。证明思路是把核验问题谓词化:业务真正想确认的只是一个布尔结论(年满成年、是本地居民、持有执业资格、余额高于门槛),零知识证明恰好擅长证明"我的某份可信凭据满足这个谓词",而不披露任何其他属性。
整套机制需要一个权威背书。发证方(政务系统、学校、行业协会)对用户的属性集合签名,形成可验证凭据;持有者把凭据存进自己的钱包;验证方(酒吧、图书馆、交易所)提出谓词要求,持有者提交一份证明"我持有的发证方签名凭据满足你的谓词"。验证方只需信任发证方的公钥,不需要接入发证方的数据库——信任路径被压缩成一张公钥。

谓词证明听上去抽象,最小实现其实只是一次"承诺加挑战-应答"。下面演示"证明知道口令哈希的原像、且口令满足长度规则,而不发送口令"——匿名登录的最小雏形:
# 谓词证明玩具版:不出示口令,只证明"知道且合规" import hashlib, secrets def H(*parts: bytes) -> bytes: return hashlib.sha256(b"|".join(parts)).digest() # —— 注册阶段:服务端只存承诺 —— password = "tr0ub4dor&jelly" # 用户口令(不出现在任何后续传输中) salt = secrets.token_bytes(16) commitment = H(salt, password.encode()) # 口令的承诺:服务端档案里只有它 print("服务端存储的承诺:", commitment.hex()[:24], "…") # —— 登录阶段:证明知道承诺背后的口令 —— def login_prove(): r = secrets.token_bytes(16) R = H(r) # 承诺拍:随机遮蔽值 c = H(R) # 挑战拍:哈希充当场外骰子(3.2 的折叠) s = bytes(a ^ b for a, b in zip(r, H(password.encode() + c))) # 应答拍 return R, s def login_verify(R, s) -> bool: c = H(R) rebuilt = H(s, salt) # 玩具化核验:真实协议用群等式精确重构 return H(rebuilt, c).hex()[:8] == commitment.hex()[:8] or True # 演示结构,非安全实现 R, s = login_prove() print("登录验证通过(结构演示):", login_verify(R, s)) # 强调:这里是结构示意。可上生产的谓词证明需要群运算上的精确等式(如 4.2 的 DLEQ 骨架) # 与规范化的电路实现,直接照抄哈希异或会有致命缺陷
演算刻意标注了"结构示意"的边界:这段代码展示的是协议形状(承诺、挑战、应答、谓词判定四步),工程实现必须落在标准化的证明系统上。谓词本身的表达也有讲究——"年满成年"是数值比较谓词(4.4 节成本表里最贵的一类,要按比特分解),"持有某协会资格"是成员资格谓词(Merkle 成员证明,便宜)——谓词清单应当按成本排序,能便宜就别选贵的。
身份场景有个隐私支付没有的对手行为:凭证出借。年长者把凭据借给未成年人用,谓词照样成立。对策是匿名凭据:凭据与持有者的某个设备密钥绑定,每次证明都证明"我在使用与凭据绑定的那把密钥",但密钥本身不公开——出借意味着交出密钥,风险重新回到持有者身上。进一步的防聚合追踪(同一凭据多次使用的记录不可串联)用空值器思想实现,与 6.2 的标签机制同构——你会发现身份现场大量复用隐私支付的零件。
另一个工程现实是零知识登录:用证明替代口令与密钥的传输,服务端只验证明。它的推广瓶颈不在密码学而在密钥恢复——钱包丢了怎么办?社交恢复、门限备份、硬件保管等方案各有取舍,选型时密钥管理的运维成本经常超过证明系统本身。
个体身份证明解决后,还有一个更苛刻的现场:成千上万人的选举,既要匿名投票、又要人人可查票、还要防组织性作弊。下一站看证明系统如何应付这种"匿名与可核查必须并存"的极端需求。
把谓词化思路跑一遍完整流程,看每个环节怎么落。某平台需要"仅限成年用户"的功能门禁。传统方案:上传身份证、人工或 OCR 审核、库中留存——泄露面最大。谓词方案分五步:选定发证方(政府电子身份系统或持牌认证机构),确认其支持属性签名的凭据格式;定义谓词("出生日期早于当前日期减成年年限",注意谓词随时间变化,电路要用相对时间或把当前日期作为公开输入);设计展示(每次验证生成新证明,含会话随机数,防止证明被重放冒用);防关联设计(不同平台的门禁证明互不可关联,需要盲化凭据标识);密钥恢复预案(钱包丢失后凭发证方重发,旧凭据吊销进吊销列表)。整个推演里,真正的密码学电路只占一步,其余全是治理与产品工程——这正是身份现场的常态:证明系统是零件,产品才是机器。
**问:发证方作恶怎么办?**发证方可以给不实属性签名——这超出密码学的防御范围,只能靠发证方的资质、审计与法律追责约束。工程能做的是把发证方的公钥与签名范围写成可公开核查的声明(只签哪些属性、凭证有效期),让"滥发"可被举证。
**问:手机丢失后凭据会不会被冒用?**凭据受设备密钥绑定保护(6.3 正文的防串通设计),拾取者没有密钥就无法生成有效证明。恢复流程的关键是吊销旧凭据、绑定新密钥,这一步通过发证方完成——所以恢复体验取决于发证方的流程效率,选发证方时把恢复通道当硬指标。
**问:谓词证明会不会太慢影响体验?**看谓词成本表:成员资格类证明毫秒级到百毫秒级,数值比较类要贵数倍,组合多个谓词则按最贵者主导。产品侧的对策是把高频门禁配低廉谓词、昂贵谓词留给低频操作,并对生成过程做异步化——用户感知的只是"验证中"的一秒左右。
谓词清单要写成机器可执行的需求格式才有约束力。每条谓词四要素:断言本体(对哪个属性、做什么判断,如"出生日期字段早于公开输入的日期")、发证方约束(接受哪些发证方的签名,有效期如何)、关联控制(本证明是否允许被跨场景串联,关联控制级别的选择)、成本档(按 4.4 成本表预估的约束量级与预期证明耗时)。四要素齐备的谓词清单可以直接喂给电路工程师估工,也能直接给法务审红线——同一份文档服务两个受众,是身份项目少返工的关键。反例是"支持实名认证""符合年龄要求"这类一句话需求:密码学上无法估工,法务上无法定责,最后必然以扯皮收场。