技术 › FCMP++

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ₖ),它们满足若干个关于点的线性方程:

Y_j = Σ_k w_k · X_{j,k}    对每个方程 j

协议与单个密钥的情况相同:

  1. 选取随机数 α_k,并为每个方程公布 A_j = Σ α_k·X_{j,k};
  2. 挑战值 c = Hs(所有已公布的内容);
  3. 响应值 s_k = α_k + c·w_k;
  4. 验证:对每个 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 证明的是如下方程组:

Õ = x·G + (y + r_o)·T
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 的讨论中。