欢迎关注公众号:区块链之美。
致力于区块链技术研究,传播区块链技术和解决方案、区块链应用落地、区块链行业动态等。

1.质数阶双线性群(Prime-Order Bilinear Groups)

质数双线性群可以由五元组(p,G1,G2,GT,e)(p,G1,G2,GT,e)(p,G1,G2,GT,e)来描述。五元组中ppp是一个与给定安全常数λλλ相关的大质数,G1,G2,GTG1,G2,GTG1,G2,GT均是阶为ppp的乘法循环群,eee为双线性映射e:G1×G2→GTe:G1×G2→GTe:G1×G2→GT,它满足以下3个条件:

  • 双线性(Bilinearity):对于任意的g∈G1,h∈G2,a,b∈Zpg∈G1,h∈G2,a,b∈Zpg∈G1,h∈G2,a,b∈Zp,有e(ga,hb)=e(g,h)abe(g^a,h^b)=e(g,h)^{ab}e(ga,hb)=e(g,h)ab;
  • 非退化性(Non-degeneracy):至少存在元素g1∈G1,g2∈G2g_1∈G1,g_2∈G2g1​∈G1,g2​∈G2,满足e(g1,g2)≠1e(g_1,g_2)≠1e(g1​,g2​)​=1;
  • 可计算性(Efficiency):对于任意的u∈G1,v∈G2u∈G1,v∈G2u∈G1,v∈G2,存在一个与给定安全常数λλλ相关的多项式时间算法,可以高效地计算e(u,v)e(u,v)e(u,v)。

现在的密码学相关论文中,习惯将G1,G2G1,G2G1,G2设置为乘法循环群。但是,基于椭圆曲线的双线性群构造中,G1,G2G1,G2G1,G2是加法群。所以在大约2005年以前的论文中,双线性群一般写成加法群形式。JPBC中将G1,G2G1,G2G1,G2表示称为了乘法循环群,因此在实现写成加法群形式的方案时,要注意将加法群改成乘法群的写法再进行实现。如何修改呢?很简单,把加法群中的加法运算写成乘法运算、把加法群中的乘法运算写成幂指数运算即可。

2.合数阶双线性群(Composite-Order Bilinear Groups)

合数阶双线性群和质数阶双线性群很类似,区别是G1,G2,GTG1,G2,GTG1,G2,GT的阶数是一个合数NNN,其中NNN是一些大质数的乘积,如N=p1p2⋯pnN=p_1p_2⋯p_nN=p1​p2​⋯pn​。同样,e为双线性映射e:G1×G2→GTe:G1×G2→GTe:G1×G2→GT,它满足双线性性、非退化性以及可计算性。

与质数阶双线性群不同,合数阶双线性群中,GNGNGN有阶数分别为p1,p2,⋯,pnp_1,p_2,⋯,p_np1​,p2​,⋯,pn​的子群Gp1,⋯,GpnGp_1,⋯,Gp_nGp1​,⋯,Gpn​。这些子群进一步满足正交特性。

对于所有的hi∈Gpih_i∈Gp_ihi​∈Gpi​和hj∈Gpjh_j∈Gp_jhj​∈Gpj​,如果i≠ji≠ji​=j,那么e(hi,hj)=1e(h_i,h_j)=1e(hi​,hj​)=1

简单地说就是,子群之间进行双线性运算的结果必为1。

2.1.一些说明

首先,由于双线性群现在的构造是基于椭圆曲线的,而椭圆曲线上的元素是由坐标(x,y)(x,y)(x,y)表示的,所以如果我们将G1,G2G1,G2G1,G2的结果输出到Java的控制台,我们得到的是一个坐标。不过,GTGTGT是一个普通的ZnZ_nZn​群,所以其元素的表示是一个数。

其次,在密码学中,如果G1=G2G1=G2G1=G2,我们称这个双线性群是对称双线性群(Symmetric Bilinear Group),否则称之为非对称双线性群(Asymmetric Bilinear Group)。

是否为对称双线性群由选取的椭圆曲线种类决定。一般认为,非对称双线性群要比对称双线性群更安全。特别地,现在已经证明一些特定的对称双线性群是不安全的了。

现在JPBC可以使用的曲线为如下几类:

  • Type A
  • Type A1
  • Type D
  • Type E
  • Type F
  • Type G

现在密码学实现基本只使用Type A和Type A1的。前者为对称质数阶双线性群,后者为合数阶对称双线性群。本博客也只在这两类曲线上实验。其他类曲线的实现类似。由于是对称双线性群,本博客中G1,G2G1,G2G1,G2统一写为GGG。

3.双线性群初始化

