likes
comments
collection
share

GoPBC实践 (一):适用于链上计算的密文大小固定的属性基加密机制(On-Chain ABE)

作者站长头像
站长
· 阅读数 11

关于Go PBC Wrapper库的说明介绍在官方文档中已经详细给出,本系列专栏将不再详细介绍官方文档中已有内容,请读者及时翻阅官方文档查看相关函数。

版本说明

PBC LibraryGolanggpbc
Version0.5.141.19.1v0.0.0-20181205041846-3e516ca0c5d6

适用于区块链的密文大小固定的属性基加密机制 (On-Chain Constant-size ABE)

双线性配对

G,GT\mathbb{G},\mathbb{G}_TG,GT 为两个具有相同阶 ppp 的循环乘法群。gggG\mathbb{G}G 的生成元。将 e^\hat{e}e^ 表示为双线性配对:G×G→GT\mathbb{G} \times \mathbb{G} \to \mathbb{G}_TG×GGT。 该双线性配对操作具有以下属性: (1)双线性:e^(ga,gb)=e^(g,g)ab\hat{e}(g^a, g^b)=\hat{e}(g,g)^{ab}e^(ga,gb)=e^(g,g)ab,其中 a,b∈Zp∗a, b \in \mathbb{Z}_p^*a,bZp; (2)非退化性:e^(g,g)≠1\hat{e}(g,g) \neq 1e^(g,g)=1; (3)可计算性:对所有的 g1,g2∈Gg_1, g_2 \in \mathbb{G}g1,g2G 计算 e^(g1,g2)\hat{e}(g_1,g_2)e^(g1,g2) 是很有效的。

ABE Setup

  • U={η1,η2,...,ηn}\mathcal{U}=\{\eta_1,\eta_2,...,\eta_n\}U={η1,η2,...,ηn} 表示应用系统中的 nnn 个属性,其中每个属性都有多个值。

  • Si={vi,1,vi,2,...,vi,n}S_i=\{ v_{i,1}, v_{i,2},..., v_{i,n} \}Si={vi,1,vi,2,...,vi,n} 表示属性 ηi\eta_iηi 的多个值。

  • Attribute Authority (AA) 选择两个随机大数 x,y∈Zp∗x, y \in \mathbb{Z}_p^{*}x,yZp 作为系统私钥 msk=⟨x,y⟩msk=\left \langle x, y \right \ranglemsk=x,yH0H_0H0 是一个哈希函数:{0,1}∗→Zp∗\{0,1\}^* \to \mathbb{Z}_p^*{0,1}Zp

  • 将属性值 SiS_iSi 与属性 ηi\eta_iηi 进行绑定,即设置 Xi,k,Yi,kX_{i,k}, Y_{i,k}Xi,k,Yi,kXi,k=g−H0{x∣∣i∣∣ki},Yi,k=e^(g,g)H0{y∣∣i∣∣ki}X_{i,k}=g^{-H_0\{x||i||k_i\}}, Y_{i,k}=\hat{e}(g, g)^{H_0\{y||i||k_i\}}Xi,k=gH0{xiki},Yi,k=e^(g,g)H0{yiki}, 其中 i(1≤i≤n)i (1\le i \le n)i(1in)U\mathcal{U}U 中的第 iii 个属性 ηi\eta_iηiki(1≤ki≤ni)k_i (1 \le k_i \le n_i)ki(1kini) 是属性值集合 SiS_iSi 中的第 kkk 个值。\

  • 将系统公钥设置为 mpk=⟨g,{Xi,k,Yi,k}⟩mpk=\left \langle g, \{X_{i,k}, Y_{i,k} \} \right \ranglempk=g,{Xi,k,Yi,k}

Setup代码实现

type ABEmsk struct {
	x []byte
	y []byte
}

type ABEmpk struct {
	g   []byte
	X_k [][]string
	Y_k [][]string
}
func OCABE() {
    params := pbc.GenerateA(160, 512)
    pairing := params.NewPairing()

    g := pairing.NewG1().Rand()

    x := pairing.NewZr().Rand()
    y := pairing.NewZr().Rand()
    msk := ABEmsk{
            x: x.Bytes(),
            y: y.Bytes(),
    }

    U := []string{"h1", "h2", "d1", "d2", "p", "c1", "c2", "M"}
    S := [][]string{
            {"a", "b", "c"}, {"e", "f", "g"}, {"h", "i", "j", "k"},
            {"l", "m", "n", "o"}, {"q", "r"}, {"s", "t", "a"}, {"b", "c", "e", "f"}, {"t", "s", "y", "w"},
    }

    X_k, Y_k := computeXY(params.String(), g.Bytes(), U, S, msk)
    mpk := ABEmpk{
            g:   g.Bytes(),
            X_k: X_k,
            Y_k: Y_k,
    }
}

