BBS Signature ################# doc ========================================================== `The BBS Signature Scheme `_ `Zcash Overwinter Consensus and Sapling Cryptography Review `_ `Slide: The BBS Signature Scheme `_ use case ========================================================== 改进oauth2式的bearer access token 改进oauth2 DPoP式的校验形态,不用hmac/hash啥的 verifiable credential,例如driver license overview ========================================================== bbs的核心特征是short group Signature,支持zkp,选择性披露部分消息(Selective Disclosure),而proof of possession本身并不泄漏与原始signature的关联(Unlinkable)。 BLS12-381 pairing curve,同zcash,117~120 bits security。 G1/G2均为r质数阶的subgroup,public key在G2,signature在G1。 random要求CSPRNG。 基于IKM trust setup,结合keyinfo,派生私钥SK。 PK = P2 * SK, P2为G2的生成元。 header 配置信息,signature/proof中都含header。 messages 内容信息,signature全量,proof按需。 Sign ========================================================== Sign(SK, PK, header, messages) 生成确定的generators .. math:: (Q_1, Q_2, H_1, ..., H_L) = createGenerators(L+2) 基于PK、generators、header计算domain,一个hash2scalar映射。 .. math:: domain = calculateDomain(PK, Q_1, Q_2, (H_1, ..., H_L), header) 基于SK、domain, msg1 ... msgL 计算 (e, s),一个expand_message,两个hash2scalar映射。 .. math:: eSOcts = serialize(SK, domain, msg_1, ..., msg_L) eSExpand = expandMessage(eSOcts, expandDST, eSLen) e = hash2scalar(eSExpand[0..(octetScalarLength - 1)]) s = hash2scalar(eSExpand[octetScalarLength..(eSLen - 1)]) 计算A .. math:: B = P1 + Q_1 * s + Q_2 * domain + H_1 * msg_1 + ... + H_L * msg_L A = B * (1 / (SK + e)) signature = (A, e, s) Verify ========================================================== .. math:: ProofVerify(PK, proof, header, ph, disclosedMessages, disclosedIndexes) 同样生成generators、domain 计算B .. math:: B = P1 + Q_1 * s + Q_2 * domain + H_1 * msg_1 + ... + H_L * msg_L 校验签名 .. math:: if e(A, W + P2 * e) * e(B, -P2) != Identity_{GT}, return INVALID return VALID pairing比较简单,:math:`W = octetsToPubkey(PK) = P2 * SK` ProofGen ========================================================== .. math:: proof = ProofGen(PK, signature, header, ph, messages, disclosedIndexes) L为messages总数,R为披露的messages数,U为未披露的messages数 同样生成generators、domain 生成random列表 .. math:: randomScalars = calculateRandomScalars(6+U) (r1, r2, \tilde{e}, \tilde{r}2, \tilde{r}3, \tilde{s}, \tilde{m}_{j1}, ..., \tilde{m}_{jU}) = randomScalars 计算中间参数 .. math:: B = P1 + Q_1 * s + Q_2 * domain + H_1 * msg_1 + ... + H_L * msg_L r3 = r1 ^ -1~mod~r A' = A * r1 Abar = A' * (-e) + B * r1 D = B * r1 + Q_1 * r2 s' = r2 * r3 + s~mod~r C1 = A' * \tilde{e} + Q_1 * \tilde{r}2 C2 = D * (-\tilde{r}3) + Q_1 * \tilde{s} + H_{j1} * \tilde{m}_{j1} + ... + H_{jU} * \tilde{m}_{jU} 计算challenge,同样是hash2scalar .. math:: c = calculateChallenge(A', Abar, D, C1, C2, (i_1, ..., i_R), (msg_{i1}, ..., msg_{iR}), domain, ph) 计算proof .. math:: \hat{e} = c * e + \tilde{e}~mod~r \hat{r}2 = c * r2 + \tilde{r}2~mod~r \hat{r}3 = c * r3 + \tilde{r}3~mod~r \hat{s} = c * s' + \tilde{s}~mod~r for j in (j1, ..., jU): \hat{m}_j = c * msg_j + \tilde{m}_j~mod~r proof = (A', Abar, D, c, \hat{e}, \hat{r}2, \hat{r}3, \hat{s}, (\hat{m}_{j1}, ..., \hat{m}_{jU})) 注意 :math:`j_1, ..., j_U` 是未披露的messages index ProofVerify ========================================================== .. math:: result = ProofVerify(PK, proof, header, ph, disclosedMessages, disclosedIndexes) 同样生成generators、domain 计算C1 .. math:: C1 = (Abar - D) * c + A' * \hat{e} + Q_1 * \hat{r}2 = (A' * (-e) + B * r1 - D) * c + A' * \hat{e} + Q_1 * \hat{r}2 = (A' * (-e) - Q_1 * r2) * c + A' * \hat{e} + Q_1 * \hat{r}2 = A' * (\hat{e} - e * c) + Q_1 * (\hat{r}2 - r2 * c) = A' * \tilde{e} + Q_1 * \tilde{r}2 = C1 计算C2 .. math:: T = P1 + Q_2 * domain + H_{i1} * msg_{i1} + ... + H_{iR} * msg_{iR} C2 = T * c - D * \hat{r}3 + Q_1 * \hat{s} + H_{j1} * \hat{m}_{j1} + ... + H_{jU} * \hat{m}_{jU} = (P1 + Q_2 * domain + H_{i1} * msg_{i1} + ... + H_{iR} * msg_{iR}) * c - D * (c * r3 + \tilde{r}3) + Q_1 * (c * s' + \tilde{s}) + H_{j1} * (c * msg_{j1} + \tilde{m}_{j1}) + ... + H_{jU} * (c * msg_{jU} + \tilde{m}_{jU}) = (P1 + Q_2 * domain + H_1 * msg_1 + ... + H_L * msg_L - D * r3 + Q_1 * s') * c - D * \tilde{r}3 + Q_1 * \tilde{s} + H_{j1} * \tilde{m}_{j1} + ... + H_{jU} * \tilde{m}_{jU} = (B - Q_1 * s - D * r3 + Q_1 * s') * c + D * (-\tilde{r}3) + Q_1 * \tilde{s} + H_{j1} * \tilde{m}_{j1} + ... + H_{jU} * \tilde{m}_{jU} = (B + Q_1 * r2 * r3 - B * r1 * r3 - Q_1 * r2 * r3) * c + D * (-\tilde{r}3) + Q_1 * \tilde{s} + H_{j1} * \tilde{m}_{j1} + ... + H_{jU} * \tilde{m}_{jU} = D * (-\tilde{r}3) + Q_1 * \tilde{s} + H_{j1} * \tilde{m}_{j1} + ... + H_{jU} * \tilde{m}_{jU} = C2 计算cv .. math:: cv = calculateChallenge(A', Abar, D, C1, C2, (i_1, ..., i_R), (msg_{i1}, ..., msg_{iR}), domain, ph) 检查cv是否与c相等 .. math:: if A' == Identity_{G1}, return INVALID if e(A', W) * e(Abar, -P2) != Identity_{GT}, return INVALID e(A', W) * e(Abar, -P2) = e(A', P2 * SK) * e(A' * (-e) + B * r1, -P2) = e(A * r1 * SK, P2) * e( (A * (-e) + B) * r1, -P2) = e(A * r1 * SK, P2) * e( A * SK * r1, -P2) = Identity_{GT} security ========================================================== valid public key valid point prime order check run in constant time nonce reuse attack header中带个nonce G1与G2不同构 DRBG proof replay attack