本文主要介绍论文《Short Group Signatures》群签名的go语言版本的具体实现。

本文是在参考 yunfeiyanggzq 的实现基础上,进行了进一步的改造加工,以此为基础进行的详细解释。其代码地址为:

  • https://github.com/yunfeiyangbuaa/BBS04_signature

群签名

在一个群签名方案中,一个群体中的任意一个成员可以以匿名的方式代表整个群体对消息进行签名。与其他数字签名一样,群签名是可以公开验证的,而且可以只用单个群公钥来验证。

群签名主要流程:

流程 解释
生成群 生成群公钥(gpk),群主私钥(gmsk)和群参数
加入群 群主为群成员产生私钥(gsk)和证书(cert)
生成群签名 群成员用私钥和证书产生群签名
群签名验证 其他人通过群公钥、群参数验证群签名信息的有效性(此时其他人仅知道签名者属于哪个群,但无法获取签名者身份信息)
追踪签名者信息 在监管介入场景中,群主通过签名信息可获取签名者证书,从而追踪到签名者身份

PBC库

首先,需要安装GMP库和PBC库,这些都是加密库,由C语言写的,官网地址为:PBC Library

安装方式可以参考上文中的github地址,也可以参考如下的方式安装:

安装 GMP

很多系统都有自带的安装包,在 Debian / Ubuntu 系统中,我们可以这样安装 :

sudo apt-get install libgmp-dev

安装 PBC

环境和编译

为了安装 PBC 库,需要先安装3个环境:

gcc
flex (http://flex.sourceforge.net/)
bison (https://www.gnu.org/software/bison/).

大多数的发行版本都包含了这3个库文件:

sudo apt-get install build-essential flex bison

然后,从 PBC官网 下载安装包(如pbc-0.5.14.tar.gz)并解压。

$ tar -xzvf pbc-0.5.14.tar.gz
$ cd /pbc
$ ./configure
$ make
$ make install
管理库路径

添加 pbc 库文件libpbc.so.1路径。

$ cd /etc/ld.so.conf.d
$ sudo vim libpbc.conf

/etc/ld.so.conf.d路径下新建libpbc.conf文件,内容为:

/usr/local/lib

更新cache:

sudo ldconfig

常用的库函数

Add

func (el *Element) Add(x, y *Element) *Element

说明:两数相加,Add sets el = x + y and returns el.

Invert

func (el *Element) Invert(x *Element) *Element

说明:一个数的倒数,Invert sets el = 1/x and returns el.

Mul

func (el *Element) Mul(x, y *Element) *Element

说明:两数相乘,Mul sets el = x * y and returns el.

PowZn

func (el *Element) PowZn(x, i *Element) *Element

说明:x的 i 次方,PowZn sets el = x^i and returns el.

Neg

func (el *Element) Neg(x *Element) *Element

说明:一个数的负数,Neg sets el = -x and returns el.

Pair

func (el *Element) Pair(x, y *Element) *Element

说明:两个数的配对操作,Pair sets el = e(x,y) where e denotes the pairing operation, and returns el.

Go语言实现

需要实现四个函数功能:

  • K e y G e n ( n ) KeyGen(n) KeyGen(n)

  • $Sign(gpk, gsk[i], M) $

  • V e r i f y ( g p k , M , σ ) Verify(gpk,M,σ) Verify(gpk,M,σ)

  • $Open(gpk, gmsk, M, σ) $

其中,参数解释:

  • g p k gpk gpk 表示的是群公钥,有: g p k = ( g 1 , g 2 , h , u , v , w ) gpk = (g_1, g_2, h, u, v, w) gpk=(g1​,g2​,h,u,v,w)

  • g s k [ i ] gsk[i] gsk[i] 表示的是群成员的私钥,有:$ gsk[i] = (A_i, x_i) $

  • M M M 表示的是需要签名的数据

  • σ σ σ 表示签名后的数据,有:$σ ← (T_1, T_2, T_3, c, s_α, s_β, s_x, s_{δ1}, s_{δ2}) $

  • g m s k gmsk gmsk 是群主持有的一对参数,用于揭示签名的主人,有: $gmsk = (ξ1, ξ2) $

那么,具体如何实现呢?

我们使用Go语言实现,幸运的是,PBC有Go语言的库,官网地址为 pbc · pkg.go.dev

K e y G e n ( n ) KeyGen(n) KeyGen(n)

我们先看一下该函数如何实现:

由论文可知:

产生群公钥

需要先选择两个参数: g 1 , g 2 g_1, g_2 g1​,g2​ :

params:=pbc.GenerateA(160,512)
pairing:=params.NewPairing()
g1:=pairing.NewG1().Rand()
g2:=pairing.NewG2().Rand()

之后,根据运算规则,先定义公钥和群私钥的结构体:

// 群公钥
type Group struct {g1, g2, h, u, v, w  *pbc.Elementpairing             *pbc.Pairing
}// 群主的私钥
type PrivateKey struct {*Groupxi1, xi2, gamma *pbc.Element
}

其中,群私钥PrivateKey里的成员,有:

  • ( x i 1 , x i 2 ) = ( ξ 1 , ξ 2 ) (xi1, xi2) = (ξ_1, ξ_2) (xi1,xi2)=(ξ1​,ξ2​)

  • $gamma = γ $

实现各个参数:

priv.gamma = priv.pairing.NewZr().Rand()
priv.xi1 = priv.pairing.NewZr().Rand()
priv.xi2 = priv.pairing.NewZr().Rand()

之后,参数h 为:

priv.h = priv.pairing.NewG1().Rand()

参数 u, v 为:

temp1 := priv.pairing.NewZr().Invert(priv.xi1)      // Invert sets el = 1/x and returns el.
temp2 := priv.pairing.NewZr().Invert(priv.xi2)
priv.u = priv.pairing.NewG1().PowZn(priv.h, temp1)  // PowZn sets el = x^i and returns el.
priv.v = priv.pairing.NewG1().PowZn(priv.h, temp2)

参数W 为:

priv.w = priv.pairing.NewG2().PowZn(priv.g2, priv.gamma)

组合起来,即实现了群主私钥和群公钥:

  • 群公钥Group: g p k = ( g 1 , g 2 , h , u , v , w ) gpk = (g_1, g_2, h, u, v, w) gpk=(g1​,g2​,h,u,v,w)

  • 群主私钥PrivateKey: ( γ , ξ 1 , ξ 2 , g p k ) (γ,ξ1, ξ2,gpk) (γ,ξ1,ξ2,gpk)

产生群成员私钥

我们知道,群成员的私钥是:$gsk[i] = (A_i, x_i) $,其中:

  • $x_i ← Z^∗_p $

  • $A_i ← g_1^{1/(γ+x_i)} ∈ G1 $

所以,有:

// 群成员的私钥,群成员的私钥中,有保护群公钥
type Cert struct {*Group                // 群公钥A, a *pbc.Element     // A_i, x_i
}

解释:

( A i , x i ) = ( A , a ∗ p b c . E l e m e n t ) (A_i, x_i) = (A, a *pbc.Element) (Ai​,xi​)=(A,a∗pbc.Element)

则,代码有:

cert := new(Cert)
cert.Group = priv.Group
cert.a = priv.pairing.NewZr().Rand()   // 产设X_itemp3 := priv.pairing.NewZr().Add(priv.gamma, cert.a)   // Add sets el = x + y and returns el.
temp4 := priv.pairing.NewZr().Invert(temp3)
cert.A = priv.pairing.NewG1().PowZn(priv.g1, temp4)     // 产设A_i

至此,产生了群成员的私钥

S i g n ( g p k , g s k [ i ] , M ) Sign(gpk, gsk[i], M) Sign(gpk,gsk[i],M)

我们先看一下该函数如何实现:

签名结构体

由论文,我们先定义一个结构体:

// 签名
type Sig struct {m                                                  stringt1, t2, t3, c, salpha, sbeta, sa, sdelta1, sdelta2 *pbc.Element
}

其中,由:

  • m m m 表示需要签名的信息

  • t 1 , t 2 , t 3 t1, t2, t3 t1,t2,t3 表示: T 1 , T 2 , T 3 T_1, T_2, T_3 T1​,T2​,T3​

  • s a l p h a , s b e t a salpha, sbeta salpha,sbeta 表示: s α , s β s_α, s_β sα​,sβ​

  • $ sdelta1, sdelta2$ 表示: s δ 1 , s δ 2 s_{δ1}, s_{δ2} sδ1​,sδ2​

  • s a sa sa 表示: s x s_x sx​

  • c c c 表示: c c c

之后,根据论文,开整。

这些参数怎么计算呢?论文给出了计算公式:

根据这些公式实现即可:

根据公式: α , β ← Z p ∗ α, β \leftarrow Z_{p}^{*} α,β←Zp∗​,有:

alpha := cert.pairing.NewZr().Rand()
beta := cert.pairing.NewZr().Rand()

计算 T 1 , T 2 , T 3 T_1, T_2, T_3 T1​,T2​,T3​

根据公式(1) ,计算 T 1 , T 2 , T 3 T_1, T_2, T_3 T1​,T2​,T3​, 有:

t1 := cert.pairing.NewG1().PowZn(cert.u, alpha)
t2 := cert.pairing.NewG1().PowZn(cert.v, beta)
tmp := cert.pairing.NewZr().Add(alpha, beta)
tmp1 := cert.pairing.NewG1().PowZn(cert.h, tmp)
t3 := cert.pairing.NewG1().Mul(cert.A, tmp1)

计算两个辅助值:$δ_1 \leftarrow xα , δ_2 \leftarrow xβ \in Z_{p}^{*}. $

delta1 := cert.pairing.NewZr().Mul(cert.a, alpha)
delta2 := cert.pairing.NewZr().Mul(cert.a, beta)

其中,cert.a表示群成员私钥 g s k [ i ] = ( A i , x i ) gsk[i] = (A_i, x_i) gsk[i]=(Ai​,xi​) 中的 x i x_i xi​

计算 { R 1 , R 2 , R 3 , R 4 , R 5 } \{R_1, R_2, R_3,R_4,R_5\} {R1​,R2​,R3​,R4​,R5​}

Alice挑选参数:$r_α,r_β, r_x, r_{δ_1}, ; and ; r_{δ_2} $

ralpha := cert.pairing.NewZr().Rand()       // r_α
rbeta := cert.pairing.NewZr().Rand()        // r_β
rdelta1 := cert.pairing.NewZr().Rand()      // r_{δ_1}
rdelta2 := cert.pairing.NewZr().Rand()      // r_{δ_2}
ra := cert.pairing.NewZr().Rand()           // r_x

接下来,根据公式(2) ,计算 { R 1 , R 2 , R 3 , R 4 , R 5 } \{R_1, R_2, R_3,R_4,R_5\} {R1​,R2​,R3​,R4​,R5​}, 有::

 r1 := cert.pairing.NewG1().PowZn(cert.u, ralpha)    // 幂指数
//**********************************************************//r2 := cert.pairing.NewG1().PowZn(cert.v, rbeta)
//**********************************************************//  分别对应论文中的各个参数temp1 := cert.pairing.NewGT().Pair(t3, cert.g2)r3_e1 := cert.pairing.NewGT().PowZn(temp1, ra)uuu := cert.pairing.NewZr().Neg(ralpha)                // Neg sets el = -x and returns el.www := cert.pairing.NewZr().Neg(rbeta)xxx := cert.pairing.NewZr().Add(uuu, www)              // Add sets el = x + y and returns el. r3_e2 := cert.pairing.NewGT().PowZn(cert.ehw, xxx)uuu1 := cert.pairing.NewZr().Neg(rdelta1)www1 := cert.pairing.NewZr().Neg(rdelta2)xxx1 := cert.pairing.NewZr().Add(uuu1, www1)r3_e3 := cert.pairing.NewGT().PowZn(cert.ehg2, xxx1)r3 := cert.pairing.NewGT().Mul(cert.pairing.NewGT().Mul(r3_e1, r3_e2), r3_e3)
//**********************************************************//tt_temp2 := cert.pairing.NewG1().PowZn(t1, ra)tt_temp := cert.pairing.NewZr().Neg(rdelta1)tt := cert.pairing.NewG1().PowZn(cert.u, tt_temp)r4 := cert.pairing.NewG1().Mul(tt, tt_temp2)            // Mul sets el = x * y and returns el.
//**********************************************************//rr_temp2 := cert.pairing.NewG1().PowZn(t2, ra)rr_temp := cert.pairing.NewZr().Neg(rdelta2)rr := cert.pairing.NewG1().PowZn(cert.v, rr_temp)r5 := cert.pairing.NewG1().Mul(rr, rr_temp2)

计算挑战c

根据公式:
c ← H ( M , T 1 , T 2 , T 3 , R 1 , R 2 , R 3 , R 4 , R 5 ) ∈ Z p ∗ c \leftarrow H(M, T_1, T_2, T_3, R_1, R_2, R_3, R_4, R_5) \in Z_p^* c←H(M,T1​,T2​,T3​,R1​,R2​,R3​,R4​,R5​)∈Zp∗​
代码实现为:

 var s strings += t1.String()s += t2.String()s += t3.String()s += r1.String()s += r2.String()s += r3.String()s += r4.String()s += r5.String()s += mc := cert.pairing.NewZr().SetFromStringHash(s, sha256.New())

计算 { s α , s β , s x , s δ 1 , s δ 2 } \{s_α, s_β, s_x, s_{δ_1}, s_{δ_2}\} {sα​,sβ​,sx​,sδ1​​,sδ2​​}

根据公式(3),计算 { s α , s β , s x , s δ 1 , s δ 2 } \{s_α, s_β, s_x, s_{δ_1}, s_{δ_2}\} {sα​,sβ​,sx​,sδ1​​,sδ2​​}

 sig.salpha = cert.pairing.NewZr().Add(ralpha, cert.pairing.NewZr().Mul(c, alpha))sig.sbeta = cert.pairing.NewZr().Add(rbeta, cert.pairing.NewZr().Mul(c, beta))sig.sa = cert.pairing.NewZr().Add(ra, cert.pairing.NewZr().Mul(c, cert.a))sig.sdelta1 = cert.pairing.NewZr().Add(rdelta1, cert.pairing.NewZr().Mul(c, delta1))sig.sdelta2 = cert.pairing.NewZr().Add(rdelta2, cert.pairing.NewZr().Mul(c, delta2))

签名 σ σ σ

根据公式,计算 $σ \leftarrow (T_1, T_2, T_3, c, s_α, s_β, s_x, s_{δ_1}, s_{δ_2}) $

其实,在上面的实现中,我们已经计算出来了 σ σ σ 。即,我们的结构体 Sig 就是 σ σ σ 。

$Verify(gpk, M, σ) $

我们先看一下该函数如何实现:

也就是说,需要根据公式(10),计算出 R 1 , R 2 , R 3 , R 4 , R 5 R_1, R_2,R_3,R_4,R_5 R1​,R2​,R3​,R4​,R5​

计算规则为:

 r1 := g.pairing.NewG1().Mul(g.pairing.NewG1().PowZn(g.u, sig.salpha), g.pairing.NewG1().PowZn(sig.t1, g.pairing.NewZr().Neg(sig.c)))
//**********************************************************//r2 := g.pairing.NewG1().Mul(g.pairing.NewG1().PowZn(g.v, sig.sbeta), g.pairing.NewG1().PowZn(sig.t2, g.pairing.NewZr().Neg(sig.c)))
//**********************************************************//temp1 := g.pairing.NewGT().Pair(sig.t3, g.g2)r3_e1 := g.pairing.NewGT().PowZn(temp1, sig.sa)uuu := g.pairing.NewZr().Neg(sig.salpha)www := g.pairing.NewZr().Neg(sig.sbeta)xxx := g.pairing.NewZr().Add(uuu, www)r3_e2 := g.pairing.NewGT().PowZn(g.ehw, xxx)uuu1 := g.pairing.NewZr().Neg(sig.sdelta1)www1 := g.pairing.NewZr().Neg(sig.sdelta2)xxx1 := g.pairing.NewZr().Add(uuu1, www1)r3_e3 := g.pairing.NewGT().PowZn(g.ehg2, xxx1)r3_tep := g.pairing.NewGT().Mul(g.pairing.NewGT().Mul(r3_e1, r3_e2), r3_e3)yyy := g.pairing.NewGT().Pair(sig.t3, g.w)ggg := g.pairing.NewGT().Pair(g.g1, g.g2)hhh := g.pairing.NewGT().Invert(ggg)r3 := g.pairing.NewGT().Mul(r3_tep, g.pairing.NewGT().PowZn(g.pairing.NewGT().Mul(yyy, hhh), sig.c))
//**********************************************************//tt_temp2 := g.pairing.NewG1().PowZn(sig.t1, sig.sa)tt_temp := g.pairing.NewZr().Neg(sig.sdelta1)tt := g.pairing.NewG1().PowZn(g.u, tt_temp)r4 := g.pairing.NewG1().Mul(tt, tt_temp2)
//**********************************************************//rr_temp2 := g.pairing.NewG1().PowZn(sig.t2, sig.sa)rr_temp := g.pairing.NewZr().Neg(sig.sdelta2)rr := g.pairing.NewG1().PowZn(g.v, rr_temp)r5 := g.pairing.NewG1().Mul(rr, rr_temp2)

再和c做对比:

 var s strings += sig.t1.String()s += sig.t2.String()s += sig.t3.String()s += r1.String()s += r2.String()s += r3.String()s += r4.String()s += r5.String()s += sig.mc_ := g.pairing.NewZr().SetFromStringHash(s, sha256.New())if c_.Equals(sig.c) {fmt.Println("verify_sign   true")return true} else {fmt.Println("verify_sign   false")return false}

O p e n ( g p k , g m s k , M , σ ) Open(gpk, gmsk, M, σ) Open(gpk,gmsk,M,σ)

我们来看看群主是怎么open追踪到是谁签名的:

群主有 ( ξ 1 , ξ 2 ) (ξ_1, ξ_2) (ξ1​,ξ2​),需要计算:
A i ← T 3 / ( T 1 ξ 1 ⋅ T 2 ξ 2 ) A_i \leftarrow T_3/(T_1^{ξ_1} \cdot T_2^{ξ_2}) Ai​←T3​/(T1ξ1​​⋅T2ξ2​​)
即:

temp1 := priv.pairing.NewG1().PowZn(sig.t1, priv.xi1)
temp2 := priv.pairing.NewG1().PowZn(sig.t2, priv.xi2)
temp3 := priv.pairing.NewG1().Mul(sig.t3, priv.pairing.NewG1().Invert(priv.pairing.NewG1().Mul(temp1, temp2)))
fmt.Printf("%X\n", sha256.Sum256(temp3.Bytes()))
return temp3

群签名和Go语言实现细节(BBS04--Short Group Signatures)相关推荐

  1. 群签名和环签名的区别_环签名,聚合签名

    本文主要对当下的一些密码学技术的简单阐述 参考文献: 环签名 环签名(ring signature)是一种数字签名方案,最初由Rivest等人提出,环签名是一种简化的群签名,环签名中只有环成员没有管理 ...

  2. AI干货分享:基于群签名的新一代区块链技术

    来源:启迪之星上海 本文约2700字,建议阅读7分钟. 本文中郭晓峰先生将与大家分享基于VRF的一些新技术,并对DFINITY进行详细的讨论,包括它相对于PoW技术的进步,解决的问题,以及个人理解上的 ...

  3. 群签名和环签名的区别_Monero技术详解(三):核心技术—环签名(1)

    在前文介绍了Monero的一次性地址方案.从方案看来,Monero中的UTXO只有一次性地址,用户地址是产生一次性地址的基础,用户对UTXO的所有权并不能显现地看出来.发送人在每次交易时创建一次性地址 ...

  4. 【区块链与密码学】第9-3讲:群签名方案的安全性要求

    [本课堂内容全部选编自PlatON首席密码学家.武汉大学国家网络安全学院教授.博士生导师何德彪教授的<区块链与密码学>授课讲义.教材及互联网,版权归属其原作者所有,如有侵权请立即与我们联系 ...

  5. 群签名和环签名的区别_环签名方案的研究

    摘要: 信息时代虽然带给我们无限商机与方便,但也充斥着隐患与危险.由于网络容易受到攻击,导致机密信息的泄密,数据被篡改,轻则引发企业,部门工作陷入瘫痪,个人利益受损,重则危及国家安全和社会稳定,因此保 ...

  6. c 多文件全局变量_必须知道的C语言知识细节:C程序编译后内存到底是如何布局...

    「今天是学习C语言第 116 天」 当你选择了一种语言,意味着你还选择了一组技术.一个社区.--Joshua Bloch C语言程序编译以后,代码和数据都必须存放在内存中由CPU执行.理解C程序内存是 ...

  7. 数字签名,盲签名,环签名,群签名

    数字签名 类似在纸质合同上签名确认合同内容,数字签名用于证实某数字内容的完整性(integrity)和来源(或不可抵赖,non-repudiation). 实际应用中,由于直接对原消息进行签名有安全性 ...

  8. 群签名技术的理解和总结

    定义一个群G,G = {U1, U2,...,Ut}.其中群成员可以代表群进行签名.C 表示密钥生成中心KGC. 准备阶段 这个阶段,C会生成各个群成员的私钥和共同拥有的公钥.(缺少的一会在补充) 主 ...

  9. 群签名、环签名、盲签名

    文章目录 群签名 定义 安全性 构造 环签名 定义 安全性 构造 盲签名 定义 安全性 构造 群签名 定义 群签名方案是算法组 Π G S = ( G e n , S i g n , V e r , ...

最新文章

  1. java modelmapper_java - 使用ModelMapper映射抽象类型的字段 - SO中文参考 - www.soinside.com...
  2. 常用模块和面向对象 类
  3. 30年传奇 侯为贵留下的荣耀和遗憾
  4. oracle 判断是否位汉字,js判断字符是否是汉字的两种方法小结
  5. Android中MVC框架的运用
  6. Java的书写汽车价格_ES Java API_基于mget实现多辆汽车的配置与价格对比
  7. 如何在CentOS/RedHat下实现根据源码包创建rpm包
  8. Atitit. 异常的使用总结最佳实践java .net php Vo8f
  9. ezd格式文件怎么打开_支持EZD文本格式的软件,想要打开DXF文本格式,怎样把它改成EZD文本格式...
  10. android手机免费无线投屏电脑方法教程步骤AirServer7
  11. 2. Ruby下载安装
  12. PR转场插件 MAC版 FilmImpact Transition Pack v1-v2
  13. 【微信小程序】生命周期
  14. OS X下修改系统Hosts文件以及苹果手机如何host映射
  15. 五使用计算机上数学课英文,数学课用英语怎么说
  16. EasyExcel:读取Excel数据到List集合中
  17. 2021年秋招简历:张宁宁-硕士-苏州大学-信息与通信工程
  18. h5网页服务器选择,h5制作选择虚拟主机还是服务器
  19. sql时间函数以及格式转换
  20. 【Docker】配置镜像加速器(以腾讯云为例)

热门文章

  1. 使用 break 语句直接强行退出循环
  2. Padding设置方法
  3. Navicat 直接修改查询数据
  4. PhD Debate-8 | 迈向常识知识的高级语义理解
  5. IOS学习---OC基础学习(Foundation)
  6. 精通lambda表达式:Java多核编程pdf
  7. 一纸学习思维导图 Mind Map
  8. 小学阅读方法六种_小学写作手法六种
  9. 根据快递单号,生成快递单号
  10. 计算机组成原理实验二