Pypbc 的简易用法
PBC(Pairing-Based Cryptography Library) 是实现双线性对运算的函数库 . 这个开源代码 C
函数库是由Stanford 大学开发 ,
库的地址为 http://crypto.stanford.edu/pbc/.
具体的安装步骤看我之前写的博客:
https://blog.csdn.net/weixin_39032619/article/details/109261403
这次讲一讲在学习使用这个库中的心得:
(一)包的初始化
在pypbc库中,有个对象:Element,Pairing,Parameters。
其中Parameters对象负责对对象进行初始化,规定使用哪种曲线,在pbc当中实现了好几种,有a.param,b.param……。在help里面可以看到:
There are three basic ways to instantiate a Parameters object:
| Parameters(param_string=s) -> a set of parameters built according to s.
| Parameters(n=x, short=True/False) -> a type A1 or F curve.
| Parameters(qbits=q, rbits=r, short=True/False) -> type A or E curve.
有三种不同的初始化方式
(1 )第一种是根据输入曲线参数来初始化出现。
例如:
stored_params = """type a
q 8780710799663312522437781984754049815806883199414208211028653399266475630880222957078625179422662221423155858769582317459277713367317481324925129998224791
h 12016012264891146079388821366740534204802954401251311822919615131047207289359704531102844802183906537786776
r 730750818665451621361119245571504901405976559617
exp2 159
exp1 107
sign1 1
sign0 1
"""
params = Parameters(param_string=stored_params) # type a
pairing = Pairing(params) #实例化双线性对对象
(2)第2种是根据设置群的阶数来生成曲线
q_1 = get_random_prime(60) # 生成一个长度为60的随机素数
q_2 = get_random_prime(60)
#使用的是pbc中的a1_param参数
params = Parameters( n = q_1 * q_2 )
#实例化双线性对对象,可以理解为e(a,b)
pairing = Pairing( params )
我们首先生成2个长度为60的随机素数,将他们的乘积作为阶数n进行曲线的初始化。
(3)第三种根据安全参数进行实例化
qbits=512, rbits=160
params = Parameters(qbits=qbits, rbits=rbits) #参数初始化
pairing = Pairing(params) # 根据参数实例化双线性对
(二)元素的操作
我们上面提到三个对象Element、pairing,Parameters,Element是负责元双线性对的运算,包括群之间的加减乘除。
简单介绍一下功能:
#初始化一个G1,G2,GT,Zr元素,如果value赋值则进行是运算
Element(pairing, G1||G2||GT||Zr, value=v) -> Element
#初始化一个G1||G2||GT||Zr中的元素并置为1
Element.one(pairing, G1||G2||GT||Zr) -> identity element for the given group.
#初始化一个G1||G2||GT||Zr中的元素并置为0
Element.zero(pairing, G1||G2||GT||Zr) -> identity element for the given group.
#从群中取一个随机数,并初始化一个元素,一般是取g的,也就是生成元。
Element.random(pairing, G1||G2||GT||Zr) -> random element of the given group.
#根据给定的值生成哈希函数
Element.from_hash(pairing, G1||G2||GT||Zr -> element whose value is determined by the given hash value.
各个函数的使用简单的举个例子
#从G2中取一个随机数,并初始化一个元素,一般是取g的,也就是生成元。
g = Element.random( pairing, G2 )
#初始化一个GT元素
a = Element( pairing, GT )
#初始化一个G2元素
b = Element( pairing, G2 )
#初始化一个Zr元素
c = Element( pairing, Zr )
#初始化一个GT中的元素并置为1
Element.one( pairing, GT )
#初始化一个Zr中的元素并置为0
Element.zero( pairing, Zr )
'''对群进行运算一般使用Element,而不是直接在数值上进行运算。(当然直接运算也可以)。其中pairing代表我们初始化的双线性对,G2代表返回值的类型,value=就是值等于多少,G2中的元素做底数,Zr中的元素做指数,其实也能使用b = g ** c是同样的效果,但下面这样写更加工整,看着更明白,减少出错。
'''
b = Element( pairing, G2, value = g ** c ) # b = g^c
# a = e(g,g),注意:type(a) = GT。
a = pairing.apply(g,g)
(三)方案的实现
代码请结合2004年Boneh的论文方案来阅读,其中**[params, g]是公共参数**,近来我在看学术论文时经常看到公共参数生成算法,该算法返回公共参数pp,pp作为方案其余各算法的隐含输入,这样写法是为了结合工程习惯。Pbc library公共参数生成算法中的qbits和rbits用法具体请阅读**官方文档**,
—— KeyGen:输入安全参数生成群G1,G2的阶p,并挑选一个属于Zp^*的随机数α,G1的生成元g,输出
A p u b = [ g , h = g α ] and A p r i v = α A_{p u b}=\left[g, h=g^{\alpha}\right] \text { and } A_{p r i v}=\alpha Apub=[g,h=gα] and Apriv=α
—— PEKS(A_pub,W):W是明文message,首先计算t=e(H1(W),hr)∈G2,r是Zp*的一个随机数。输出密文
S = PEKS ( A p u b , W ) = [ g r , H 2 ( t ) ] S=\operatorname{PEKS}\left(A_{p u b}, W\right)=\left[g^{r}, H_{2}(t)\right] S=PEKS(Apub,W)=[gr,H2(t)]
—— Trapdoor(A_priv,W):输出
output T W = H 1 ( W ) α ∈ G 1 \text { output } T_{W}=H_{1}(W)^{\alpha} \in G_{1} output TW=H1(W)α∈G1
—— Test(A_pub,S ,T_w):让S=[A,B],A=g^r,B=H2(t),判断 H2(e(T_w,A)) = B 是否成立,如果成立返回yes,否则返回no。
注意:PEKS论文中PEKS定义为
G
1
×
G
1
→
G
2
G_1 \times G_1 \rightarrow G_2
G1×G1→G2
使用的是对称双线性对。而我们熟知的定义是
G
1
×
G
2
→
G
T
G_1 \times G_2 \rightarrow G_T
G1×G2→GT
二者的表述不同,转换一下表示为(论文中的G1)=(定义中的G1,G2),(论文中的G2)=(定义中的GT),而在pypbc中是使用我们熟知的定义来表示的,与论文中有所不同。
from pypbc import *
import hashlib
Hash1 = hashlib.sha256
Hash2 = hashlib.sha256
# 公钥可搜索加密-2004-Boneh
# 密钥生成算法,输入安全参数qbits和rbits,返回[params, g, pk, sk]
def KeyGen(qbits=512, rbits=160):
params = Parameters(qbits=qbits, rbits=rbits) #参数初始化
pairing = Pairing(params) # 根据参数实例化双线性对
# 返回公共参数,PEKS是对称双线性对,G1=G2,二者的生成元是一样的,G2同样可以替换为G1
g = Element.random(pairing, G2) # g是G2的一个生成元
sk = Element.random(pairing, Zr) # 私钥是一个素数域Zp内的随机数
pk = Element(pairing, G2, value=g ** sk) # 公钥是[g, h = g^α] α=sk
return [params, g, sk, pk]
# PEKS算法,输入公共参数[params, g],公钥pk,关键字word,返回[A, B] (具体参考论文)
def PEKS(params, g, pk, word):
#PEKS 算法输入公钥pk(论文中是h),G1的生成元g,关键字W
pairing = Pairing(params)
#首先生成t = e(H1(W),h^r),H1(W)是对关键字进行哈希函数处理,这里使用的是hash256算法
hash_value = Element.from_hash(pairing, G1, Hash1(str(word).encode('utf-8')).hexdigest())
r = Element.random(pairing, Zr) #定义一个Zp内的随机数r
h_r = Element(pairing,G1,value = pk ** r)
# t = pairing.apply(hash_value, h_r)
# g_r = Element(pairing,G1,value = g ** r)
t = pairing.apply(hash_value, pk ** r) #生成双线性对e(H1(W),h^r)
return [g**r, Hash2(str(t).encode('utf-8')).hexdigest()]
# 陷门生成算法,输入公共参数[params],私钥sk,待查关键字word,返回陷门td
def Trapdoor(params, sk, word):
pairing = Pairing(params)
hash_value = Element.from_hash(pairing, G1, Hash1(str(word).encode('utf-8')).hexdigest())
return hash_value ** sk
# 测试算法,输入公共参数[params],公钥pk,S=[A, B],陷门td,返回布尔值True/False
def Test(params, pk, cipher, td):
pairing = Pairing(params)
[A, B] = cipher
td = Element(pairing, G1, value=str(td))
temp = pairing.apply(td, A)
temp = Hash2(str(temp).encode('utf-8')).hexdigest()
return temp == B
if __name__ == '__main__':
[params, g, sk, pk] = KeyGen(512, 160)
message= 'father'
cipher = PEKS(params, g, pk, message)
keyword = 'father'
td = Trapdoor(params, sk, keyword)
B=Test(params, pk, cipher, td)
print(B)
if B:
print("在密文中检索到关键字%s"%keyword)
else:
assert (Test(params, pk, cipher, td), '密文中无法检索到该关键字')
更多推荐
所有评论(0)