Skip to content

BBS+ Signature

Threshold BBS+ Signatures for Distributed Anonymous Credential Issuance

Anonymous Attestation Using the Strong Diffie Hellman Assumption Revisited

BBS+ 基本流程

1. KeyGen

  • 假设待签名消息数量为
  • 选择生成元 G1G1G2G2
  • 随机选择 +1 个元素,记为
H=(H0,H1,,H),HiG1
  • 随机选择私钥 x$Zp
  • 计算公钥元素
X=xG2G2
  • 输出:
    • 公钥 pk=(G1,G2,H,X)
    • 私钥 sk=x

2. Sign

给定消息向量:

m=(m1,m2,,m),miZp

签名者执行:

  • 采样随机数 e,s$Zp
  • 构造承诺基点:
C=G1+sH0+i=1miHi
  • 计算
A=(x+e)1C
  • 输出签名:
σ=(A,e,s)

3. Verify

给定消息向量 m 和签名 σ=(A,e,s),验证者检查:

e(A,X+eG2)=?e(G1+sH0+i=1miHi,G2)

若等式成立,则接受该签名。

4. 正确性

因为

A=(x+e)1(G1+sH0+i=1miHi)

所以:

e(A,X+eG2)=e((x+e)1(G1+sH0+i=1miHi),(x+e)G2)=e(G1+sH0+i=1miHi,G2)

因此验证方程成立。

弱盲签名下的BBS+

普通 BBS+ 中,签名者直接看到全部消息。盲签名场景下,用户希望:

  • 某些消息对签名者可见;
  • 某些消息对签名者隐藏;
  • 签名者最终仍然对完整消息向量签名。

这时需要补充 blindblind signunblind 三步。

1. 消息划分

设消息集合被拆成两部分:

  • 显式消息(签名者可见):{mi}iR
  • 隐藏消息(签名者不可见):{mj}jH

其中 RH={1,2,,},且 RH=

2. Blind

用户先对隐藏消息做一个承诺,并发送给签名者。

  • 用户随机选择盲化因子 r$Zp
  • 计算隐藏消息承诺:
Cblind=rH0+jHmjHj
  • 用户将 Cblind 发送给签名者

在更严格的协议中,用户还需要附带一个零知识证明,证明自己确实知道 (r,{mj}jH),否则签名者可能会在无效承诺上签名。

3. Proof of Knowledge of Commitment(PoK)

为了让签名者相信用户不是随意伪造一个群元素,而是真的知道隐藏消息与盲化因子,用户需要对 Cblind 附带一个知识证明。

设隐藏消息个数为 |H|,用户要证明自己知道:

  • 盲化因子 r
  • 隐藏消息 {mj}jH
  • 且它们满足
Cblind=rH0+jHmjHj

这可以用一个基于 Fiat--Shamir 变换的 Sigma 协议来实现。

Prove

用户执行:

  • 随机选择掩码
r~$Zp,m~j$Zp(jH)
  • 构造临时承诺
T=r~H0+jHm~jHj
  • 计算挑战
c=Hash(Cblind,T,|H|)
  • 计算响应值
s^=r~+crm^j=m~j+cmj(jH)
  • 输出证明
πpok=(T,c,s^,{m^j}jH)

Verify

签名者收到 (Cblind,πpok) 后,执行:

  • 重新计算挑战
c=Hash(Cblind,T,|H|)
  • 检查 c=c

  • 检查如下等式是否成立:

s^H0+jHm^jHj=?T+cCblind

若成立,则说明用户确实知道对应的盲化因子和隐藏消息;否则拒绝继续 blind signing。

为什么验证等式成立

因为

s^H0+jHm^jHj=(r~+cr)H0+jH(m~j+cmj)Hj=r~H0+jHm~jHj+c(rH0+jHmjHj)=T+cCblind

因此只要用户知道 (r,{mj}),它就能构造出可验证的响应;而不知道这些值的一方通常无法通过该检查。

4. BlindSign

签名者拿到:

  • 可见消息 {mi}iR
  • 用户提交的承诺 Cblind
  • 用户提交的知识证明 πpok

签名者先验证 πpok,仅在验证通过后继续签名。

然后:

  • 采样随机数 e,s$Zp
  • 构造待签名项
C=G1+Cblind+sH0+iRmiHi
  • 计算盲签名
