盲签名算法原理:从 Chaum 原始方案到 SM2 盲签名的数学构造与安全分析

算法原理 · 2026-08-01

概述

盲签名(Blind Signature)是一种特殊的数字签名协议,由 David Chaum 于 1982 年首次提出,其核心特性是签名者对消息内容不可见,且签名完成后无法将签名与签名过程关联。这一性质使其成为电子现金、匿名投票、匿名凭证等隐私保护应用的基础构件。

与传统数字签名相比,盲签名在签名流程中引入了"盲化"(blinding)步骤:消息持有者在发送消息前先用随机因子对消息进行变换,签名者对变换后的盲消息进行签名,消息持有者再通过"去盲"(unblinding)操作恢复出对原始消息的有效签名。整个过程中,签名者既不知道消息内容,也无法在事后将签名结果与特定的签名会话关联。

本文从 RSA 盲签名的经典构造出发,深入解析其数学原理与安全证明,然后讨论 SM2 盲签名的设计思路和核心挑战(基于 GM/T 0003-2012 的 SM2 椭圆曲线参数),最后分析工程实现中的关键陷阱与典型应用场景。

数学基础:盲签名的形式化定义

1. 安全属性

一个安全的盲签名方案必须满足以下三个核心属性:

(1)不可伪造性(Unforgeability)

与标准数字签名相同,盲签名必须保证:不知道签名私钥的攻击者无法伪造有效签名。形式化定义与 EUF-CMA(Existential Unforgeability under Chosen Message Attack)一致。

(2)不可追踪性(Untraceability / Blindness)

这是盲签名独有的安全属性。形式化定义如下:

