公钥可搜索加密
公钥可搜索加密(Public-Key Encryption with Keyword Search,简称PEKS)定义如下:
- :初始化算法,输入安全参数,获取私钥和公钥。
- :关键词加密算法,输入公钥和文档关键词,输出文档关键词对应的密文。
- :陷门生成算法,输入私钥和搜索关键词,输出搜索关键词对应的陷门。
- :测试算法,输入陷门和密文,输出布尔变量,当陷门和密文对应同一关键词时,否则。
PEKSBoneh2004方案构造如下:
令为双线性对,两个函数和为哈希函数。
- :输入安全参数,该安全参数决定群和的阶,随机挑选 和的生成元,输出和。
- :输入公钥和关键词,随机挑选,计算,输出。
- :输入私钥和关键词,输出。
- :输入陷门和密文,记密文为,若,输出,否则输出。
验证正确性:
,进一步有。
直觉上(非理论层面,非严谨数学思维)对方案构造安全性进行分析:将当成随机谕言机,利用的单向性,敌手很难根据逆推出,同样很难根据逆推出。
为什么不直接使用和的形式?注意,在该形式中,即使敌手没有私钥,它同样也可以生成有效陷门;但在PEKSBoneh2004方案中,若没有私钥,那么它无法生成正确的陷门。
为什么不直接使用和的形式,然后在加密方和搜索方共享一条密钥?注意,该形式存在密钥管理问题,若有个加密方,那么搜索方需要将共享给这个加密方,加密方有可能是普通用户,不具备安全高防性,其易遭受黑客攻击,从而泄露。对比之下,在PEKSBoneh2004方案中,加密方仅需持有公钥,私钥泄露的风险大大减小。
并且上述两个做法对应的是固定的,若两个加密方同时加密同一,那么它们产生的两个密文是完全一样的,这显得有点不“安全”,监听者无需攻击服务器(一般假设云服务器具有安全高防性,需重点防范的是监听),仅需监听数据就可以自己对密文相关性进行一个分析。一种粗糙的应对策略是利用服务器的二次加密,但这样做服务器需要维护一条公钥,这增加了云服务商的花费开销,显得有点“不理想”。云服务商可能仅想提供计算服务,由搜索方自己去维护自己的公钥。(至于防陷门监听,可以利用对称加密AES,注意,公钥可搜索加密在上传密文阶段是对,而在搜索阶段是对。)
密码工具库
PEKSBoneh2004方案用到双线性对,这里推荐一个实用的python密码工具库charm-crypto,该工具库由约翰斯·霍普金斯大学科研人员开发,© Copyright 2013, Johns Hopkins University ISI. Last updated on Feb 20, 2018. 写论文若使用该工具进行科研实验,请在Reference中标明
@article{charm13,
year={2013},
issn={2190-8508},
journal={Journal of Cryptographic Engineering},
volume={3},
number={2},
doi={10.1007/s13389-013-0057-3},
title={Charm: a framework for rapidly prototyping cryptosystems},
url={http://dx.doi.org/10.1007/s13389-013-0057-3},
publisher={Springer-Verlag},
keywords={Applied cryptography; Protocols; Software; Privacy},
author={Akinyele, Joseph A. and Garman, Christina and Miers, Ian
and Pagano, Matthew W. and Rushanan, Michael
and Green, Matthew and Rubin, Aviel D.},
pages={111-128},
}
PEKSBoneh2004方案代码实现
#coding=utf-8
from charm.toolbox.pairinggroup import PairingGroup, ZR, G1, G2, GT, pair
import hashlib
Hash1pre = hashlib.md5
def Hash1(w):
# 先对关键词w进行md5哈希
hv = Hash1pre(str(w).encode('utf8')).hexdigest()
print(hv)
# 再对md5值进行group.hash哈希,生成对应密文
# 完整的Hash1由md5和group.hash组成
hv = group.hash(hv, type=G1)
return hv
Hash2 = hashlib.sha256
def Setup(param_id='SS512'):
# 代码符号G1 x G2 → GT
group = PairingGroup(param_id)
# 方案选用的是对称双线性对,故G2 = G1
g = group.random(G1)
alpha = group.random(ZR)
# 生成私钥与公钥并进行序列化
# Serialize a pairing object into bytes
sk = group.serialize(alpha)
pk = [group.serialize(g), group.serialize(g ** alpha)]
return [sk, pk]
def Enc(pk, w, param_id='SS512'):
group = PairingGroup(param_id)
# 进行反序列化
g, h = group.deserialize(pk[0]), group.deserialize(pk[1])
r = group.random(ZR)
t = pair(Hash1(w), h ** r)
c1 = g ** r
c2 = t
# 对密文进行序列化
print(group.serialize(c2))
return [group.serialize(c1), Hash2(group.serialize(c2)).hexdigest()]
def TdGen(sk, w, param_id='SS512'):
group = PairingGroup(param_id)
sk = group.deserialize(sk)
td = Hash1(w) ** sk
# 对陷门进行序列化
return group.serialize(td)
def Test(td, c, param_id='SS512'):
group = PairingGroup(param_id)
c1 = group.deserialize(c[0])
c2 = c[1]
print(c2)
td = group.deserialize(td)
return Hash2(group.serialize(pair(td, c1))).hexdigest() == c2
if __name__ == '__main__':
# 'SS512'是对称双线性对
param_id = 'SS512'
[sk, pk] = Setup(param_id)
group = PairingGroup(param_id)
c = Enc(pk, "yes")
td = TdGen(sk, "yes")
assert(Test(td, c))
td = TdGen(sk, "no")
assert(not Test(td, c))
c = Enc(pk, "Su*re")
assert(not Test(td, c))
c = Enc(pk, "no")
assert(Test(td, c))
c = Enc(pk, 9 ** 100)
td = TdGen(sk, 9 ** 100)
assert(Test(td, c))
td = TdGen(sk, 9 ** 100 + 1)
assert(not Test(td, c))
Reference
[1] Dan Boneh, Giovanni Di Crescenzo, Rafail Ostrovsky, et al. Public Key Encryption with Keyword Search[C]// Advances in Cryptology - EUROCRYPT 2004, International Conference on the Theory and Applications of Cryptographic Techniques, Interlaken, Switzerland, May 2-6, 2004, Proceedings. 2004.
[2] 双线性对映射 概念理解
来源:CSDN
作者:华南农大-郭庆文
链接:https://blog.csdn.net/u014134327/article/details/103788783