关于Go PBC Wrapper库的说明介绍在官方文档中已经详细给出,本系列专栏将不再详细介绍官方文档中已有内容,请读者及时翻阅官方文档查看相关函数。
版本说明
库 | PBC Library | Golang | gpbc |
---|---|---|---|
Version | 0.5.14 | 1.19.1 | v0.0.0-20181205041846-3e516ca0c5d6 |
适用于区块链的密文大小固定的属性基加密机制 (On-Chain Constant-size ABE)
双线性配对
令 为两个具有相同阶 的循环乘法群。 是 的生成元。将 表示为双线性配对:。
该双线性配对操作具有以下属性:
(1)双线性:,其中 ;
(2)非退化性:;
(3)可计算性:对所有的 计算 是很有效的。
ABE Setup
-
表示应用系统中的 个属性,其中每个属性都有多个值。
-
表示属性 的多个值。
-
Attribute Authority (AA) 选择两个随机大数 作为系统私钥 。 是一个哈希函数:。
-
将属性值 与属性 进行绑定,即设置 :
,
其中 是 中的第 个属性 , 是属性值集合 中的第 个值。\ -
将系统公钥设置为 。
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
- 令 表示用户拥有的属性列表。对于属性列表中的每个属性的值,AA随机选择一个值 来绑定属性与其对应的值。 是一个防碰撞哈希函数:。
- 对于属性列表 中的第 个属性和第 个值,其对应的属性密钥 。其中
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
- 由于需要将密文存储的区块链上,所以为了节约存储开销,将密文设置为固定大小。
- 首先将所有的属性和对应的值整合到一个访问策略 中。
- 计算 ,其中 .
- 在文献[1]中,作者使用AES密钥 来加解密文件,并保护文件ID 。
- Health Center (HC) 选择一个 , 并计算 。其中 ,,。
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
- 解密过程,类似解密过程,私钥的整合通过 , 其中 是用户的属性列表 。
- 。对应的就是如上所述的密文。
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
}
程序运行结果展示
参考文献
[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