给定签名者对两个消息 $m_0, m_1$ 的签名结果 $\sigma_0, \sigma_1$,以及签名过程中产生的两个盲化消息 $\tilde{m}_0, \tilde{m}_1$ 及其对应的签名会话记录,签名者无法以优于随机猜测的概率判断哪个签名对应哪个原始消息。
等价表述:对于任意两个消息 $m_0, m_1$ 和它们的签名 $\sigma_0, \sigma_1$,存在一个随机因子 $r$ 使得 $\sigma_0 = \text{Unblind}(\text{Sign}(\text{Blind}(m_0, r)))$ 且 $\sigma_1 = \text{Unblind}(\text{Sign}(\text{Blind}(m_1, r')))$,签名者无法区分 $(\sigma_0, \sigma_1)$ 与 $(m_0, m_1)$ 的对应关系。

(3)不可链接性(Unlinkability)

签名完成后,给定一个签名 $\sigma$ 和签名过程中的盲化消息 $\tilde{m}$,签名者无法判断 $\sigma$ 是否由 $\tilde{m}$ 签名后去盲得到。这是比不可追踪性更强的属性,要求即使签名者保存了所有签名会话的完整记录,也无法在事后建立关联。

2. 盲化-签名-去盲三步范式

所有盲签名方案都遵循统一的三步结构:

CODE
消息持有者 (User)                签名者 (Signer)
    |                                |
    |  1. Blind: m̃ = Blind(m, r)    |
    |------------------------------->|
    |                                |
    |  2. Sign: σ̃ = Sign(sk, m̃)    |
    |<-------------------------------|
    |                                |
    |  3. Unblind: σ = Unblind(σ̃, r)|
    |                                |

其中 $r$ 是消息持有者选择的随机盲化因子,$sk$ 是签名者私钥。最终 $\sigma$ 是对原始消息 $m$ 的有效签名,但签名者不知道 $m$ 的内容,也无法将 $\sigma$ 与签名会话关联。

RSA 盲签名:Chaum 的原始构造

1. 算法描述

RSA 盲签名基于 RSA 加密的同态性质:$(m_1 \cdot m_2)^d \equiv m_1^d \cdot m_2^d \pmod n$。

密钥生成:与标准 RSA 相同

  • 选择两个大素数 $p, q$,计算 $n = p \cdot q$
  • 选择公钥指数 $e$,计算私钥指数 $d \equiv e^{-1} \pmod{\phi(n)}$
  • 公钥 $pk = (n, e)$,私钥 $sk = d$
盲化: 消息持有者选择随机盲化因子 $r \in \mathbb{Z}_n^*$,计算盲消息: $$\tilde{m} = m \cdot r^e \pmod n$$

签名: 签名者对盲消息计算签名: $$\tilde{\sigma} = \tilde{m}^d \pmod n$$

去盲: 消息持有者去除盲化因子: $$\sigma = \tilde{\sigma} \cdot r^{-1} \pmod n$$

正确性验证: $$\sigma = \tilde{\sigma} \cdot r^{-1} = (m \cdot r^e)^d \cdot r^{-1} = m^d \cdot r^{ed} \cdot r^{-1} = m^d \cdot r \cdot r^{-1} = m^d \pmod n$$

最终 $\sigma = m^d \pmod n$ 正是对原始消息 $m$ 的标准 RSA 签名。

2. 安全分析

不可追踪性证明(直觉版):

对于任意盲化消息 $\tilde{m}$ 和签名 $\tilde{\sigma}$,消息持有者可以选择不同的盲化因子 $r$ 来生成不同的 $(m, \sigma)$ 对。给定 $\tilde{m}$ 和 $\tilde{\sigma}$,对于任意消息 $m^*$,都存在 $r^* = \tilde{m} \cdot (m^*)^{-1} \pmod n$ 使得 $\tilde{m} = m^* \cdot (r^*)^e$。因此,签名者无法从 $\tilde{m}$ 推断出原始消息。

安全假设:

  • RSA 问题的困难性:给定 $n, e$ 和 $c = m^e \pmod n$,计算 $m$ 是困难的
  • 盲化因子 $r$ 的随机性:$r$ 必须从 $\mathbb{Z}_n^*$ 中均匀随机选择

3. 安全陷阱:参数重用攻击

关键陷阱:如果消息持有者在不同签名会话中重用同一个盲化因子 $r$,则签名者可以通过观察两个盲消息 $\tilde{m}_1 = m_1 \cdot r^e$ 和 $\tilde{m}_2 = m_2 \cdot r^e$ 计算 $\tilde{m}_1 / \tilde{m}_2 = m_1 / m_2$,从而推断消息之间的关系。

防护:每次签名会话必须生成独立的随机盲化因子。

SM2 盲签名:设计思路与核心挑战

1. 背景

SM2 椭圆曲线公钥密码算法系列标准(GM/T 0003-2012)定义了 SM2 数字签名算法(GB/T 32918.2-2016)。与 RSA 不同,SM2 签名不具备"乘法同态"性质,因此不能直接套用 Chaum 的构造方法。

重要说明:SM2 盲签名目前尚无正式国家标准,相关研究主要参考 ISO/IEC 14888-3(数字签名 第3部分:基于离散对数的机制)和 IEEE P1363.3 中的盲签名框架,并结合 SM2 特定参数进行适配。本节给出一个简化的教学模型,用于说明盲签名在椭圆曲线上的设计思路,实际生产应采用经过严格安全证明的方案。

2. SM2 与 RSA 在盲签名构造上的核心差异

特性RSA 盲签名SM2 盲签名(EC 方案)
数学基础模幂乘法同态椭圆曲线标量乘法
盲化操作模乘:$\tilde{m} = m \cdot r^e$点加:$R = [r]G$,$\tilde{e} = e + x_1$
去盲操作模乘:$\sigma = \tilde{\sigma} \cdot r^{-1}$模减:$\sigma = \tilde{\sigma} - r$
签名输出单个值 $\sigma$通常包含椭圆曲线点
安全性基于 RSA 问题基于 ECDLP

3. 简化的 EC 盲签名教学模型

以下构造是一个概念性模型,用于说明盲签名在椭圆曲线上的工作原理。注意:此模型简化了部分细节,并非生产可用方案。

算法参数(使用 SM2 推荐曲线参数):

参数说明值
$E$椭圆曲线$y^2 = x^3 + ax + b$ over $\mathbb{F}_p$
$G$基点$(x_G, y_G)$,阶为素数 $n$
$n$基点阶FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF 7203DF6B 21C6052B 53BBF409 39D54123
$d_A$签名私钥随机整数 $[1, n-1]$
$Q_A$签名公钥$Q_A = [d_A]G$
步骤 1:密钥生成

签名者生成 SM2 密钥对:

  • 私钥:$d_A \in_R [1, n-1]$
  • 公钥:$Q_A = [d_A]G$
步骤 2:盲化(消息持有者执行)

  • 选择随机盲化因子 $k \in_R [1, n-1]$
  • 计算盲化点 $R = [k]G = (x_1, y_1)$
  • 计算消息哈希:$e = \text{SM3}(m)$
  • 计算盲化哈希:$\tilde{e} = e + x_1 \pmod n$
  • 发送 $(\tilde{e}, R)$ 给签名者(注意:此处传递 $R$ 是构造需要,不同方案可能不同)
步骤 3:签名(签名者执行)

  • 收到 $(\tilde{e}, R)$
  • 选择随机数 $t \in_R [1, n-1]$
  • 计算签名分量:$s = (d_A \cdot \tilde{e} + t) \pmod n$
  • 发送 $s$ 给消息持有者
步骤 4:去盲(消息持有者执行)

  • 计算去盲签名:$\sigma = s - k \pmod n$
  • 最终签名为 $(e, \sigma, R)$
验证方程:

验证者收到 $(e, \sigma, R)$,检查: $$[\sigma]G + [e]Q_A = R + [d_A \cdot \tilde{e} + t - k]G + e \cdot [d_A]G$$

教学说明:上述验证方程仅用于说明盲签名验证的一般结构。实际 SM2 盲签名方案中,验证方程的构造更为复杂,需确保既能验证签名有效性,又不泄露签名者身份。建议参考 ISO/IEC 14888-3 和学术文献(如 Pointcheval, Stern 等关于 EC 盲签名的论文)获取严格构造。

4. 与标准 SM2 签名的关系

标准 SM2 签名(GB/T 32918.2-2016)流程:

  • 计算 $e = \text{SM3}(Z_A \| M)$
  • 选择随机 $k$,计算 $[k]G = (x_1, y_1)$
  • 计算 $r = (e + x_1) \pmod n$
  • 计算 $s = ((1 + d_A)^{-1} \cdot (k - r \cdot d_A)) \pmod n$
  • 签名为 $(r, s)$
SM2 盲签名的核心区别在于:
  • 盲化阶段由消息持有者引入随机因子,而非签名者
  • 签名者不直接看到消息哈希 $e$,而是看到盲化后的 $\tilde{e}$
  • 去盲阶段恢复出对原始消息的有效签名
  • SM2 签名包含 $(r, s)$ 两个分量,盲签名构造需要更复杂的交互

工程实现与代码示例

1. Python 实现(基于 gmssl — 教学演示版)

以下代码演示盲签名的核心流程。注意:gmssl 3.2.x 不直接提供盲签名 API,本示例基于底层原语组合,用于教学演示而非生产使用。

2. 关键工程陷阱

陷阱 1:盲化因子重用

如果同一消息持有者在不同会话中重用盲化因子 $k$,签名者可以通过观察多个盲化消息推断消息之间的关系。

PYTHON
# ❌ 错误:重用盲化因子
k_fixed = 12345  # 固定盲化因子
e1_tilde, _ = blind_message(msg1, k_fixed, G)
e2_tilde, _ = blind_message(msg2, k_fixed, G)
# ✅ 正确:每次会话生成独立随机因子
k1 = int.from_bytes(os.urandom(32), 'big') % n
k2 = int.from_bytes(os.urandom(32), 'big') % n

陷阱 2:盲化因子泄露

如果盲化因子 $k$ 泄露给签名者,签名者可以计算 $e = \tilde{e} - x_1$ 恢复原始消息哈希,从而破坏不可追踪性。

防护:盲化因子必须安全存储,签名完成后立即删除。

陷阱 3:签名者侧信道攻击

签名者在计算盲签名时,如果实现不当,可能通过侧信道(如功耗、时间)泄露私钥信息。

防护:使用恒定时间实现,对关键操作进行盲化(对私钥操作引入随机掩码)。

陷阱 4:验证方程设计错误

EC 盲签名的验证方程设计远比 RSA 复杂。如果方程设计不当,可能导致:

  • 签名可被伪造
  • 盲化因子可被恢复
  • 签名者隐私被破坏
防护:参考 ISO/IEC 14888-3 等标准文档,验证方程需经过严格的安全证明。

应用场景

1. 电子现金(e-Cash)

Chaum 最初提出盲签名的动机是实现匿名电子支付:

  • 用户生成一个序列号(代表一枚硬币),盲化后发送给银行
  • 银行对盲化序列号签名(相当于背书),扣除用户账户余额
  • 用户去盲得到对序列号的有效签名
  • 用户将签名后的序列号支付给商家
  • 商家验证银行签名,确认硬币有效
匿名性:银行无法将签名后的硬币与用户关联,因为签名时银行看到的是盲化后的序列号。

防双花:需要额外的机制(如 Brands 的受限盲签名)来防止同一枚硬币被花费两次。

2. 匿名凭证(Anonymous Credentials)

盲签名是实现匿名身份凭证的核心技术:

  • 用户向身份提供者(IdP)证明自己的身份属性(如年龄 > 18)
  • IdP对用户的公钥或承诺进行盲签名,背书其属性
  • 用户去盲得到签名凭证
  • 用户向服务提供者(SP)出示凭证,证明自己满足条件,但不泄露具体身份
典型系统:
  • Microsoft U-Prove(基于 Brands 凭证)
  • IBM Idemix(基于 CL 签名 + 零知识证明)
  • 国密场景下的匿名身份认证系统

3. 匿名投票(E-Voting)

盲签名在电子投票中的应用:

  • 选民准备选票,盲化后发送给选举委员会
  • 委员会验证选民资格后,对盲选票签名(授权投票)
  • 选民去盲得到签名后的选票
  • 选民将签名选票提交到公告板
匿名性:委员会无法将签名选票与特定选民关联,因为签名时看到的是盲化后的选票。

可验证性:任何人都可以验证委员会签名,确认选票被授权。

与其他签名方案的对比

特性标准签名盲签名群签名环签名
签名者身份公开公开群管理员环成员之一
消息隐私无签名者不可见无无
签名者匿名性无无群内匿名环内匿名
不可追踪性N/A签名者无法追踪管理员可追踪不可追踪
典型应用通用认证电子现金、匿名凭证企业内部审计区块链隐私交易
国密支持SM2/SM3参考 ISO/IEC 14888-3无标准无标准

参考来源

  • Chaum, D. (1982). "Blind Signatures for Untraceable Payments". *Advances in Cryptology — CRYPTO '82*. DOI:10.1007/978-1-4757-0602-4_18
  • GB/T 32918.2-2016《SM2 椭圆曲线公钥密码算法 第2部分:数字签名算法》
  • GM/T 0003-2012《SM2 椭圆曲线公钥密码算法》系列标准
  • ISO/IEC 14888-3:2018《数字签名 第3部分:基于离散对数的机制》
  • Brands, S. (1993). "An Efficient Off-Line Coin System Based on the Representation Problem". CWI Report CS-R9323.
  • Pointcheval, D., & Stern, J. (1996). "Provably Secure Blind Signature Schemes". *Advances in Cryptology — ASIACRYPT '96*.

相关实践