J. Bethencourt, A. Sahai and B. Waters, “Ciphertext-Policy Attribute-Based Encryption,” 2007 IEEE Symposium on Security and Privacy (SP '07), 2007, pp. 321-334, doi: 10.1109/SP.2007.11.

python的charm-crypto库,abenc_bsw07源码阅读

CP-ABE方案首次由 J. Bethencourt,A. Sahai 和 B. Waters在 IEEE Symposium on Security and Privacy (SP '07)上发布,该方案也常被成为BSW(三人名字首字母)。该方案改善了Sahai等人在2005年发表的基于身份的模糊加密方案(FIBE),该方案将用户身份分解成一系列描述用户身份的属性,加密者加密数据时指定一个属性集合和阈值d,解密者必须拥有至少d个给定的属性才能正确解密密文。FIBE方案是BSW方案的雏形。因为BSW方案是对FIBE方案的改进,在算法设计中也使用了FIBE方案的思想和运算原理,在其基础上添加了访问控制树,以及递归求解访问控制树

1.方案定义

该方案由5个基本算法组成:Setup、Encrypt、KeyGen、Decrypt和 Delegate。

  1. Setup\mathrm{Setup}:该算法以隐含安全参数λ作为输入,输出系统公钥PK和主私钥MK。
  2. Encrypt(PK,M,A)CT\mathrm{Encrypt}(PK, M, A) → CT:该算法输入系统公钥PK、明文M和基于属性的访问结构A,输出对明文M加密后密文CT,且只有用户拥有的属性集合满足访问结构A才能正确解密密文CT。
  3. KeyGen(MK,PK,S)SK\mathrm{KeyGen}(MK, PK, S)→ SK :该算法以系统主私钥MK和属性集合S作为输入,输出用户私钥SK。
  4. Decrypt(PK,CT,SK)M\mathrm{Decrypt}(PK, CT, SK) → M:该算法输入系统公钥PK、密文CT和用户私钥SK作为输入,若S满足A,则能够正确解密密文并输出明文M。
  5. Delegate(SK,S~)SK~\mathrm{Delegate}(SK,\tilde{S})\to \tilde{SK} :该算法输入属性集合SS的私钥SKSK和一个属性集合S~\tilde{S}S~S\tilde{S}\subseteq S ,输出一个基于属性集合S~\tilde{S}的私钥SK~\tilde{SK}

2.算法详细设计

该方案用到以下基本条件:

  • G0G_0为一个阶为素数pp的双线性群,ggG0G_0的生成元。
  • e:G0×G0G1e:G_0\times G_0\to G_1表示双线性映射。
  • 群的大小由安全参数λ\lambda决定
  • 对于iZpi\in Z_{p}ZpZ_p中元素组成的集合SS,定义拉格朗日系数Δi,S(x)=jS,jixjij\Delta_{i,S}(x)=\prod_{j\in S,j\neq i}\frac{x-j}{i-j}
  • 应用一个哈希函数H:{0,1}G0H:\{0,1\}^*\to G_0,该函数能将任意字符串描述的属性映射为一个随机的群元素

2.1 Setup

该算法以隐含安全参数λ\lambda作为输入,输出系统公钥PK和主私钥MK。

该算法选择一个阶为pp的双线性群G0G_0,该群的生成元为gg。然后随机选择加密指数α,βZP\alpha,\beta \in Z_P。输出系统公钥PK=(G0,g,h=gβ,f=g1β,e(g,g)α)PK=(G_0,g,h=g^\beta,f=g^{\frac1\beta},e(g,g)^\alpha);系统主密钥MK=(β,gα)MK=(\beta,g^\alpha)

2.2 KeyGen

KeyGen(MK,PK,S)SK\mathrm{KeyGen}(MK, PK, S)→ SK :该算法以系统主私钥MKMK和属性集合SS作为输入,输出用户私钥SKSK

首先随机选择一个随机数rZpr\in Z_{p},然后对于每个属性jSj\in S,随机选择rjZpr_j\in Z_p。这个过程是属性集合SS中有几个属性,那就再ZpZ_p里面随机找几个数rjr_j,然后再按照如下过程计算用户私钥:

SK=(D=gα+rβ,jS:Dj=grH(j)rj,Dj=grj)SK=(D=g^{\frac{\alpha+r}\beta},\forall j\in S:D_j=g^r\cdot H(j)^{r_j},D_j^{^{\prime}}=g^{r_j})

利用PKPKMKMK里的相关参数和属性集SS来计算私钥。

jS:Dj=grH(j)rj,Dj=grj\forall j\in S:D_j=g^r\cdot H(j)^{r_j},D_j^{'}=g^{r_j},则表示属性集SS里含有几个属性,我们就从ZpZ_p里选出几个随机数来计算相应的DjD_jDjD_j^{^{\prime}}

2.3 Encrypt

Encrypt(PK,M,A)CT\mathrm{Encrypt}(PK, M, A) → CT:该算法输入系统公钥PKPK、明文MM和基于属性的访问结构AA,输出对明文MM加密后密文CTCT,且只有用户拥有的属性集合满足访问结构AA才能正确解密密文CTCT

首先对访问结构AA中的访问控制树TT中的每个节点xx(包括叶子节点)选择一个多项式qxq_x,这些多项式自上而下从根节点RR进行选择。对于树中的每一个节点xx,设多项式qxq_x的阶dxd_x为节点xx的阈值kxk_x减去1,即dx=kx1d_x=k_x-1

从根节点RR开始随机选择sZps\in Z_{p}并设置qR(0)=sq_R(0)=s。然后随机选择多项式qRq_R的其他dRd_R个点来定义该多项式。对于任何其他节点xx,令qx(0)=qparent(x)(index(x))q_x(0)=q_{parent(x)}(index(x))且随机选择多项式qxq_x的其他dxd_x个点来定义该多项式。

有点费解,那就举个例子吧!

image-20231120205325890

由图可知,属性值都在叶子节点上,而非叶子节点都是满足条件个数的门限。除了叶子节点,所有非叶子节点都是a/ba/b的形式,表示改节点有bb个子节点,要满足其中aa个子节点才可以。而非叶子节点才会有随机生成的多项式qxq_x,多项式qxq_x的阶就是该多项式的最高次幂,至于这个阈值kxk_x就是a/ba/b这个形式的aa

image-20231120205304092

接下来,对这一层的非叶子节点再按照根节点的多项式生成规则,为其随机生成多项式。

image-20231120205422683

YY为访问控制树TT的所有叶子节点的集合,那么通过控制结构构造的密文为

CT=(T,C~=Me(g,g)αs,C=hs,yY:Cy=gqy(0),Cy=H(att(y))qy(0))CT=(T,\tilde{C}=Me(g,g)^{\alpha s},C=h^s,\forall y\in Y:C_y=g^{q_y(0)},C_y^{\prime}=H(att(y))^{q_y(0)})

TT表示访问控制树。

C~=Me(g,g)αs\tilde{C}=Me(g,g)^{\alpha s}MM表示明文,ss就是根节点上要隐藏的秘密值(上面例子中的5),这个值是在ZpZ_p中随机选取的。

C=hsC=h^s,直观理解即可。

yY:Cy=gqy(0),Cy=H(att(y))qy(0)\forall y\in Y:C_y=g^{q_y(0)},C_y^{\prime}=H(att(y))^{q_y(0)},这是对叶子节点的操作,每个叶子节点经过这样计算,都会有一个值,比如上面例子中“网信院”对应值就是19。

2.4 Decrypt

Decrypt(PK,CT,SK)M\mathrm{Decrypt}(PK, CT, SK) → M:该算法输入系统公钥PK、密文CT和用户私钥SK作为输入,若S满足A,则能够正确解密密文并输出明文M。

解密过程是一个递归算法DecryptNode(CT,SK,x)\mathrm{DecryptNode}(CT,SK,x)。该算法输入为一个密文,CT=(T,C~,C,yY:Cy,Cy)CT=(T,\tilde{C},C,\forall y\in Y:C_y,C_y^{^{\prime}}),一个属性集SS的私钥SKSK和树TT中的一个节点xx

假如xx是一个叶子节点,令i=att(x)i=att(x),假如iSi\in S,定义:

DecryptNode(CT,SK,x)=e(Di,Cx)e(Di,Cx)=e(grH(i)ri,hqx(0))e(gri,H(i)qx(0))=e(g,g)rqx(0)\mathrm{DecryptNode}(CT,SK,x)=\frac{e(D_i,C_x)}{e(D_i^{'},C_x^{'})}=\frac{e(g^r\cdot H(i)^{r_i},h^{q_x(0)})}{e(g^{r_i},H(i)^{q_x(0)})}=e(g,g)^{r\cdot q_x(0)}

这个过程需要用到双线性映射的性质。

如果iSi\notin S的话,那么这个算法就输出⊥,表示控制结构中的属性不在个人私钥对应的属性集合中,则访问控制结构不满足私钥属性集合,则不能解密。

现在考虑非叶子节点时的递归情况,当xx是非叶子节点时,算法的计算情况如下:对于节点xx的所有孩子节点zz,调用函数DecryptNode(CT,SK,z)\mathrm{DecryptNode}(CT,SK,z)并存储其结果为FzF_z。令SxS_x为一个任意的大小为kxk_x的孩子节点zz的集合,并且满足$F_{z}\neq\bot $。如果不存在这样的集合,函数就返回⊥。否则,我们就计算:

Fx=zSxFzAi,Sx(0)=zSx(e(g,g)rqparent(z)(index(z)))Ai,Sx(0)=zSxe(g,g)rqx(i)Ai,Sx(0)=e(g,g)rqx(0)\begin{aligned}F_x&=\prod_{z\in S_x}F_z^{A_{i,S_x}(0)}=\prod_{z\in S_x}\left(e(g,g)^{r\cdot q_{parent(z)}(index(z))}\right)^{A_{i,S_x^{\prime}}(0)}\\&=\prod_{z\in S_x}e(g,g)^{r\cdot q_x(i)\cdot A_{i,S_x^{\prime}}(0)}=e(g,g)^{r\cdot q_x(0)}\end{aligned}

其中,i=index(z)i=index(z)Sx={index(z):zSx}S_x^{^{\prime}}=\{index(z):z\in S_x\}

结合上面的例子,我们现在有"计算机学院"(1,19)、“硕士”(2,44)和"研一"(3,83),所以,根据拉格朗日插值法,我们可以算出这三个节点的父节点的多项式是qx(x)=8+4x+7x2q_x(x)=8+4x+7x^2,这么我们就知道了这个父节点的隐藏秘密值是8。假设现在,我们也知道"教师"(2,11),结合刚解开的那个秘密值是(1,8),两者结合,再拉格朗日插值法一下,就得到了根节点的多项式是qR(x)=5+3xq_R(x)=5+3x。这样,我们就得到根节点的秘密值是5。这里,容易会有一个疑问——我在3/3那个节点解出了它的秘密值是8,进行拉格朗日插值计算的时候,我怎么知道它在根节点的index是1,别忘了,密文里面是有完整的访问控制树的结构的,我们可以根据这个结构很容易就能看出来它的index=1 。所以,在参与拉格朗日插值计算时候,就可以自动加入相应的index值计算。