func computeXY(params string, g_ []byte, U []string, S [][]string, msk ABEmsk) (Xik, Yik [][]string) {
	pairing, _ := pbc.NewPairingFromString(params)
	g := pairing.NewG1().SetBytes(g_)

	X := make([][]string, len(U))
	Y := make([][]string, len(U))
	p := pairing.NewGT().Pair(g, g)
	for i := 0; i < len(U); i++ {
		for j := 0; j < len(S[i]); j++ {
			i_j := strconv.Itoa(i) + strconv.Itoa(j)
			x_j := i_j + pairing.NewZr().SetBytes(msk.x).String()

			x_j_zr := pairing.NewZr().SetFromStringHash(x_j, sha256.New())
			x_j_zr = pairing.NewZr().Neg(x_j_zr)
			X_i_k := pairing.NewG1().PowZn(g, x_j_zr)
			X[i] = append(X[i], X_i_k.String())

			y_j := i_j + pairing.NewZr().SetBytes(msk.y).String()
			y_j_zr := pairing.NewZr().SetFromStringHash(y_j, sha256.New())
			Y_i_k := pairing.NewGT().PowZn(p, y_j_zr)
			Y[i] = append(Y[i], Y_i_k.String())
		}
	}

	return X, Y
}

ABE KeyGen

  • LLL 表示用户拥有的属性列表。对于属性列表中的每个属性的值,AA随机选择一个值 sk∈RZp∗sk \in_R \mathbb{Z}_p^*skRZp 来绑定属性与其对应的值。H3H_3H3 是一个防碰撞哈希函数:Zp∗→G\mathbb{Z}_p^* \to \mathbb{G}ZpG
  • 对于属性列表 LLL 中的第 iii 个属性和第 kik_iki 个值,其对应的属性密钥 SKL=⟨sk,{σiˉ}⟩SK_L=\left \langle sk, \{\bar{\sigma_i}\} \right \rangleSKL=sk,{σiˉ}。其中 σiˉ=σi,ki=gH0(y∣∣i∣∣ki)H3(sk)H0(x∣∣i∣∣ki)\bar{\sigma_i}=\sigma_{i,k_i}=g^{H_0(y||i||k_i)}H_3(sk)^{H_0(x||i||k_i)}σiˉ=σi,ki=gH0(yiki)H3(sk)H0(xiki)

KeyGen代码实现

func AttrKeyGen(params string, g_ []byte, msk ABEmsk, n int, userAttr map[string][]int) ([]byte, [][]strin) {
	// fmt.Println("ABE Attributes Key Gen")
	pairing, _ := pbc.NewPairingFromString(params)
	g := pairing.NewG1().SetBytes(g_)
	x := pairing.NewZr().SetBytes(msk.x)
	y := pairing.NewZr().SetBytes(msk.y)
        
	sk := pairing.NewZr().Rand()
	h3_sk_g := pairing.NewG1().SetFromStringHash(sk.String(), sha256.New())

	sigma_keys := make([][]string, n)
	i := 0
	for _, v := range userAttr {
		for j := 0; j < len(v); j++ {
			x_j := strconv.Itoa(i) + strconv.Itoa(v[j]) + x.String()
			y_j := strconv.Itoa(i) + strconv.Itoa(v[j]) + y.String()

			xjk_zr := pairing.NewZr().SetFromStringHash(x_j, sha256.New())
			yjk_zr := pairing.NewZr().SetFromStringHash(y_j, sha256.New())

			tmp1 := pairing.NewG1().PowZn(g, yjk_zr)
			tmp2 := pairing.NewG1().PowZn(h3_sk_g, xjk_zr)
			sigma_key := pairing.NewG1().Mul(tmp1, tmp2)
			sigma_keys[i] = append(sigma_keys[i], sigma_key.String())
		}
		i += 1
	}
	return sk.Bytes(), sigma_keys
}

ABE ENC

  • 由于需要将密文存储的区块链上,所以为了节约存储开销,将密文设置为固定大小。
  • 首先将所有的属性和对应的值整合到一个访问策略 A=⋀i∈IAAi\mathbb{A}=\bigwedge_{i \in \mathcal{I}_{\mathbb{A}}}\mathbb{A}_iA=iIAAi 中。
  • 计算 ⟨XA,YA⟩=⟨∏i∈IAXˉi,∏i∈IAYˉi⟩\left \langle X_{\mathbb{A}}, Y_{\mathbb{A}} \right \rangle = \left \langle \prod\limits_{i \in \mathcal{I}_{\mathbb{A}}} \bar{X}_i, \prod\limits_{i \in \mathcal{I}_{\mathbb{A}}} \bar{Y}_i \right \rangleXA,YA=iIAXˉi,iIAYˉi,其中 ⟨Xˉi,Yˉi⟩=⟨Xi,k,Yi,k⟩\left \langle \bar{X}_i, \bar{Y}_i \right \rangle=\left \langle X_{i,k}, Y_{i,k} \right \rangleXˉi,Yˉi=Xi,k,Yi,k.
  • 在文献[1]中,作者使用AES密钥 kidk_{id}kid 来加解密文件,并保护文件ID ididid
  • Health Center (HC) 选择一个 s∈RZp∗s \in_R \mathbb{Z}_p^*sRZp, 并计算 cid=ABE.Enc(mpk,id∣∣kid,A)=⟨A,C0,C1,C2⟩c_{id}=ABE.Enc(mpk, id||k_{id}, \mathbb{A})=\left \langle \mathbb{A}, C_0, C_1, C_2 \right \ranglecid=ABE.Enc(mpk,idkid,A)=A,C0,C1,C2。其中 C0=(id∣∣kid)⋅YAsC_0=(id||k_{id})\cdot Y_{\mathbb{A}}^sC0=(idkid)YAsC1=gsC_1=g^sC1=gsC2=XAsC_2=X_{\mathbb{A}}^sC2=XAs

