公钥可搜索加密及其python实现

孤街浪徒 提交于 2020-01-11 08:03:21

公钥可搜索加密

公钥可搜索加密(Public-Key Encryption with Keyword Search,简称PEKS)定义如下:

  • Setup(1λ)(sk,pk)\mathsf{Setup}(1^\lambda) \to (\it{sk}, \it{pk}):初始化算法,输入安全参数1λ1^\lambda,获取私钥sk\it{sk}和公钥pk\it{pk}
  • Enc(pk,w)c\mathsf{Enc}(\it{pk}, w) \to c:关键词加密算法,输入公钥和文档关键词ww,输出文档关键词对应的密文cc
  • TdGen(sk,w)td\mathsf{TdGen}(\it{sk}, w) \to \it{td}:陷门生成算法,输入私钥和搜索关键词ww,输出搜索关键词对应的陷门td\it{td}
  • Test(td,c)b\mathsf{Test}(\it{td}, c) \to b:测试算法,输入陷门和密文,输出布尔变量bb,当陷门和密文对应同一关键词时b=1b=1,否则b=0b=0

PEKSBoneh2004方案构造如下:
e:G1×G1G2e : \mathbb{G}_1 \times \mathbb{G}_1 \to \mathbb{G}_2为双线性对,两个函数H1:{0,1}G1\mathsf{H}_1 : \{0, 1\}^* \to \mathbb{G}_1H2:G2{0,1}logp\mathsf{H}_2 : \mathbb{G}_2 \to \{0, 1\}^{\log p}为哈希函数。

  • Setup\mathsf{Setup}:输入安全参数,该安全参数决定群G1\mathbb{G}_1G2\mathbb{G}_2的阶pp,随机挑选αZp\alpha \gets \mathbb{Z}^*_pG1\mathbb{G}_1的生成元gg,输出pk:=[g,h=gα]{\it pk} := [g, h=g^\alpha]sk:=α{\it sk} := \alpha
  • Enc\mathsf{Enc}:输入公钥和关键词,随机挑选rZpr \gets \mathbb{Z}^*_p,计算t:=e(H1(w),hr)t := e(\mathsf{H}_1(w), h^r),输出c:=[gr,H2(t)]c := [g^r, \mathsf{H}_2(t)]
  • TdGen\mathsf{TdGen}:输入私钥和关键词,输出td:=H1(w)α{\it td} := \mathsf{H}_1(w)^\alpha
  • Test\mathsf{Test}:输入陷门和密文,记密文为c=[c1,c2]c = [c_1, c_2],若H2(e(td,c1))=c2\mathsf{H}_2(e(\it{td}, c_1)) = c_2,输出b:=1b := 1,否则输出b:=0b := 0

验证正确性:
e(td,c1)=e(H1(w)α,gr)=e(H1(w),gαr)=e(H1(w),hr)e( {\it td}, c_1) = e(\mathsf{H}_1(w)^\alpha, g^r) = e(\mathsf{H}_1(w), g^{\alpha r}) = e(\mathsf{H}_1(w), h^r),进一步有H2(e(td,c1))=c2\mathsf{H}_2(e(\it{td}, c_1)) = c_2

直觉上(非理论层面,非严谨数学思维)对方案构造安全性进行分析:将H1\mathsf{H}_1当成随机谕言机,利用H1\mathsf{H}_1的单向性,敌手A\mathscr{A}很难根据td{\it td}逆推出ww,同样很难根据cc逆推出ww

为什么不直接使用c:=H(w)c := \mathsf{H}(w)td:=H(w){\it td} := \mathsf{H}(w)的形式?注意,在该形式中,即使敌手A\mathscr{A}没有私钥α\alpha,它同样也可以生成有效陷门td{\it td};但在PEKSBoneh2004方案中,若A\mathscr{A}没有私钥α\alpha,那么它无法生成正确的陷门td{\it td}

为什么不直接使用c:=H(k,w)c := \mathsf{H}(k, w)td:=H(k,w){\it td} := \mathsf{H}(k, w)的形式,然后在加密方和搜索方共享一条密钥kk?注意,该形式存在密钥管理问题,若有nn个加密方,那么搜索方需要将kk共享给这nn个加密方,加密方有可能是普通用户,不具备安全高防性,其易遭受黑客攻击,从而泄露kk。对比之下,在PEKSBoneh2004方案中,加密方仅需持有公钥,私钥泄露的风险大大减小。

并且上述两个做法ww对应的cc是固定的,若两个加密方同时加密同一ww,那么它们产生的两个密文是完全一样的,这显得有点不“安全”,监听者无需攻击服务器(一般假设云服务器具有安全高防性,需重点防范的是监听),仅需监听数据就可以自己对密文相关性进行一个分析。一种粗糙的应对策略是利用服务器的pk{\it pk}'二次加密cc,但这样做服务器需要维护一条公钥pk{\it pk}',这增加了云服务商的花费开销,显得有点“不理想”。云服务商可能仅想提供计算服务,由搜索方自己去维护自己的公钥pk{\it pk}。(至于防陷门监听,可以利用对称加密AES,注意,公钥可搜索加密在上传密文阶段是nn11,而在搜索阶段是1111。)

密码工具库

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},
}

项目地址:http://charm-crypto.io/

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] 双线性对映射 概念理解

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!