代理重加密(Proxy Re-encryption)简介

1,181 阅读4分钟

什么是代理重加密

交互的三方:Alice(消息发送者),Proxy(代理加密者),Bob(消息接收者)

  1. Alice和Bob分别生成一对非对称加密公私钥
  2. Bob将其公钥发送给Alice
  3. Alice用自身私钥加密明文,生成密文,发送给Proxy
  4. Alice基于Bob的公钥,生成一个代理密钥,发送给Proxy
  5. Proxy根据代理密钥和密文,生成一个代理密文,发送给Bob
  6. Bob用自身私钥解密代理密文,得到Alice发送的明文

在代理重加密的流程中,Proxy是半可信的。意即:它会完美执行我们制定的代理重加密流程,不会故意在其中进行替换或篡改,但它会尝试从自己获取的信息中推断明文。

为什么需要代理重加密

代理重加密反映的是明文机密性与其加解密算力的解耦。

先看看如果不使用代理重加密,Alice要发送消息给Bob,需要怎么做:

  1. Aliceg和Bob分别生成一对非对称加密公私钥
  2. Bob将其公钥发送给Alice
  3. Alice用公钥加密明文得到密文,发送给Bob
  4. Bob用自身私钥解密密文,得到Alice发送的明文

虽然流程变得简单了,但很容易注意到一件事情:每当Alice需要向一个新的接收方发送信息时,他都需要重新对明文进行一次加密。当明文很长时,这个加密可能是一项代价很高的操作。这就使得内容的分发对于Alice来说变得很困难。

而代理重加密正是解决这个问题。这里“代理”的是什么,正是令加密的运算由proxy进行代理,并且其代理的也仅是加密的运算本身,Proxy无法在这个过程中访问明文的内容,但负责了最重量级的密文的重加密运算和内容的传输分发。Bob只需发送自己的公钥以请求Alice的授权,而Alice只需要以生成代理密钥的方式,对Bob进行授权即可。在全过程中,明文只会由发送端Alice和经Alice授权的接收端Bob获知。

一个简单的代理重加密方案

在这里,我给出一个来自论文《Divertible Protocols and Atomic Proxy Cryptography》的代理重加密方案,它基于离散对数问题构建。

  1. 选取公共参数:素数qq和满足条件的素数p=2q+1p=2q+1ggZp\mathbb{Z}_p^\star上的生成元。这组参数是Alice、Bob与Proxy共享的。

  2. Alice生成密钥对。

    Alice的私钥为从Z2q\mathbb{Z}_{2q}^\star中随机选取的a:0<a<p1a:0<a<p-1,且aap1p-1互质。

    Alice发布公钥为gamodpg^a \mod p

  3. Alice加密信息mm时,随机在Z2q\mathbb{Z}_{2q}^\star选取一个kk,并计算(c1,c2)(c_1,c_2),发送给proxy。其中:

    c1=mgkmodpc_1=mg^k\mod p

    c2=(ga)kmodpc_2=(g^a)^k \mod p

    则不难验证,解密的方式为计算m=c1((c2a1)1)modpm=c_1((c_2^{a^{-1}})^{-1}) \mod p。此算法的效率与标准的ElGamal算法类似。

  4. Bob也用相同的算法与参数生成一个密钥对,其私钥为bb,将其发送给Alice

  5. Alice计算代理加密密钥π=a1b\pi=a^{-1}b,发送给proxy

  6. Proxy计算c2=(c2π)c_2^{\prime}=(c_2^\pi),并将(c1,c2)(c_1,c_2^{\prime})发送给Bob。

  7. Bob按前述的流程解密得到mm

如此,就完成了一个基于离散对数问题的代理重加密方案。当然很容易发现,这个方案要求Bob向Alice共享自己的私钥,并且如果Bob获得π\pi,他也可以很容易从中还原出aa。因此并不是一个最理想的方案。

改进的代理重加密方案

为了修正前面方案中的问题,论文《Improved Proxy Re-encryption Schemes with Applications to Secure Distributed Storage》中提出了另一个代理重加密的实现:

略过一些基于安全性考虑的改进细节,核心的修改在于:

  1. 引入双线性对e:G1×G1G2,gG1,Z=e(g,g)G2e:G_1 \times G_1 \rarr G_2, g\in G_1,Z=e(g,g)\in G_2

    此处的gg与前面含义相同,为生成元。

    双线性对的性质可以参考文章 双线性对知识梳理 (leanote.com)

  2. 代理加密密钥变成了π=gb/aG1\pi=g^{b/a} \in G_1

    注意Alice只需要Bob的公钥就能计算出此密钥

  3. Alice加密时,生成(gak,mZk)(g^{ak},mZ^{k})

  4. Proxy重加密时,计算e(gak,gb/a)=Zbke(g^{ak},g^{b/a})=Z^{bk}(由双线性对的性质可以得到此等式)

    (Zbk,mZk)(Z^{bk},mZ^k)就是Bob可解密的密文

  5. 不难发现这个密文的格式与Alice发送的略有不同,但解密是相似的。计算m=mZk(Zbk)b1m=\frac{mZ^k}{(Z^{bk})^{b^{-1}}}即可。

    另外补充一点,Alice如果想解密自己加密的密文,也可以通过计算m=mZke(gak,g)a1m=\frac{mZ^k}{e(g^{ak},g)^{a^{-1}}}实现。

此方案的设计通过引入双线性对,实现了两个优点:

  1. Bob的私钥隐藏在公钥中,但仍然可以通过双线性对的性质将Alice的私钥消去,仅留下Bob的私钥
  2. 双线性对的单向映射保证了单向的代理关系。

以上就是代理重加密的概念及其两个简单方案的设计。另外还可以发现,当引入同态加密原语时,如果解密方法本身支持纯密态运算,可以很容易构建一个基于同态加密的代理重加密方案(虽然这种设计几乎不具备实用性)。感兴趣的读者可以自己尝试构造。