在JPBC中,双线性群的使用都是通过叫做Pairing的对象来实现的。双线性群的初始化在JPBC中就是对Pairing对象的初始化。双线性群有两种初始化的方法。第一种是通过代码动态产生一个双线性群,第二种是从文件中读取参数而产生群。

3.1.通过代码动态产生

动态产生的方法非常简单,大概有如下步骤:指定椭圆曲线的种类、产生椭圆曲线参数、初始化Pairing。Type A曲线需要两个参数:rBit是Zp中阶数p的比特长度;qBit是G中阶数的比特长度。代码为:

//rBit是Zp中阶数p的比特长度,如160;qBit是G中阶数的比特长度,如512。
TypeACurveGenerator pg = new TypeACurveGenerator(rBit, qBit);
PairingParameters typeAParams = pg.generate();
Pairing pairing = PairingFactory.getPairing(typeAParams);

Type A1曲线需要二个参数:numPrime是阶数N中有几个质数因子;qBit是每个质数因子的比特长度。注意,Type A1涉及到的阶数很大,其参数产生的时间也比较长。代码为:

TypeA1CurveGenerator pg = new TypeA1CurveGenerator(numPrime, qBit);
PairingParameters typeA1Params = pg.generate();
Pairing pairing = PairingFactory.getPairing(typeA1Params);

3.2.通过文件读取产生

我们也可以选择事先产生好参数,存放在文件中。以后再初始化的时候,直接从文件中读取参数,就可以非常快速的初始化双线性群。

PairingParameters支持toString()函数。实际上,我们可以直接将PairingParametersd的toString()存放在文件中。读取的时候,通过读取文件就可以直接初始化双线性群了。

Type A曲线从文件中读取参数初始化的代码为:

TypeACurveGenerator pg = new TypeACurveGenerator(rBit, qBit);
PairingParameters typeAParams = pg.generate();
//将参数写入文件a.properties中,我用了Princeton大学封装的文件输出库
Out out = new Out("a.properties");
out.println(typeAParams);
//从文件a.properties中读取参数初始化双线性群
Pairing pairing = PairingFactory.getPairing("a.properties");

Type A1曲线从文件中读取参数初始化的代码为:

TypeA1CurveGenerator pg = new TypeA1CurveGenerator(numPrimes, qBit);
PairingParameters typeA1Params = pg.generate();
//将参数写入文件a1.properties中,同样使用了Princeton大学封装的文件输出库
Out out = new Out("a1.properties");
out.println(typeA1Params);
//从文件a1.properties中读取参数初始化双线性群
Pairing pairing = PairingFactory.getPairing("a1.properties");

4.产生双线性群中的随机数

Type A中产生随机数的方法很简单,代码为:

//随机产生一个Z_p群的元素
Element Z_p = pairing.getZr().newRandomElement().getImmutable();
//随机产生一个G_1群的元素
Element G_1 = pairing.getG1().newRandomElement().getImmutable();
//随机产生一个G_2群的元素
Element G_2 = pairing.getG2().newRandomElement().getImmutable();
//随机产生一个G_T群的元素
Element G_T = pairing.getGT().newRandomElement().getImmutable();

Type A1中产生随机数的方法稍微有点麻烦。对于ZN和GT方法和Type A一样。代码为:

//随机产生一个Z_N群的元素
Element Z_N = pairing.getZr().newRandomElement().getImmutable();
//随机产生一个G_T群的元素
Element G_T = pairing.getGT().newRandomElement().getImmutable();

但是对于G就不同了。因为G有子群Gpi,Type A1产生随机数时需要指定生成元,椭圆曲线的参数,产生哪个子群的元素,以及Type A1一共有多少个子群。

假定我们产生的Type A1共有n个子群,这n个子群的阶分别为p1,⋯,pn,产生随机数的代码如下:

TypeA1CurveGenerator pg = new TypeA1CurveGenerator(numPrimes, qBit);
PairingParameters typeA1Params = pg.generate();
Pairing pairing = PairingFactory.getPairing(typeA1Params);//设定并存储一个生成元。由于椭圆曲线是加法群,所以G群中任意一个元素都可以作为生成元
Element generator = pairing.getG1().newRandomElement().getImmutable();
//随机产生一个G_p_1中的元素
Element G_p_1 = ElementUtils.getGenerator(pairing, generator, typeA1Params, 0, numPrimes).getImmutable();
//随机产生一个G_p_2中的元素
Element G_p_2 = ElementUtils.getGenerator(pairing, generator, typeA1Params, 1, numPrimes).getImmutable();
// ......
//随机产生一个G_p_n中的元素
Element G_p_n = ElementUtils.getGenerator(pairing, generator, typeA1Params, 1, numPrimes).getImmutable();

