以太坊从工作量证明切换到权益证明后,验证者要签名的消息种类突然变多:提议区块要签、投票要签、同步委员会要签、证明自己被抽中也要签。多到一定程度,一个新问题浮出水面:同一把验证者密钥在不同场合签出来的东西,怎么保证不会互相冒充、不会从测试网搬到主网、不会从上一个分叉期拖进下一个分叉期?共识规范给出的答案不是加多套密钥,而是在每一次签名的哈希里塞进三段带位置的字节:这个签名是干什么用的、处于哪个分叉版本、发生在哪条链的哪一次创世。
签名的不是消息,是带上下文的承诺
按共识规范的写法,验证者从不直接对一段投票内容签名。流程是先把被签对象化成默克尔根,再把它和分叉数据拼进签名数据结构,连同域值一起再取一次根,最终交给 BLS 签名的是一串”已经绑定完上下文的承诺”。域值本身由四字节用途前缀、对应时段的分叉版本和三十二字节的创世验证者根拼成。用途前缀各有专属值:信标提议、信标投票、RANDAO、委员会抽签、同步委员会,各不相同;分叉版本随升级纪元切换,而创世根在一次创世之后永远不变。三段信息都参与哈希,改任何一段都会让签名对不上。
三种事故各被哪一段挡住

把三段信息对号入座,三类历史隐患就各有各的守门员。跨网络重放:如果攻击者把主网密钥原样搬进测试网(或者反过来),因为两条链的创世验证者根不同,同一份签名在新链上直接无效——这也是各家质押客户端敢在迁移工具里复用密钥的前提。跨职权重放:有人想把一份投票签名冒充成区块提议签名,用途前缀不同导致签名根不同,冒充不成立;若没有这层隔离,同一把密钥签出的两种材料一旦语义可互换,罚没逻辑会凭空多出无数边角案例。跨分叉重放:升级切换分叉版本后,旧版本时期的消息在新版本时期重放会被拒绝,避免状态切换窗口里出现一物两签。
值得补充的是这些字段的可见性。创世验证者根是三十二字节常量,不同网络的公开文档都会写明各自的取值;分叉版本按纪元分组记录在共识规范各升级目录里,节点配置文件中也能看到当前与后续的取值;用途前缀则是规范里固定不变的表。三者都不涉及隐私,任何人都能把一条链上采集到的签名材料拿去核对语境,这也是排查质押事故时最常见的取证动作:先确认签名属于哪条链、哪个时期、哪种职责,再判断它是失效重放还是真的双重签名。
防线也有够不着的地方
要说清楚域值防什么、不防什么:它防的是同一密钥的合法签名被挪用到错误上下文,不防密钥本身被盗——攻击者拿着私钥在正确上下文里签名,任何域值都拦不住,那是运维安全的责任。它也依赖客户端实现正确:如果某个实现错误地把分叉版本或创世根拼错,轻则节点与全网无法达成签名验证,重则给重放留下窗口,这正是规范用一致性测试盯着的部分。普通用户接触不到域值字段,但它可以解释两个常见现象:为什么质押迁移工具只搬签名保护库和密钥、不需要重新登记身份;为什么测试网签出的任何”证据”拿到主网都是废纸。核验一份签名属于哪条链哪个用途,理论上就是把三段前缀拆开对照规范表,区块浏览器与客户端日志里看到的不同签名类型标签,底层就是这些前缀。(风险提示:本文仅为签名机制说明,不构成安全产品推荐或投资建议。)
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。