ENC代码实现

func ABEenc(params string, g_ []byte, mpk ABEmpk, policA map[string][]int, U []string, msg_ string) (polic map[string][]int, c0, c1, c2 []byte) {
	pairing, _ := pbc.NewPairingFromString(params)
	g := pairing.NewG1().SetBytes(g_)
	s := pairing.NewZr().Rand()
        
	msg_el, _ := pairing.NewGT().SetString(msg_, 0)

	X_A := pairing.NewG1().Set1()
	Y_A := pairing.NewGT().Set1()

	for k, v := range policA {
		index := indexOf(U, k)
		x_i := mpk.X_k[index]
		y_i := mpk.Y_k[index]

		for j := 0; j < len(v); j++ {
			k_i := v[j]
			xi_el, ok := pairing.NewG1().SetString(x_i[k_i], 0)
			if !ok {
				fmt.Println("error set string!")
			}
			yi_el, ok := pairing.NewGT().SetString(y_i[k_i], 0)
			if !ok {
				fmt.Println("error set string!")
			}

			X_A = pairing.NewG1().Mul(X_A, xi_el)
			Y_A = pairing.NewGT().Mul(Y_A, yi_el)
		}
	}

	Y_A_s := pairing.NewGT().PowZn(Y_A, s)
	c0_el := pairing.NewGT().Mul(msg_el, Y_A_s)
	c1_el := pairing.NewG1().PowZn(g, s)
	c2_el := pairing.NewG1().PowZn(X_A, s)
	polic = policA
	return polic, c0_el.Bytes(), c1_el.Bytes(), c2_el.Bytes()
}

ABE DEC

  • 解密过程,类似解密过程,私钥的整合通过 σA=∏i∈IAσˉi\sigma_{\mathbb{A}}=\prod\limits_{i\in \mathcal{I}_{\mathbb{A}}} \bar{\sigma}_iσA=iIAσˉi, 其中 σˉi\bar{\sigma}_iσˉi 是用户的属性列表 SKLSK_LSKL
  • id∣∣kid=C0e^(σA,C1)⋅e^(H3(sk),C2)id||k_{id}=\frac{C_0}{\hat{e}(\sigma_{\mathbb{A}}, C_1)\cdot\hat{e}(H_3(sk), C_2)}idkid=e^(σA,C1)e^(H3(sk),C2)C0C0,C1,C2C_0, C_1, C_2C0,C1,C2对应的就是如上所述的密文。

DEC代码实现

func ABEdec(params string, c0_, c1_, c2_, sk_ []byte, sigma_keys_ [][]string) (plaintext string) {
	pairing, _ := pbc.NewPairingFromString(params)
	c0 := pairing.NewGT().SetBytes(c0_)
	c1 := pairing.NewG1().SetBytes(c1_)
	c2 := pairing.NewG1().SetBytes(c2_)

	sk := pairing.NewZr().SetBytes(sk_).String()
	sk_h3_el := pairing.NewG1().SetFromStringHash(sk, sha256.New())

	tmp1 := pairing.NewGT().Pair(sk_h3_el, c2)

	sigma_A := pairing.NewG1().Set1()
	for _, sigma_key := range sigma_keys_ {
		for j := 0; j < len(sigma_key); j++ {
			sigma_key_el, _ := pairing.NewG1().SetString(sigma_key[j], 0)
			sigma_A = pairing.NewG1().Mul(sigma_A, sigma_key_el)
		}
	}

	tmp2 := pairing.NewGT().Pair(sigma_A, c1)

	tmp3 := pairing.NewGT().Mul(tmp1, tmp2)

	plain_msg_el := pairing.NewGT().Div(c0, tmp3)\
	plaintext = plain_msg_el.String()
	return

}

程序运行结果展示

GoPBC实践 (一):适用于链上计算的密文大小固定的属性基加密机制(On-Chain ABE)

参考文献

[1] M. Wang, Y. Guo, C. Zhang, C. Wang, H. Huang and X. Jia, "MedShare: A Privacy-Preserving Medical Data Sharing System by Using Blockchain," in IEEE Transactions on Services Computing, doi: 10.1109/TSC.2021.3114719. [2] 李发根,吴威峰著. 基于配对的密码学[M]. 北京:科学出版社, 2014