身份基加密 (Identity based Encryption)算法
论文 Identity-Based Encryption from the Weil Pairing
Setup
- 生成pairing相关公共参数 < e , G 1 , G T , Z r > <e,G_1, G_T,Z_r> <e,G1,GT,Zr>
- 选取随机数 x ∈ Z r x\in Z_r x∈Zr 作为系统主密钥 m s k msk msk
- 选取随机元素 g ∈ G 1 g\in G_1 g∈G1作为生成元,计算公共参数 g x g^x gx。因此,有系统公钥 p k = < g , g x > pk=<g,g^x> pk=<g,gx>
- 选取公共哈希函数 H 1 : { 0 , 1 } ∗ → G 1 ∗ H_1:\{0,1\}^*\rightarrow G_1^* H1:{0,1}∗→G1∗, H 2 : G T → { 0 , 1 } n H_2:G_T \rightarrow \{0,1\}^n H2:GT→{0,1}n
KeyGen
- 给定用户身份 I D ∈ { 0 , 1 } ∗ ID\in \{0,1\}^* ID∈{0,1}∗,将其映射为群 G 1 G_1 G1上的元素。即计算 Q I D = H 1 ( I D ) Q_{ID}=H_1(ID) QID=H1(ID)
- 由系统主密钥 x x x计算此 I D ID ID对应的私钥为 s k = Q I D x sk=Q_{ID}^x sk=QIDx
Encrypt
- 针对目标用户身份 I D ∈ { 0 , 1 } ∗ ID\in \{0,1\}^* ID∈{0,1}∗,计算 Q I D = H 1 ( I D ) Q_{ID}=H_1(ID) QID=H1(ID)
- 选取随机数 r ∈ Z r r\in Z_r r∈Zr,计算密文组件 C 1 = g r C_1=g^r C1=gr
- 计算 g I D = e ( Q I D , g x ) r g_{ID}=e(Q_{ID},g^x)^r gID=e(QID,gx)r
- 计算密文组件 C 2 = M ⊕ H 2 ( g I D ) C_2=M \oplus H_2(g_{ID}) C2=M⊕H2(gID),其中 M ∈ { 0 , 1 } n M \in \{0,1\}^n M∈{0,1}n是明文数据
- 最终的密文为 < C 1 , C 2 > <C_1,C_2> <C1,C2>
Decrypt
- 解密的关键在于恢复 g I D g_{ID} gID
- e ( s k , C 1 ) = e ( Q I D x , g r ) = e ( Q I D , g ) x r = g I D e(sk,C_1)=e(Q_{ID}^x,g^r)=e(Q_{ID},g)^{xr}=g_{ID} e(sk,C1)=e(QIDx,gr)=e(QID,g)xr=gID
- 恢复明文 M = C 2 ⊕ H 2 ( e ( s k , C 1 ) ) M=C_2 \oplus H_2(e(sk,C_1)) M=C2⊕H2(e(sk,C1))
代码实现注意事项
1.选择用Properties保存是因为支持键值读取,比如密文可能包含多个组件,方便分别读取每个组件。
2.方法SetProperties的第二个参数必须为String类型,因此需要先将要保存的元素转换为String类型后存储。
//写入文件
Properties pkProp = new Properties();
//pkProp.setProperty("g", new String(g.toBytes())); //可以用这种方式将g转换为字符串后写入,但文件中会显示乱码
//为了避免乱码问题,统一采用Base64编码为可读字符串形式
pkProp.setProperty("g", Base64.getEncoder().encodeToString(g.toBytes()));
pkProp.setProperty("gx", Base64.getEncoder().encodeToString(gx.toBytes()));
storePropToFile(pkProp, pkFileName);
//从文件读取
Properties pkProp = loadPropFromFile(pkFileName);
String gString = pkProp.getProperty("g");
Element g = bp.getG1().newElementFromBytes(Base64.getDecoder().decode(gString)).getImmutable();
String gxString = pkProp.getProperty("gx");
Element gx = bp.getG1().newElementFromBytes(Base64.getDecoder().decode(gxString)).getImmutable();
3.bp.getG1().newElementFromBytes()
和bp.getG1().newElementFromHash()
用法。前者一般用于将一个恢复一个通过bytes到处的元素,比如上图的代码中用于恢复g
和gx
。后者用于从一个hash得到的字节数组中构造一个新元素,如下代码中用于将ID映射为群元素。
byte[] idHash = sha1(id);
Element QID = bp.getG1().newElementFromHash(idHash, 0, idHash.length).getImmutable();
4.算法实现过程中,遵从原文,密文组件的计算采用了异或方式,即 C 2 = M ⊕ H 2 ( g I D ) C_2=M \oplus H_2(g_{ID}) C2=M⊕H2(gID)。在后面的ABE方案中,一般都是直接计算 C 2 = M ⋅ g I D C_2=M \cdot g_{ID} C2=M⋅gID,这样仿真起来会更简单一些。