BLS签名理论原理和工程实现

BLS签名简介

BLS 签名方案最初是由斯坦福大学教授 DanBoneh 等人于 2001 年就提出的一种签名方案(原论文地址[1]),而在 2018 年,Boneh 教授还与 IBM 研究机构的 ManuDrijvers 等人更新了这种签名方案(原论文地址[2])。

双线性映射e函数

BLS签名算法就是基于双线性映射构造的,在给出具体的签名算法之前,我们需要了解一下什么是双线性映射。

对于一个质数双线性群可以由五元组 ( p , G 1 , G 2 , G T , e ) (p,G1,G2,GT,e) 来描述。五元组中 p p 是一个与给定安全常数 λ λ 相关的大质数, G 1 , G 2 , G T G1,G2,GT 均是阶为 p p 的乘法循环群, e e 为双线性映射 e : G 1 × G 2 G T e:G1×G2→GT ,它满足以下3个条件:

  • 双线性(Bilinearity):对于任意的 g G 1 h G 2 a , b Z p g∈G1,h∈G2,a,b∈Zp ,有 e ( g a , h b ) = e ( g , h ) a b e(g^a,h^b)=e(g,h)^{ab}
  • 非退化性(Non-degeneracy):至少存在元素 g 1 G 1 , g 2 G 2 g_1∈G1,g_2∈G2 ,满足 e ( g 1 , g 2 ) 1 e(g_1,g_2)≠1
  • 可计算性(Efficiency):对于任意的 u G 1 , v G 2 u∈G1,v∈G2 ,存在有效算法高效地计算 e ( u , v ) e(u,v)

双线性映射,即利用一个特殊地函数,把一条或两条不同曲线上地两个点 P P Q Q 映射为一个数: e ( P , Q ) n e(P,Q) \to n

此外,该函数还具有以下两个特性:

  • e ( P , Q ) n e(P,Q) \to n
  • e ( a P , Q ) = e ( P , a Q ) e(a*P,Q) = e(P,a*Q)
  • e ( P a , Q ) = e ( P , Q a ) e(P^a,Q) = e(P,Q^a)
  • e ( a P , b Q ) = e ( P , a b Q ) = e ( a b P , Q ) e(a*P,b*Q) = e(P,ab*Q) = e(ab*P,Q)
  • e ( P a , P b ) = e ( P , Q ) a b e(P^a,P^b) = e(P,Q)^{ab}
  • e ( P , Q z ) = e ( P x , Q y ) , z = x y e(P,Q^z) = e(P^x,Q^y),z = xy

有关双线性映射的知识,可参考论文"ON THE IMPLEMENTATION OF PAIRING-BASED CRYPTOSYSTEMS"[3]。

Java实现双线性映射

(1)曲线初始化[4]

PairingParameters pairingParameters = PairingFactory.getPairingParameters("params/a1_2_128.properties");
Pairing pairing = PairingFactory.getPairing(pairingParameters);
Element g2 = pairing.getG2().newRandomElement();

(2)产生公私钥

byte[] privateKey = pairing.getZr().newRandomElement().toBytes();
Element secretKey = pairing.getZr().newElementFromBytes(privateKey);
Element publicKey = g2.powZn(secretKey);

(3)将两个点映射为一个数

Element n = pairing.pairing(p, q);
// the type of Q and P is Element.

如何将指定的元素哈希到双线性群中,可参考[4]。

Element h = pairing.getG1().newElementFromHash(byte[] var1, int var2, int var3);
Element h = pairing.getG1().newElementFromBytes(byte[] var1);

BLS签名

BLS签名包括:初始化、密钥生成、签名、验证四个部分,具体构造如下:

(1)初始化

G1, G2 是阶为 p 的乘法循环群,生成元分别是 g1,g2,e 是双线性映射:G1 * G2 \to GT,安全hash函数:H:{0,1}* \to G1,公开参数是 (G1, G2, GT, e, g1, g2,p,H)。

这里示例哈希函数H:{0,1}* \to G1的如何将实现签名消息映射到循环群中的一点:

byte[] msg = "message".getBytes();
byte[] hash = hash(msg, publicKey);
Element h = pairing.getG1().newElementFromHash(hash, 0, hash.length);

(2)密钥生成

选择随机数 x Z x \in Z^\ast ,将 x x 作为私钥,公钥为 v = g 2 x v G 2 v=g_2^x,v \in G2 ,即公私钥对为 ( x , v ) (x,v)

(3)签名

对于消息“message”,首先映射到循环群中的一点,记为 h = H ( m ) h=H(m) ,使用私钥签名,签名结果为 δ = h x \delta = h^x

public Signature signDemo(byte[] message){
    // 随机生成私钥
    byte[] privateKey = pairing.getZr().newRandomElement().toBytes();
    Element secretKey = pairing.getZr().newElementFromBytes(privateKey);
    // 生成公钥
    Element publicKey = systemParameters.powZn(secretKey);
    // hash映射
    byte[] hash = hash(message, publicKey);
    Element h = pairing.getG1().newElementFromHash(hash, 0, hash.length);
    // 签名
    Element signatureElement = h.powZn(secretKey);
    return new Signature(message,publicKey,signatureElement);
}

(4)验签

公钥验证签名,即验证等式 e ( δ , g 2 ) = = e ( h , v ) e(\delta,g_2) == e(h,v) 是否成立。

证明过程如下:
e ( δ , g 2 ) = e ( h x , g 2 ) = e ( h , g 2 x ) = e ( h , v ) e(\delta,g_2) = e(h^x,g_2) = e(h,g_2^x) = e(h,v)

Element p = pairing.pairing(g2,signatureElement);
Element duplicate = pairing.pairing(publicKey,h);
if (duplicate.isEqual(p)) {
    System.out.println("验签成功");
}

本文首发公众号VenusBlockChain,VenusBlockChain致力于区块链技术研究,传播区块链技术和解决方案、区块链应用落地、区块链行业动态等。有兴趣的小伙伴们,欢迎关注。
在这里插入图片描述

参考资料

[1]https://www.iacr.org/archive/asiacrypt2001/22480516.pdf
[2]https://eprint.iacr.org/2018/483.pdf
[3]https://crypto.stanford.edu/pbc/thesis.pdf
[4]https://blog.csdn.net/jingzi123456789/article/details/104944935

发布了117 篇原创文章 · 获赞 284 · 访问量 42万+

猜你喜欢

转载自blog.csdn.net/jingzi123456789/article/details/105735819
今日推荐