A=(x+e)1C
  • 输出给用户:
σ=(A,e,s)

5. Unblind

用户收到盲签名 σ=(A,e,s) 后,利用自己掌握的盲化因子 r 计算最终签名。

注意到:

C=G1+Cblind+sH0+iRmiHi=G1+(rH0+jHmjHj)+sH0+iRmiHi=G1+(s+r)H0+k=1mkHk

因此用户令:

s=s+r

并得到标准 BBS+ 签名:

σ=(A,e,s)

这个签名可直接按普通 Verify 算法验证。

6. 为什么解盲成立

由上式可知:

A=(x+e)1(G1+sH0+k=1mkHk)

其中 s=s+r。所以解盲后的 σ=(A,e,s) 与普通 BBS+ 输出格式完全一致。

deprecated

7. 签名重随机

但是很显然,对于签名 σ=(A,e,s) , 签名者给出的 A 和用户最终出示的 A 都是一致的,不满足盲签名的不可链接性,我们需要继续进行如下操作:

  • sample rZp
  • let A=A+rG1
  • so the signature is σ=(A,e,s,r)

此时,我们让验签变为:

e(A,X+eG2)=e(A+rG1,X+eG2)=e(A,X+eG2)e(rG1,X+eG2)=e(C,G2)e(rG1,(x+e)G2)=e(C,G2)e(r(x+e)G1,G2)=e(C+r(x+e)G1,G2)=?e(C+r(X+eG1),G2)

选择性披露(Selective Disclosure)

BBS+ 的核心优势之一,是签名生成后用户可以只披露部分消息,而其余消息保持隐藏,同时仍能证明签名对完整消息向量有效。

1. 核心思想

签名本质上是对承诺 C 的签名:

C=G1+sH0+i=1miHi=(x+e)A

选择性披露的目标:用户持有 (A,e,s,m),希望向验证者证明

  • 自己知道一个有效的 BBS+ 签名;
  • 公开集合 D{1,,} 中的消息 miiD)被正确公开;
  • 隐藏集合 D={1,,}D 中的消息仍被隐藏,但签名对完整 m 依然有效。

2. 凭证随机化(Credential Randomization)

用户执行以下随机化步骤:

  1. 采样随机化因子 r1$Zp

  2. 计算随机化后的 A

    Ar1A
  3. 计算 r3r11

  4. 计算 A¯(隐藏 x 的信息):

    A¯r1CeA
  5. 采样 r2$Zp

  6. 计算辅助值 ds

    dr1Cr2H0,ssr2r3

3. 零知识证明(NIZK / SPK)

用户生成非交互零知识证明(NIZK),证明自己知道隐藏消息、er2r3s

Prover(生成证明 π

  1. 生成随机掩码(Commit):

    m~i$Zp(iD),e~,r~2,r~3,s~$Zp
  2. 计算临时承诺 t1,t2

    t1=Ae~H0r~2(A¯/d)e~t2=dr~3H0s~iDHim~i(G1+iDmiHi)e~
  3. 计算挑战(Fiat-Shamir):

    c=Hash(A, A¯, d, t1, t2, G1, H0,,H, X, m)
  4. 计算响应值:

    si=m~i+cmi(iD)se=e~+ce,sr2=r~2+cr2,sr3=r~3+cr3,ss=s~+cs
  5. 输出证明:

    π=(c, {si}iD, se, sr2, sr3, ss)

最终输出的选择性披露凭证为四元组:

σ=(A, A¯, d, π)

Verifier(验证 π

  1. 检查 A0G1

  2. 检查一个 pairing 等式(只需 1 个 pairing):

    e(A, X)=?e(A¯, G2)
  3. 重新计算承诺并验证挑战:

    t^1=AseH0sr2(A¯/d)set^2=dsr3H0ssiDHisi(G1+iDmiHi)sec=Hash(A, A¯, d, t^1, t^2, G1, H0,,H, X, m)

    检查 c=?c

若全部通过,则接受该选择性披露证明。

4. 正确性证明

  • pairing:

  • lhs=e(A,X)=e(r1A,X)=e(r1Cx+e,X)=e(r1xCx+e,G2)rhs=e(A¯, G2)=e(r1Cer1A,G2)=e(r1Cer1Cx+e,G2)=e(xr1C+er1Cer1Cx+e,G2)=e(r1xCx+e,G2)