SA+L:花费授权与 key image
在 FCMP++ 中取代“签名”的广义 Schnorr 协议
SA+L(Spend Authorization + Linkability,花费授权 + 可关联性)是每个输入在 Ed25519 上附带的一个小型证明。它表明:“我知道重随机化公钥 Õ 对应的 x 和 y,并且公开的 key image L 等于同一个输出的 x·I”。从技术上讲,它是一个广义 Schnorr 协议(GSP)——由共享秘密绑定在一起的若干个 Schnorr 方程。
一分钟了解广义 Schnorr
普通的 Schnorr 证明的是在一个方程 P = x·G 中知道一个 x。广义版本证明的是知道一组秘密 (w₁, …, wₖ),它们满足若干个关于点的线性方程:
协议与单个密钥的情况相同:
- 选取随机数
α_k,并为每个方程公布A_j = Σ α_k·X_{j,k}; - 挑战值
c = Hs(所有已公布的内容); - 响应值
s_k = α_k + c·w_k; - 验证:对每个
j检查Σ s_k·X_{j,k} = A_j + c·Y_j。
关键细节在于:在 w_k 出现的每个方程中,使用的都是同一个响应值 s_k。因此验证者得知的不只是“知道某些秘密”,而是“对所有方程都知道同样的秘密”。花费授权和 key image 正是这样被关联起来的。
SA+L 证明了哪些方程
公开的有:Õ, Ĩ, R, L 以及生成元 G, T, U, V。花费者的秘密:x, y(输出密钥)和 r_o, r_i, r_r_i(重随机化的“油漆”)。简化来说,SA+L 证明的是如下方程组:
R = r_i·V + r_r_i·T
L = x·Ĩ − (x·r_i)·U 最后一个即 L = x·(Ĩ − r_i·U) = x·I;乘积 x·r_i 作为一个单独的秘密引入,与 R 的关联防止了伪造
规范中的确切方程略有不同(它们仔细处理了需要哪些秘密的乘积以及如何避免泄露),但思路正是如此:一个证明中,x 既“打开”了 Õ,又“生成”了 L。
为什么不直接用签名
在 RingCT 中,CLSAG 同时完成三件事:把输入隐藏在环中、证明花费授权、关联 key image。在 FCMP++ 中,第一项工作由成员证明接手。剩下两项则由一个简单得多的协议解决。这带来了:
- 体积小——每个输入只需几个点和标量;
- 角色分离——持有密钥的设备(硬件钱包)可以计算 SA+L,而没有密钥的电脑负责构建繁重的成员证明;
- 前向保密——得益于密钥中的
y·T(见概述); - 为多重签名打下基础——GSP 的线性结构可以很好地拆分给多个签名者(类似 FROST 的方案)。
签名的内容是什么
和 CLSAG 一样,挑战值 c 包含整笔交易的哈希(前缀、输出、承诺)。因此 SA+L 也起到签名的作用:签名后哪怕改动交易中的一个字节,证明都无法通过验证。
形式化定义见 Luke Parker 的 FCMP++ 论文以及 Rust 实现(monero-oxide 项目)。该协议及其实现已通过外部审计;审计报告的链接汇总在 GitHub 上 Monero Research Lab 的讨论中。