5.将指定的元素哈希到双线性群中

由于双线性群最初是用在基于身份的加密(Identity-Based Encryption)系统中,我们经常会需要将一个特定的String或者byte[]哈希到双线性群中。

JPBC支持将byte[]哈希到双线性群的Z,G,GT中。但是,JPBC说明文档中没有提到的是,byte[]数组长度不能太长,如果过长会抛出异常。因此,我建议首先将byte[]用一个SHA256或者其他通用哈希函数哈希到固定长度,再用JPBC提供的函数哈希到双线性群上。在这里我略去SHA256步骤,直接给出哈希到Z,G,GT群的代码:

//将byte[] byteArray_Z_p哈希到Z_p群
Element hash_Z_p = pairing.getZr().newElement().setFromHash(byteArray_Z_p, 0, byteArray_Z_p.length);
//将byte[] byteArray_G_1哈希到G_1群
Element hash_G_1 = pairing.getG1().newElement().setFromHash(byteArray_G_1, 0, byteArray_G_1.length);
//将byte[] byteArray_G_2哈希到G_2群
Element hash_G_2 = pairing.getG2().newElement().setFromHash(byteArray_G_2, 0, byteArray_G_2.length);
//将byte[] byteArray_G_T哈希到G_T群
Element hash_G_T = pairing.getGT().newElement().setFromHash(byteArray_G_T, 0, byteArray_G_T.length);

注意,对于Type A1来说,这个代码无法指定哈希到指定子群Gpi中。解决方法是将byte[]先哈希到Z群,然后利用G,GT的生成元计算幂指数,从而达到哈希到G,GT上的效果。

6.双线性群的运算

双线性群之间有如下运算:

  • G相关运算:GZ, G×G;
  • GT相关运算:GZT, GT×GT;
  • Z相关运算:Z+Z, Z×Z;
  • Pairing运算

做运算的时候要注意一下几点:

  1. Java的运算结果都是产生一个新的Element来存储,所以我们需要把运算结果赋值给一个新的Element;
  2. Java在进行相关运算时,参与运算的Element值可能会改变。所以,如果需要在运算过程中保留参与运算的Element值,在存储的时候一定要调用getImmutable(),具体方法见代码中的初始化相关参数部分。
  3. 其实为了保险起见,防止Element在运算的过程中修改了Element原本的数值,可以使用Element.duplicate()方法。这个方法将返回一个与Element数值完全一样的Element,但是是个新的Element对象。举例来说,如果做G1×G1的运算,可以写成:
Element G_1_m_G_1 = G_1.duplicate().mul(G_1_p.duplicate());

G和G其实也是可以进行幂指数运算的,即GG,调用的函数为Element e1.pow(Element e2)。特别注意,我们再写G群的Z次方运算时,用的函数为powZn(),而不是pow(),这个调用错误很容易使得程序的运算结果不正确。
代码如下:

//初始化相关参数
Element G_1 = pairing.getG1().newRandomElement().getImmutable();
Element G_2 = pairing.getG2().newRandomElement().getImmutable();
Element Z = pairing.getZr().newRandomElement().getImmutable();
Element G_T = pairing.getGT().newRandomElement().getImmutable();Element G_1_p = pairing.getG1().newRandomElement().getImmutable();
Element G_2_p = pairing.getG2().newRandomElement().getImmutable();
Element Z_p = pairing.getZr().newRandomElement().getImmutable();
Element G_T_p = pairing.getGT().newRandomElement().getImmutable();//G_1的相关运算
//G_1 multiply G_1
Element G_1_m_G_1 = G_1.mul(G_1_p);
//G_1 power Z
Element G_1_e_Z = G_1.powZn(Z);//G_2的相关运算
//G_2 multiply G_2
Element G_2_m_G_2 = G_2.mul(G_2_p);
//G_2 power Z
Element G_2_e_Z = G_2.powZn(Z);//G_T的相关运算
//G_T multiply G_T
Element G_T_m_G_T = G_T.mul(G_T_p);
//G_T power Z
Element G_T_e_Z = G_T.powZn(Z);//Z的相关运算
//Z add Z
Element Z_a_Z = Z.add(Z_p);
//Z multiply Z
Element Z_m_Z = Z.mul(Z_p);//Pairing运算
Element G_p_G = pairing.pairing(G_1, G_2);

参考

[1] https://blog.csdn.net/liuweiran900217/article/details/45080653

双线性群简介与基本运算相关推荐

  1. 合数双线性群(Composite Order Bilinear Groups)

    基于属性加密大部分都是利用素数双线性群作为数学基础,最近看到一篇论文基于合数双线性群,由于看不懂,找到比较原始的定义,定义如下: 定义一个群生成器,一个算法将安全参数作为输入,输出一个双线性群的描述, ...

  2. java密码学原型算法_java密码学原型算法实现——双线性对.pdf

    java密码学原型算法实现--双线性对 Java 密码学原型算法实现--双线性对 1.背景介绍 如何使用jPBC 库进行双线性群初始化,包括: (1)质数阶双线性群(Prime-Order Bilin ...

  3. 网吧组网新趋势:双光纤接入+千兆到桌面(转)

    如今,国内的网吧已趋于饱和,特别是一些大中型城市中的网吧,数量众多.在如此庞大的网吧群体中,要保持自己能够盈利,设计和组建一个稳定.高速.便于管理控制的低投资高收益的网吧网络就显得极其重要.虽然很多网 ...

  4. HTML怎么打双引号,双引号怎么打出来

    双引号怎么打出来 要打双引号,就要先有中文输入法,然后切换好中文符号(中问的句号是空心的,英文句号是实心的),然后按SHIFT+'键就可以了,'在字母L的右边第二个键.打第一个是开双引" , ...

  5. html的中文引号怎么打,双引号怎么打出来

    双引号怎么打出来 要打双引号,就要先有中文输入法,然后切换好中文符号(中问的句号是空心的,英文句号是实心的),然后按SHIFT+'键就可以了,'在字母L的右边第二个键.打第一个是开双引" , ...

  6. 提升性能 网吧双光纤接入路由器方案

    随着近几年网吧向着正规化.规模化发展,对网络带宽的需求也越来越大.传统的双绞线接入由于提供的数据传输率较慢,造成网吧内的网络性能低下,严重制约了网吧规模的扩展,采用新的接入方式已势不可挡. 光纤比传统 ...

  7. PHP中的单引号和双引号的区别

    PHP中单引号和双引号简介 PHP中字符串和变量插值时单引号和双引号的区别 PHP中转义撇号时单引号和双引号的区别 本文将介绍PHP中单引号和双引号的区别. PHP中单引号和双引号简介 在 PHP 中 ...

  8. html中引号怎么打,双引号怎么打出来

    双引号怎么打出来 要打双引号,就要先有中文输入法,然后切换好中文符号(中问的句号是空心的,英文句号是实心的),然后按SHIFT+'键就可以了,'在字母L的右边第二个键.打第一个是开双引" , ...

  9. 【博士论文】物联网数据安全可信的共享技术研究

    来源:专知 本文约2000字,建议阅读5分钟 本文为你分享物联网数据安全可信的共享技术研究. 来自上海交通大学牛超越的博士论文,入选2021年度"CCF优秀博士学位论文奖"初评名单 ...

最新文章

  1. 、|| 和 、| 的区别(详尽版)
  2. 在高并发分布式情况下生成唯一标识id
  3. 轻松搞定项目中的空指针异常Caused by: java.lang.NullPointerException: null
  4. QT的QSqlDatabase类的使用
  5. 3D角色设定全析百图斩
  6. layui让文字和div平行_layui富文本的使用注意事项以及拓展
  7. 【C++】CCFCSP201803-1跳一跳
  8. 删除网络信息服务器端,网络安全:手动清除gh0st远控服务端
  9. oracle数据库速度测试,ORACLE数据库测试数据插入速度
  10. 多系统精密星历下载与分析
  11. 在国内使用DNS服务器的一个对比分析
  12. ArcGIS土地利用转移矩阵(附土地利用数据下载)
  13. windows开机自启exe程序bat
  14. 系统集成项目管理师和高级项目管理师考试心得
  15. nginx做域名映射到指定端口(阿里云服务器、阿里域名服务)
  16. 阿里云的专业技术认证分为哪些?为啥要获得阿里云的ACP认证!
  17. 第一次软工作业(数独)
  18. Docker中成功安装修罗Xiunobbs论坛步骤
  19. 内存小实用的手机浏览器,这2款无广告,功能不输UC
  20. 一度智信电商:店铺转化率太低?

热门文章

  1. Android Glide加载gif
  2. vep加密视频破解转换为mp4教程
  3. 一款IM即时通讯聊天系统源码,包含app和后台源码
  4. PID控制器(比例-积分-微分控制器)
  5. QT:颜色拾取器的实现
  6. 强烈推荐,分享一些让人拍案叫绝的黑科技软件(网站)
  7. 电脑安全莫依赖影子系统(或冰封系统)
  8. 精品:企业级智能 PDF 和文档处理 SDK:GdPicture.NET
  9. vue 实现Excel 导出
  10. MySQL常见高可用方案