用于Cheon抗性的静态DIFFIE-HELLMAN安全性的方法和系统
技术领域
本公开涉及密码学领域中的静态组。
背景技术
Diffie-Hellman密钥交换是一种在公共信道上安全地交换密码密钥的方法。在各种系统中,协议使用整数模p的乘法组,其中p是素数。公共值g是模p的原始根,并且被提升为在密码事务的每一侧都是秘密的指数。由于乘法组的特征,两个原始根的交换(每个原始根被提升为各方之一的秘密)可以被组合在一起以形成双方之间的共享秘密。由于离散对数问题,窃听者无法轻易地导出共享秘密。
Diffie-Hellman密钥交换的变体或特殊情况利用椭圆曲线密码(ECC)。在ECC中,该组不是有限域的乘法组,而是椭圆曲线的子组。椭圆曲线的使用允许比乘法组更小的组大小以实现相同的安全级别。
在某些形式的Diffie-Hellman密钥交换中,一方可以多次重用秘密值。这种做法可称为静态Diffie-Hellman。Jung Hee Cheon在题为“Security analysis of the strongDiffie-Hellman problem.”Advances in Cryptology-EuroCrypt 2006,LNCS 4004,pg.1,Springer,2006的论文中(其通过引用并入本文)发现在组大小q中,如果q-1或q+1具有一定大小的因子,则静态Diffie-Hellman问题实际上比对Diffie-Hellman问题的最佳已知攻击容易得多。特别地,Cheon算法涉及对手挑选各种点Q并且通过使第一参与者将静态私钥x应用于Q来看到共享秘密xQ。这种Cheon攻击使得Diffie-Hellman协议不太安全。
附图说明
参考附图将更好地理解本公开,在附图中:
图1是示出了参与者利用密码模块来交换信息的框图;
图2是示出了在椭圆密码Diffie-Hellman系统中的共享秘密的建立的数据流程图;
图3是示出了选择Cheon抗性曲线的过程的过程图;
图4是示出了使用特定准则在椭圆密码Diffie-Hellman系统中的共享秘密的建立的数据流程图;以及
图5是能够执行本公开的实施例的简化计算设备的框图。
具体实施方式
本公开提供了一种用于提供静态椭圆曲线Diffie-Hellman密码系统(ECDH)的Cheon-抗性安全性的方法,该方法包括:提供用于在一对通信者之间进行消息通信的系统,消息是根据在相应通信者的计算机处理器上可执行的ECDH指令被交换的,该ECDH指令使用从多条曲线中选择的曲线,该选择包括:挑选一个范围的曲线;从该一个范围的曲线中选择与阈值效率匹配的曲线;在所选择的该曲线内排除可以包括有意的漏洞的曲线;以及从未排除的所选择的该曲线中推选具有Cheon抗性的曲线,该推选包括从q阶的加法组中选择曲线,其中q是素数,使得q-1=cr、并且q+1=ds,其中r和s是素数,并且c和d是该组的整数Cheon辅因子,使得cd≤48。
本公开进一步提供了一种用于为静态椭圆曲线Diffie-Hellman密码系统(ECDH)提供Cheon-抗性安全性的方法,该方法包括:提供用于在一对通信者之间进行消息通信的系统,消息是根据在相应通信者的计算机处理器上可执行的ECDH指令被交换的,该ECDH指令使用包括以下各项的曲线:q阶的加法组,其中q是素数,使得q-1=cr、并且q+1=ds,其中r和s是素数,并且c和d是该组的整数Cheon辅因子,使得cd≤48;形式为y2=x3+ix的仿射方程,其中长度为454位;域大小p=2454+(3x17x11287)2;阶q=2452+(7x41117)2;r=(q–1)/8;以及s=(q+1)/6。
本公开进一步提供了一种用于提供静态椭圆曲线Diffie-Hellman密码系统(ECDH)的Cheon-抗性安全性的计算设备,该计算设备包括用于执行程序指令的处理器,该处理器被配置为:提供用于在一对通信者之间进行消息通信的系统,消息是根据在相应通信者的计算机处理器上可执行的ECDH指令被交换的,该ECDH指令使用从多条曲线中选择的曲线,该选择包括:挑选一个范围的曲线;从该一个范围的曲线中选择与阈值效率匹配的曲线;在所选择的该曲线内排除可以包括有意的漏洞的曲线;以及从未排除的所选择的该曲线中推选具有Cheon抗性的曲线,该推选包括从q阶的加法组中选择曲线,其中q是素数,使得q-1=cr、并且q+1=ds,其中r和s是素数,并且c和d是该组的整数Cheon辅因子,使得cd≤48。
本公开进一步提供了一种用于提供静态椭圆曲线Diffie-Hellman密码系统(ECDH)的Cheon-抗性安全性的计算设备,该计算设备包括用于执行程序指令的处理器,该处理器被配置为:提供用于在一对通信者之间进行消息通信的系统,消息是根据在相应通信者的计算机处理器上可执行的ECDH指令被交换的,该ECDH指令使用包括以下各项的曲线:q阶的加法组,其中q是素数,使得q-1=cr、并且q+1=ds,其中r和s是素数,并且c和d是该组的整数Cheon辅因子,使得cd≤48;形式为y2=x3+ix的仿射方程,其中长度为454位;域大小p=2454+(3x17x11287)2;阶q=2452+(7x41117)2;r=(q–1)/8;以及s=(q+1)/6。
现在参考图1,其示出了用于一对通信者之间的消息通信的系统10。具体地,在图1中,一对通信者A和B通过数据通信链路12连接。通信者A和B中的每一个具有密码模块或单元14,其根据建立的协议来执行公共密钥密码操作以允许通过链路12的安全通信。密码单元14在密码域内操作,密码域的参数由其他实体共享。
在一个示例中,通信者A和B利用Diffie-Hellman(DH)密钥交换。具体地,Diffie-Hellman密钥交换使用可交换组,这是一种具有一个二进制运算并且遵守某些公理的代数系统。
最初由Diffie和Hellman提出的组被称为大小为p的有限域的乘法组,其中p是素数。使用这样的乘法组,数字集合{1,2,...,p-1}可以具有被定义为乘法模p的二进制运算,这意味着在除以p之后计算余数之后的乘法。该组在数学方面是众所周知的,并且被Diffie和Hellman应用于密码学。
为了说明的目的,考虑小的素数p=5。二进制运算,对于该组的乘法模p可以在下表中表示:
表1:二进制运算,乘法模5
在该组中,我们具有例如2×4=3。具体地,正常乘法2×4=8,但是在该组中,余数以模5计算,其给出3,因为8=1×5+3。
对于组的任何元素g和一些正整数x,我们可以通过在g的x个副本之间应用二进制运算来定义gx。此运算称为组取幂,并且g被称为底数,并且x被称为指数。在该组是有限域的乘法组的情况下,组取幂也被称为模幂运算。
因此,为了说明,令p=5,如上表1中所示。如果g=2并且x=6,则在模幂运算中,gx=26=4。这是因为,在常规取幂下,26=64并且64模5的余数为4。
即使在接近2256的大型组中,也可以使用诸如平方和乘法算法之类的算法来非常有效地进行组取幂。该算法最多需要log2(x)组运算来计算gx。在组大小2256中,组取幂采用512或更少的组操作,这通常是实用的。
离散对数是组取幂的倒数。y=gx与底数g的离散对数是x。计算离散对数在某些组中是一个“难”题。这个问题的难度对于Diffie-Hellman密钥交换和相关公钥密码算法的安全性至关重要,其被称为离散对数问题(DLP)。难是密码学中的术语,并且如本文所使用的通常意味着只要系统的安全性被认为是重要的,就必须超出对手能力之外,必须防止破坏系统。在数学上,该术语可能意味着问题的解在渐近多项式时间中是不可解的。
因此,公钥密码依赖于是难的DLP。
再次参考图1,在Diffie-Hellman密钥交换中,贡献者A生成秘密指数x,并且贡献者B生成秘密指数y。A将A=gx发送给B,并且B将B=gy发送给A。贡献者A计算z=Bx并且贡献者B计算w=Ay。由于z=gxy=w,所以计算值相等,因此两个贡献者都计算了相同的共享值w=z。
针对其中离散对数问题是难的组,通常认为对手E难以从g、A和B计算z和w。该问题现在称为Diffie-Hellman问题(DHP)。可以通过求解DLP来求解DHP:给定A=gx,通过求解DLP找到x,然后通过组取幂计算Bx,从而求解DHP,因为w=z=Bx。因此,DHP并不比DLP更难。DHP可能比DLP更容易,但在某些情况下,可以通过求解DHP来求解DLP,尽管转换可能更昂贵。
以上是Diffie-Hellman密钥交换的基本一般形式。
在描述Diffie-Hellman密钥交换之后,ElGamal引入了使用相同的Diffie-Hellman组用于数字签名的方法,其允许贡献者A和B确信彼此的消息。ElGamal还澄清了Diffie-Hellman密钥交换可用于构建公钥加密方案。在一个示例中,贡献者B可以使用固定的Diffie-Hellman私钥,而贡献者A可以使用短暂的私钥,其对于它希望发送给贡献者B的每个消息仅具有一个密钥。
椭圆曲线密码
椭圆曲线密码(ECC)可以被视为用于公钥密码的Diffie-Hellman系统的特殊情况。
在ECC中,该组不是有限域的乘法组,而是椭圆曲线的子组。如上所述,使用ECC的一个原因是,对于相同大小的组,DLP在ECC中比在经典DH组中的DLP更难。这允许较小的组被用于相同的安全级别。尽管椭圆曲线(EC)组的使用比相同大小的有限域(FF)组的使用慢,但由于EC组针对相同的安全级别而言可以小得多,因此针对相同安全的FF组,它们可以具有相似的速度。
通常,曲线是任何一维点集合。代数曲线由多项式方程定义。平面曲线是嵌入平面中的曲线。平面代数曲线的一个简单示例是在(x,y)平面中具有等式x2+y2=1的圆。
根据称为代数几何的数学理论,每条曲线都具有称为其属的数字。属0曲线包括直线、圆、椭圆、抛物线和双曲线。通常,属0曲线是任何曲线,其点可以可逆地转换为数字,仅使用变换的两个方向上的有理函数。例如,通过将点(x,y)映射到数字w=y/(x+1),圆具有属0。该映射可以通过(x,y)=((1–w2)/(1+w2),2w/(1+w2))反转。
因此,属0曲线可以仅具有实(x,y)平面中的分量。虽然双曲线似乎有两个分量,但这些分量在平面的延伸部分与投影线连接,其认为渐近线的作用类似于无穷远处的点。
属0曲线后的最简单的曲线类别是属1曲线。这些传统上也称为椭圆曲线,因为它们起源于测量椭圆的弧长。
椭圆曲线的简单形式是平面三次曲线。平面三次曲线是由平面中的三次方程定义的曲线。一小类三次曲线具有属0,并且这些例外称为奇异三次曲线。否则,大多数三次平面曲线具有属1。
椭圆曲线的三次方程的传统形式是Weierstrass三次方,其包括诸如y2=x3+ax+b之类的方程,其中a和b是固定数,而(x,y)是点在平面中的坐标。
其他类型的三次方程也是令人关注的研究,并且可以在ECC中有用。
代数几何理论在椭圆曲线的点集合上定义了一组。更一般地,每条曲线都有一个相关联的组,称其为Jacobian组。对于属0曲线,该组的大小为1,因此对于密码它不是很令人关注或有用。对于属2或更高的曲线,该组非常复杂,但这些组已经考虑用于密码学。
平面三次曲线的Jacobian组定义如下。点O被固定为组标识。按照惯例,这个椭圆曲线是使用二进制运算的加法写的。因此,不是针对应用于组元素x和y的组运算编写xy,我们而是针对组元素X和Y编写X+Y.
为了添加点X和Y,形成通过X和Y的直线L。如果X和Y是相同的点,则挑选通过X的与曲线相切的直线。由于曲线是三次方,因此该线在0、1或3点处相交,其中相切计为两点,并且拐点计为3点。
由于直线L已经在两个点上与曲线相交,因此它必须在3个点中与曲线相交。这些点中的两个是X和Y,第三个是点Z。
可以在另一个点O和Z上进行相同的过程以获得另一个点,其用作X+Y的定义。
由于椭圆曲线传统上使用加法而不是乘法来写他们的组运算,因此可以调整以前的术语和DH组的符号。写作gx的前一个组取幂运算现在称为标量乘法,并且被写作xG。此外,离散对数有时被称为“椭圆曲线离散对数问题”(ECDLP),以避免与其他组中的离散对数问题混淆。
密码学中使用的椭圆曲线Diffie-Hellman(ECDH)组表示具有有限域的点的坐标。因此,有限域Diffie-Hellman组(FFDH组)和ECDH组均使用有限域。在FFDH组中,组元素是非零有限域元素。在ECDH组中,组元素通常是一对有限域元素,其一起满足三次方程。ECDH组中使用的有限域通常称为曲线和ECDH组的基础域。在一些实施例中,还使用术语定义域。
如上所述,ECDH组的一个优点是离散对数问题针对组大小似乎比FFDH组更难。因此,如果我们挑选ECDH组和FFDH组,其中离散日志大致相同困难,并且针对任何实际算法来说太难以解决,则通常ECDH组针对用户来说将更快。
FFDLP比ECDLP更容易的一个主要原因是FFDH组具有更好的大小元素概念。FFDLP中的这些大小概念通过将大元素分解为较小元素的组合来允许离散日志,较小元素的离散对数更容易找到。这种解决FFDLP的一般策略有时称为指数计算或筛分。针对典型的椭圆曲线组,还没有发现有效的指数计算算法。
在大多数ECDH组中,用于计算离散日志的最熟知的算法是通用组算法。通用组算法适用于任何组,只需将组运算用作黑盒子。用于计算离散日志的通用组算法的速度是有限的。具体地,如果该组具有可被素数n整除的大小,则以显着的成功率计算具有通用组算法的离散日志需要至少大约n1/2组。
椭圆曲线的一些罕见情况具有更容易解决的离散日志。这些可以使用Menezes、Okamoto、Vanstone(MOV)攻击和Satoh、Araki、Semaev、Smart(SASS)攻击来解决。可以轻松检测到这些罕见的情况,并且ECC的标准明确避免了这些特殊情况的攻击。
此外,除了难的离散对数问题之外,安全ECC需要避免边信道攻击。当ECDH和其他算法的实现泄漏附加信息(诸如有关通信者A和B的信息)时会产生边信道。
在静态Diffie-Hellman中,如下所述,期望抵抗边信道的安全性。这是根据以下定义的。假设通信者A具有安全密钥m和静态DH模块,其针对给定静态Diffie-Hellman安全组中的任何输入P计算mP。进一步假设模块没有泄漏绝对没有关于m的其他信息(因此模块没有边信道或计算没有m的签名)。在这种情况下,通信者A可以在任何协议集合中使用该模块而不暴露m。此外,即使协议不安全,它们也可能相互妥协,但它们不会暴露m。
需要注意在没有边信道的情况下实现这种ECDH。在一些实施例中,发现某些算法在没有边信道的情况下更容易实现,并且一个这样的算法是Montgomery ladder。
Montgomery ladder的有效形式使用以下形式的等式:by2=x3+ax2+x。
上述等式是三次方的并且通常定义椭圆曲线。上面的Montgomery ladder方程在Weierstrass方程中并不常见,并且历史上不被椭圆曲线的数学处理所优选,因为它略微不如Weierstrass方程普遍。
在椭圆曲线密码中,方程在有限域上定义,而不是在实线上的常用数字上定义。通常,有限域是素数域,并且具有以素数p为模的整数。这有助于确保组中的点容易在有限量的信息中表示,并且还有助于确保离散对数问题是难的。
ECC用户的大部分效率取决于p的选择,因为算法涉及以模p计算余数。通过挑选接近二的幂或其他特殊形式的p,与随机素数p相比,软件中ECC的速度几乎翻倍。
例如,提供ECDH的使用以获得公共连接上的共享秘密。现在参考图2。
在图2中,通信者A和通信者B希望通过公共通道12安全地通信。通信者A和B同意使用椭圆曲线Diffie-Hellman来获得用于通信的共享秘密。
特别地,通信者A可以挑选曲线和参数并且将它们传送给通信者B,以便确保在各方之间使用相同的曲线。
此外,通信者A和B中的每一个具有秘密整数值,其可以被认为是每个通信者的私钥。因此,通信者A具有秘密整数m,而通信者B具有秘密整数n。
共享的参数可以包括p,其是指示域Fp的顺序的素数。参数a和b是来自Weierstrass方程y2=x3+ax+b的值。参数进一步包括具有阶数q的组生成器G。
再次参考图2,在会话开始时,通信者A在消息212中向通信者B发送参数p、a、b、G、q。消息212进一步包括值mG,其可被考虑为针对通信者A的公钥。
通信者B接收消息212并且提取参数。然后,通信者B在消息220中将可以被认为是通信者B的公钥的值nG提供回通信者A.
通信者B进一步利用该曲线使用其私钥以及通信者A的公钥来计算共享秘密nmG。
类似地,通信者A利用该曲线使用其私钥以及通信者B的公钥来计算共享秘密mnG。
由于nmG=mnG,因此通信者A和B现在具有共享秘密。
窃听者230可以看到通信者A和B之间的所有通信。因此,窃听者230将知道曲线参数以及公钥mG和nG。然而,由于离散对数问题,窃听者将无法计算共享秘密nmG。
本公开涉及曲线和曲线参数的确定。
点计数
挑选用于密码的椭圆曲线组的主要挑战之一是确定其大小。虽然椭圆曲线Diffie-Hellman(ECDH)可以在不知道组的大小的情况下进行操作,但由于Pohlig-Hellman和Pollard rho算法,其安全性取决于组的大小的最大素因子。特别地,使用具有未知大小n的组的ECDH携带n的最大素因子太小的风险。
椭圆曲线组的诸如数字签名之类的其他密码应用可能需要直接了解组的大小以便正常工作。
Schoof-Elkies-Atkin(SEA)是确定椭圆曲线组大小的一般方法。使用SEA方法计算安全密码所需大小的有限域上的随机椭圆曲线上的点的数目,针对256位曲线通常需要在一秒钟内,针对512位域的较大曲线需要在一分钟内。
基于此,除非需要尝试非常大量的椭圆曲线以满足严格的准则,否则点计数是实用的。然而,在本文描述的实施例中,寻求需要满足非常严格的准则的曲线。这些相当严格的准则可能意味着需要尝试数百万条曲线并且一百万分钟大约需要2年。
在有限域上的某些椭圆曲线在它们的基本行列式D具有小值的意义上是特殊的。基本行列式是将曲线的大小n与下层域的大小p相关联的数。这种曲线通常被描述为具有复数乘法(CM),并且被称为CM曲线。CM曲线很少见,并且通常随机曲线具有非常大的行列式D。
知道p和D允许人们快速确定n。此外,如果D小,则可以找到具有基本行列式D的曲线。这是复数乘法的一部分。
CM方法的一种形式是固定p,并且尝试各种小D直到找到具有合适属性的曲线。使用CM方法搜索比使用SEA方法搜索快得多。
CM方法的另一变体将D固定为非常小的值,在这种情况下,找到曲线是微不足道的。然后该方法搜索p的不同可能值。这种方法更快,因为它避免了先前CM方法的最慢步骤,即从各种小D中找到曲线。该方法的主要缺点是需要考虑各种p值。
本文描述的实施例利用上述方法,具有固定的D和变化的p。由于该方法很快,因此它可用于找到符合非常严格准则的曲线。
静态Diffie-Hellman问题
在某种形式的Diffie-Hellman密钥交换中,通信者A将多次重用秘密值。这种做法可以称为静态Diffie-Hellman。
静态Diffie-Hellman的示例包括ElGamal加密及其变体椭圆曲线集成加密方案(ECIES)、最近提出的用于传输层安全性(TLS)1/3的最佳层安全(OPTLS)密钥协商算法、以及Ford-Kaliski密码加强方案。
因此,静态Diffie-Hellman问题是一般Diffie-Hellman问题的变体,其中对手试图利用秘密值的不断重用。
静态Diffie-Hellman组保护一些密码协议免受某些类型的故障的风险。具体地,q阶的加法组是静态Diffie-Hellman组,如果针对均匀随机秘密整数a∈{0,1,2,...,q-1},没有可行的效率算法可以使用oracle A用于计算A(P)=aP(针对组中的任何输入P)来查找秘密a的函数。定量地:如果没有算法最多花费c组操作,最多对oracle A进行o次查询,则组是(c,o,s)静态Diffie-Hellman安全,在找到秘密a时至少具有成功率s。
通过三个概念提供Diffie-Hellman组安全性。首先,离散对数组是一个组,其中离散对数问题(从aP计算a)是不可行的,并且离散对数安全性量化了问题的难度。
第二,Diffie-Hellman安全性量化了Diffie-Hellman问题的难度(从aP和bP计算abP),Diffie-Hellman组是具有棘手的Diffie-Hellman问题的那些组。
第三,Diffie-Hellman组和安全性被类似地定义。
Cheon攻击
如上所述,Cheon攻击表明,如果组大小q使得q-1或q+1具有一定大小的因子,则静态Diffie-Hellman问题实际上比对Diffie-Hellman问题的最熟知攻击容易得多。
Cheon算法涉及对手挑选各种点Q并且通过让通信者A将她的静态私钥x应用于Q来看到通信者A共享秘密xQ。
一些Diffie-Hellman协议被认为阻碍了Cheon在任意组中的攻击。通信者A可以例如将密钥导出函数应用于xQ以获得密钥k,然后通信者A丢弃xQ。如果密钥导出函数是单向的,则在实践中这可能会阻碍Cheon算法。尽管如此,依靠Cheon算法首先不可行而不依赖于密钥导出函数和xQ的安全删除可能更安全。
换句话说,挑选其中Cheon的攻击是不可行的组提供针对Cheon攻击的第二层防御,其中第一层防御将是密钥导出函数本身。
在其他情况下,诸如Ford-Kaliski密码加强xQ可以是公开的。然而对于这些组来说,抵抗Cheon攻击的需要要强得多。
因此,根据本公开的实施例,Cheon抵抗曲线是具有组大小q的曲线,使得q-1和q+1两者均避免使Cheon算法比Pollard rho更快的因子分解条件。
根据上文,Cheon抗性定义如下。如果q为素数,则q阶的加性组接近最优Cheon-抵抗,并且针对素数r和s以及整数c和d,q-1=cr并且q+1=ds,使得cd≤48。(c,d)对是该组的Cheon辅因子。
在上文中,Cheon辅因子(c,d)上的条件是任意的并且为了简单起见而挑选。在替代实施例中,可以提供更复杂的定义。例如,对于每个素数q,考虑Cheon算法的最佳参数。设c是针对大小为q的通用组的Cheon算法的最优版本的成本c。设q=logq(c)。现在考虑可能适合于实现静态Diffie-Hellman的候选素数q集合。例如,该集合可能是某个位长度的所有素数。设γ+为q的所有候选值的γq的最大值。在εq的小上限的某些定义下,几乎最优的Cheon-抗性组大小q的替代定义是γq=(1-∈q)γ+。这个替代定义虽然不完整,但对于任何实际应用来说已经几乎过于复杂,因此上面的定义更简单。
破坏密码算法
挑选曲线的另一个考虑因素是避免被有意地破坏为易受秘密攻击的密码算法。一种已知的破坏密码算法的对策是挑选整体描述非常紧凑的算法。紧凑的算法倾向于通过试错(trial and error)来防止破坏者修改算法参数的可能性。在这种情况下,试错搜索可能会迫使弱参数相对较大,因此不如更诚实的参数更紧凑。如本文所用,“诚实”意味着未特别挑选为弱的参数或算法。这种对策通常被称为“无计可施”。最近,它被称为“刚性”,含义略有不同。
因此,根据本公开的另一实施例,挑选紧凑算法。虽然挑选紧凑算法并不能防止所有破坏,但在某些情况下,最弱的算法版本具有最小的参数值,并且因此是更紧凑和更诚实的算法版本。破坏这种形式的主要对策是正确识别算法的弱版本。换句话说,利用传统的密码分析。第二个对策,它证明任何假设攻击的等效性超过算法参数的任何值。
基于上文,鉴于Cheon-抵抗曲线是期望的,并且一些协议需要依赖于静态Diffie-Hellman问题的安全性,本公开提供了更可能具有最优静态Diffie-Hellman安全性的椭圆曲线,受到曲线的其他特性的约束。
相反,人们不希望牺牲Diffie-Hellman的重要特性,无论是安全性还是效率。因此,挑战在于提高静态Diffie-Hellman组的Cheon抗性的证据,而不会影响其他特征。
根据本公开的一个实施例,可以建立非常具体的准则集合,以便解决大多数其他椭圆曲线提议的主要缺陷,即弱静态Diffie-Hellman问题的风险。
特别地,针对椭圆曲线的安全性和效率两者均存在各种准则。这些包括对通常的椭圆曲线攻击的抗性,诸如:大位长度的抵抗Pollard rho攻击;小型辅因子抵抗Pohlig-Hellman攻击;高嵌入度抵抗MOV攻击;曲线的阶不等于域的阶以抵抗SASS攻击;以及可被4整除的辅因子,以获得更好的边信道抗性和效率。
然而,这些基本准则没有解决弱静态Diffie-Hellman问题的风险。因此,根据本公开将另外的准则添加到上述基本准则,并且为了实现强静态Diffie-Hellman安全性,Cheon的攻击针对位长度几乎最优地被抵抗。
由于Cheon-抗性是高级安全属性,因此本公开提供了对安全性而非效率的强调。因此,根据本公开,不考虑选择最高效或最小的足够安全性曲线,而是考虑一个范围的更安全或更大的足够效率的曲线。在这些曲线中,利用以下准则寻求效率:足够小的位长度是实用的;针对位长度相对有效,包括接近二的幂的域大小和有效的内同态(endomorphism)。
此外,根据本公开的实施例,应用一些努力或上述准则的副产品来解决有意易受攻击的加密算法的问题。这些因素包括曲线紧凑的因素。特别地,所有曲线的参数都是紧凑的,可以表示为压缩形式。此外,通过确保曲线未被恶意操纵,曲线是紧凑的。
这些漏洞通过易于生成和再生来被解决。因此,根据下面描述的实施例,仅需要几秒来检查较旧的PC模型上的每个候选曲线而不是服务器簇上的几个月。
根据以上所述,在一个实施例中,提供了近似最优Cheon-抗性的椭圆曲线具有复数乘以i表明优越的Boneh-Boyen静态Diffie-Hellman安全性并且允许具有454位长度的Bernstein ladder,在本文中被称为Crib454。然而,该曲线仅是一个示例,并且本文描述的原理可以应用于找到与所描述的准则匹配的其他曲线。
Crib454的准则基于如下所述的安全性和效率。
CRIB454曲线利用以下准则描述:
p=2454+(3x17x11287)2
q=2452+(7x41117)2
r=(q-1)/8
s=(q+1)/6
上述准则是可能的素数。
此外,具有仿射方程的椭圆曲线定义为:y2=x3+ix。
上述曲线在大小为p的域Fp上具有n=4q个点,包括无穷远处的点。通常,i≡(-1)1/2mod p。在这方面,i≡2227/(3×17×11287)mod p。
以上准则提供了可以根据本公开使用的曲线的一个示例。也可以使用基于下面提供的因素的其他曲线。
为了易于生成、效率和紧凑,特定准则需要复数乘法(CM)。此外,挑选i的复数乘法,因为这种乘法提供了非常有效的内同态并且与辅因子4准则匹配。替代的线性内同态曲线具有统一的三次方根的复数乘法,但是它们具有辅因子3,这可能是不太理想的。
虽然本领域已经提出具有复杂乘法的曲线是有风险的,但是在30年内没有实现对CM曲线的攻击,这提供了CM曲线与非CM曲线一样好的有力证据。事实上,CM曲线可能提供比非CM曲线更好的安全性的两个原因包括,首先,有效的内同态允许更大的曲线的使用,这增加了已知攻击在给定效率水平下的难度,并且可能对CM的轻度攻击提供有一定幅度的误差。在这种情况下,温和的定义只是略微优于Pollard rho攻击。
其次,CM曲线属于一类特殊的曲线,其可能避免大多数非CM曲线的一些问题。例如,考虑对Pohlig-Hellman攻击的抵抗力,这针对特殊类型的近似素数(低辅因子)DH组来说是最强的。存在其他示例以示出特殊曲线可能比非CM曲线更安全。
在给定的素数有限域上,只有少数椭圆曲线,直到内同态,具有i的复数乘法。其中一些具有可被8整除的辅因子,因此应该避免。这通常会修正曲线方程,直到内同态。
针对Cheon-抗性安全性,本公开的实施例尝试相对于曲线大小选择接近最优的Cheon抗性,因为这可以被视为具有强静态Diffie-Hellman安全性的最强证据。为了实现这种接近最优的Cheon-抗性,Cheon辅因子然后被定义为几乎是最小的。在Crib454的符号中,挑选的Cheon辅因子是8和6,因为r=(q-1)/8并且s=(q-1)/6。在上面,组的阶是素数q,而r和s是与q相关的素数。
由于两个原因,特定挑选Cheon辅因子对(8,6)而不是(1,1)或(6,8)或(2,24)。首先,由于涉及的数字的可分性属性,一些像(1,1)的对是不可能的。实际上,对中数字的乘积应该可以被12整除,因为与任何大于或等于5的素数相邻的两个数的乘积可以被12整除。
具体地,如果q是这样的素数,则q-1或q+1必须可被3整除。q-1和q+1都是偶数,并且一个必须可被4整除。
其次,选择具有特殊形式的素数p,其是基础域的大小。具体来说,特殊形式是quasi-Fermat素数,因为这种形式允许其大小相当好的效率。这种特殊形式意味着第一个Cheon辅因子可以被8整除,而Cheon辅因子的乘积可以被48整除。
p的一般准则是它简单、紧凑和有效。特定的准则是p是二的幂加上或减去一个小数。在一些实施例中,数字越小越好。p是二的幂加上或减去一个小数,p非常简单、紧凑和有效。p是quasi-Fermat素数的特定准则,它是二的幂加上一个小数(不是负数),似乎是由CM方法的缩写形式强加的。
CM方法的缩写形式是另一准则。在CM方法的这种形式中,经由Cornacchia算法从p确定q的通常步骤被更简单的公式代替,其中p和q都是从一些给定的整数计算的。缩写方法比通常的CM方法更快,因为它避免了Cornacchia的算法,这有助于方法的再现性。
缩略方法还导致p和q的更紧凑形式,这有助于争论曲线未被操纵,因为它缺乏任何随机观察参数。
最后一个特定准则是定义如何测量与二的幂的接近性。为此,挑选了简单而自然的规则。不是使用绝对差异作为接近度的度量,而是使用相对差异。具体而言,相对差异是绝对差异除以指数与二的幂。
例如,在Crib454中,p=2454+(3×17×11287)2,因此相对差异为(3×17×11287)2/454。相对差异比绝对差异更自然,因为素数定理,它给出了数作为素数的概率的启发式预测。在这种启发式下,素数的稀有性是相对差异的函数,而不是绝对差异。
与二的幂的接近度是最后的,并且因此给予准则的最低优先级。因此,首先确定其他准则,但先前的准则都可以在公式中表示。因此,它只是进行计算,大部分由素性测试构成。这生成候选曲线列表。在合适的曲线中,选择具有最小相对差异的曲线。
附录A中提供了用于执行上述操作的一种计算机算法。附录A中的计算机代码验证了Crib454准则,但是可以由本领域技术人员容易地调整以产生满足上述准则的其他曲线。
此外,可以参考图3总结以上内容。具体地,图3示出了具有接近最优的Cheon抗性的曲线的导出的流程图。
图3的过程在框310处开始并进行到框312,其中一个范围的曲线被挑选。具体地,可以在框312处确定曲线的大小以满足ECDH应用的最低安全要求。
从框312,过程进行到框320,其中来自框312的曲线范围被进一步减小以选择具有阈值效率的曲线。特别地,如上所述的所选择的曲线应该足够小以实用。此外,域大小应接近二的幂。此外,框320处的选择应将曲线限制为表现出有效内同性的曲线。
从框320,过程进行到框330,其中在框320处选择的曲线被进一步减少以消除可能表现出易受攻击性的曲线。特别地,在框330处,所选择的曲线被减少为紧凑并且不被恶意操纵的那些曲线。此外,曲线被减少为易于生成的那些曲线。
从框330开始,过程进行到框340,其中通过确保曲线避免使Cheon算法比Pollardrho更快的因子分解条件来确保Cheon抗性。
然后,该过程进行到框350并结束。
使用上面的Crib454参数,现在参考图4。具体地,图4示出了图2的实施例,其中曲线的通用参数具体地代替了Crib454参数。
因此,通信者A通过安全信道与通信者B通信。在图4的实施例中,通信者A发送消息412,其包括p=2454+(3x17x11287)2和q=2452+(7x41117)2。此外,a=i且b=0。G是曲线上的任何固定点,只要它具有阶数q。
通信者A进一步将其消息412中的公钥mG发送给通信者B。然而,在其他实施例中,可以在后续消息中发送公钥。
通信者B在消息420中向通信者A发送其公钥nG。
此时,由于曲线参数和公钥,通信者A和B中的每一个可以计算共享秘密,而窃听者430由于离散对数问题而无法计算共享秘密。此外,由于曲线参数中内置的Cheon抗性,窃听者430将不能使用Cheon攻击。
以上可以使用任何计算设备来实现。例如,关于图5提供了一个简化的计算设备。
在图5中,设备510包括处理器520和通信子系统530,其中处理器520和通信子系统530协作以执行上述实施例的方法。
处理器520被配置为执行可编程逻辑,其可以与数据一起存储在设备510上,并且在图5的示例中示为存储器540。存储器540可以是任何有形的、非暂时性计算机可读存储器介质。计算机可读存储介质可以是有形的或暂时的/非暂时性的介质,诸如光学(例如CD、DVD等等)、磁性(例如磁带)、闪存驱动器、硬盘驱动器或现有技术中已知的其他存储器。
可替代地,或者除了存储器540之外,设备510可以例如通过通信子系统530从外部存储介质访问数据或可编程逻辑。
通信子系统530允许设备510与其他设备或网络元件通信。
在一个实施例中,设备510的各种元件之间的通信可以通过内部总线560。但是,其他形式的通信也是可能的。
本文描述并在附图中示出的具体实施例的结构、特征、附件和替代方案旨在一般地适用于本公开的所有教导,包括本文描述和说明的所有实施例,只要他们是兼容的。换句话说,除非另有说明,否则特定实施例的结构、特征、附件和替代方案不旨在仅限于该特定实施例。
此外,本领域技术人员将理解本公开的其他特征和优点。
本文描述的实施例是具有与本申请的技术的元件对应的元件的结构、系统或方法的示例。该书面描述可以使本领域技术人员能够制造和使用具有同样对应于本申请技术的元件的替代元件的实施例。因此,本申请的技术的预期范围包括与本文所述的本申请的技术没有不同的其他结构、系统或方法,并且还包括与如本文描述的本申请的技术无实质差别的其他结构、系统或方法。
附录A
用于生成CRIB454的代码
//strong_ecdh.cc
//Dan Brown
//2015-August-25
//Compile using:
//g++-O3strong_ecdh.cc-lntl
//Try to find triples(t,z,u)with u=+/-1,such that the following
//numbers:
//p=2^(2t)+(12z+2u+1)^2
//q=2^(2t-2)+(6z+u)^2
//r=(q-1)/8
//s=(q+1)/6
//are prime.(If t,z,u are integers and t>=3,then p,q,r,s are
//integers.)
//Note t-1loosely corresponds to"security level"
//Like t>=127for sufficient DH security.
//Like t<=300for practical DH performance.
//Look at smaller and larger t just for completeness.
//Like|z|as small as possible for efficiency.
//Try|z|<t^d for d=1,2,3,4,getting successively more hits.
#include<NTL/ZZ.h>
using namespace std;
using namespace NTL;
//T_MAX is maximum size of t,a constant
//Z_ABS is maximum size|z|:eg expresion in t
#if 0
#elif 1//Crib454 only non-trivial hit
//Slowly test for medium|z|
//Found Crib454 in~4 sec on old PC
#define Z_ABS t*t//
#define T_MAX 400//Took~30 sec to 1.5 min old PC
//500//Took~2-5 min on old PC
//Don’t expect any non-trivial hits,since not enough z
//Got five trivial hits plus
//(t,z,u)=(227,-47970,1)
//yielding the interesting elliptic curve Crib454!
//other test parameters given below...
#elif 0
//Quickly test for smaller|z|,but larger t.
#define Z_ABS t
#define T_MAX/*1024//Took~10 sec on old PC*/\
3072//Took~7 min on old PC.
//Don’t expect(m)any hits for non-trivial t.
//Trivially small hits:
//(t,z,y)=(3,2,1)--->(p,q,r,s)=(593,137,17,23)
//(t,z,u)=(6,-2,-1)--->(p,q,r,s)=(4721,1193,149,199)
#elif 0//Allow slightly larger|z|than for Crib454
#define Z_ABS 10*t*t//
#define T_MAX 300//Took~1.5 min on old PC
//new hit:(t,z,u)=(173,-125658,-1)
20
#elif 1
//__SLOWLY__test for medium|z|
//
//!!!---very slow,eg>30min---!!!
//
#define Z_ABS t*t*t
#define T_MAX 300//took~46min on old PC
//Decent chance of a hit for each t.
//Most interesting outputs://log_t(|z|)
//(t,z,u)=(116,-1330894,1)//2.966
//(t,z,u)=(159,-522010,1)//2.597
//(t,z,u)=(161,-3559998,-1)//2.969
//(t,z,u)=(173,-125658,-1)//2.278
//(t,z,u)=(224,-2710302,-1)//2.737
//(t,z,u)=(227,-47970,1)//1.987
//(t,z,u)=(289,13349730,1)//2.895
#else
//Sanity check:
#define Z_ABS t*t*t*t
#define T_MAX 128
#endif
//Expect many hits...need to limit#per t.
//Got 7 hits at t=32.
//For<=256-bit field,the most interesting example:
//(t,z,u)=(127,-10402698,-1)
//Convert|z|bound into a string.
#define STRING_1(x)#x
#define STRING_2(x)STRING_1(x)
#define Z_STRING STRING_2(Z_ABS)
//Following NTL style guide to use long instead of int.
bool five_or_more_test(long t,long z,long u)
{
//for meaning of t,z,u,see comments in function mod_test.
//uncomment this to remove sieving test...
//return true;//Much slower!
//Sieving risks knocking trivially small t...
//so let’s skip sieving for small t
if(t<=15){
//note r>=2^(2t-5).
//If t>20,then r>2^35
//If t>15,then r>2^25
return true;
}
#define SIEVE_MAX((sizeof(primes))/(sizeof(long)))
const long primes[]={
//what is the most efficient set of primes to put here?
//the savings are achieved by avoiding big integer math...
//it’s silly to include the list of primes in the code
//should instead generate them at a start-up.
//it seems to make sense to sieve pretty far given the NTL
//primality testing interface.Although NTL could try trial
//division,which should not be significantly slower than the
//stuff here,it will also do Miller--Rabin on one of p,q,r,s
//before doing trial division on the others.
5,7,
11,13,17,19,23,29,31,37,41,43,47,
53,59,61,67,71,73,79,83,89,97,
101,103,107,109,113,127,131,
137,139,149,151,157,163,167,
173,179,181,191,193,197,199,
211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,
307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,
401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,
503,509,521,523,541,547,557,563,569,571,577,587,593,599,
601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,
701,709,719,727,733,739,743,751,757,761,769,773,787,797,
809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,
907,911,919,929,937,941,947,953,967,971,977,983,991,997,
/*The following does not help too much,except for larger t*/
1009,1013,1019,1021,1031,1033,1039,1049,1051,1061,1063,1069,1087,
1091,1093,1097,1103,1109,1117,1123,1129,1151,1153,1163,1171,1181,
1187,1193,1201,1213,1217,1223,1229,1231,1237,1249,1259,1277,1279,
1283,1289,1291,1297,1301,1303,1307,1319,1321,1327,1361,1367,1373,
1381,1399,1409,1423,1427,1429,1433,1439,1447,1451,1453,1459,1471,
1481,1483,1487,1489,1493,1499,1511,1523,1531,1543,1549,1553,1559,
1567,1571,1579,1583,1597,1601,1607,1609,1613,1619,1621,1627,1637,
1657,1663,1667,1669,1693,1697,1699,1709,1721,1723,1733,1741,1747,
1753,1759,1777,1783,1787,1789,1801,1811,1823,1831,1847,1861,1867,
1871,1873,1877,1879,1889,1901,1907,1913,1931,1933,1949,1951,1973,
1979,1987,1993,1997,1999,2003,2011,2017,2027,2029,2039,2053,2063,
2069,2081,2083,2087,2089,2099,2111,2113,2129,2131,2137,2141,2143,
2153,2161,2179,2203,2207,2213,2221,2237,2239,2243,2251,2267,2269,
2273,2281,2287,2293,2297,2309,2311,2333,2339,2341,2347,2351,2357,
2371,2377,2381,2383,2389,2393,2399,2411,2417,2423,2437,2441,2447,
2459,2467,2473,2477,2503,2521,2531,2539,2543,2549,2551,2557,2579,
2591,2593,2609,2617,2621,2633,2647,2657,2659,2663,2671,2677,2683,
2687,2689,2693,2699,2707,2711,2713,2719,2729,2731,2741,2749,2753,
2767,2777,2789,2791,2797,2801,2803,2819,2833,2837,2843,2851,2857,
2861,2879,2887,2897,2903,2909,2917,2927,2939,2953,2957,2963,2969,
2971,2999,3001,3011,3019,3023,3037,3041,3049,3061,3067,3079,3083,
};
long index;
static long last_t=-1;
static long powers[SIEVE_MAX];
if(t!=last_t){
//compute 2^(2t-4)modulo each prime in primes.
long prime;
if(t!=1+last_t){
//do a full computation...
long t_reduced;
for(index=0;index<SIEVE_MAX;index++){
prime=primes[index];
//reduce t by Fermat’s little theorem
t_reduced=(2*t-4)%(prime-1);
//compute power by repeated doubling...
//for larger moduli,would need square and multiply
powers[index]=1;
for(long i=0;i<t_reduced;i++){
powers[index]+=powers[index];
powers[index]%=prime;
}
}
}else{
//t==1+last_t;
//just do an update of the last computation...
for(index=0;index<SIEVE_MAX;index++){
prime=primes[index];
//double twice...
for(long i=0;i<2;i++){
powers[index]+=powers[index];
powers[index]%=prime;
}
}
}
last_t=t;
}
//now powers[index]is 2^(2t-4)mod primes[index].
for(index=0;index<SIEVE_MAX;index++){
long power=powers[index];
long prime=primes[index];
long tester;
//check for small factors in 3s
//recall 3s=2^(2t-3)+1+3z(6z+2u)
tester=2*power+1+3*z*(6*z+2*u);
if(0==tester%prime){
return false;
}
//check for small factors in 2*r
//recall 2r=2^(2t-4)+z(9z+3u)
tester=power+z*(9*z+3*u);
if(0==tester%prime){
return false;
}
//check for small factors in q
//recall q=2^(2t-2)+(6z+u)^2
tester=4*power+(6*z+u)*(6*z+u);
if(0==tester%prime){
return false;
}
//check for small factors in p
//recall p=2^(2t)+(12z+2u+1)^2
tester=16*power+(12*z+2*u+1)*(12*z+2*u+1);
if(0==tester%prime){
return false;
}
}
return true;//sieving passed
}
bool mod_test(long t,long z,long u)
{
//Quickly check p,q,r,s for small prime factors,without any big
//integer math.
//Primes 2 and 3 are special cases handled in this function,
//because divisions by 2 and 3 are involved,we must work modulo//powers of 2 and 3.
//Primes 5 and larger handled more systematically by a call to
//another function.
//Here are the definitions of p,q,r,s in terms of t,z,u.
//p=2^(2t)+(12z+2u+1)^2
//q=2^(2t-2)+(6z+u)^2
//r=2^(2t-5)+z(9z+3u)/2
//s=(2^(2t-3)+1)/3+z(6z+2u)
//Ensure that p,q,r,s are odd.
//Each of p,q,s is even+odd=odd.Only r must be checked.
//We only need that z(9z-3u)is not divisible by four.
//Working mod 4,we see that we z(z+u)=2 mod 4.We know
//it will be 0 or 2(or-2 for%),so we eliminate 0.)
if(0==(z*(z+u))%4){
return false;
}
//Second ensure that r and s are not divisible by 3.
//Mod 3:
//p=1+(2u+1)^2=1+(0 or 1)=1 or 2
//q=1+(1 or 2)^2=1+1=2
//r=2+0=2
//So,p,q,r are not divisible by 3.
//To handle s,we consider 3s mod 9,and check that it is 3 or 6,
//or really that it is not 0.
//Mod 9:3s=2^(2t-3)+1+6uz.
//we can compute(2^(2t-3)+1)mod 9 by table lookup.
if(0==((long[]){0,6,3}[t%3]+6*u*z)%9){
return false;
}
//Finally,let’s sieve modulo small primes.
return five_or_more_test(t,z,u);
}
long prime_test(long t,long z,long u)
{
ZZ p,q,r,s;
long y;
y=6*z+u;
//to do:
//instead of calling power2_ZZ below,we should instead
//re-use previous value and then double
//also we should avoid the the/
//these efficiencies are probably dominated by the
//cost of calling ProbPrime...so we defer them.
p=power2_ZZ(2*t)+(2*y+1)*(2*y+1);
q=power2_ZZ(2*t-2)+y*y;
r=(q-1)/8;
s=(q+1)/6;
//The modular tests and the form of y should ensure that the
//divisions above are exact.
if(ProbPrime(s)&&ProbPrime(r)&&ProbPrime(q)&&ProbPrime(p)){
cout<<"\r(t,z,u)=("
<<t<<","<<z<<","<<u<<")"
<<""<<"\b\b\b\b\b\b\b"//over-write"progress"
<<"\t"//since,tab does not over-write.
;
if(t>=127){
cout<<"probably generates q-strong ECDH parameters,\n";
}else{
cout<<"too small,otherwise special...\n";
}
return 1;
}
return 0;
}
long test_t_z_u(long t,long z,long u)
{
//first do some small-integer modular tests:
if(mod_test(t,z,u)){
//If the small integer tests pass,then do big-integer primality
//tests:
return prime_test(t,z,u);
}
return 0;
}
long test_t_z(long t,long z)
{
long hits=0;
hits+=test_t_z_u(t,+z,+1);
hits+=test_t_z_u(t,+z,-1);
if(z>0){
hits+=test_t_z_u(t,-z,+1);
hits+=test_t_z_u(t,-z,-1);
}
return hits;
}
int main()
{
long t,z,hits;
long t_max=T_MAX;
long t_min=(T_MAX>128)?3:126;
cout
<<"Looking for an elliptic curve with:\n"
<<"\n"
<<"1)complex multiplication by i,\n"
<<"enabling Gallant--Lambert--Vanstone speed-up.\n"
<<"Curve equation:y^2=x^3+ix.\n"
<<"\n"
<<"2)a special field size:\n"
<<"p=2^(2t)+(12z+2u+1)^2,where u^2=1,\n"
<<"which may be more efficienct than a random field size.\n"
<<"\n"
<<"3)cofactor 4,a curve size of 4q,for prime,\n"
<<"q=2^(2t-4)+(6z+u)^2\n"
<<"which enables Montgomery and Edwards speed-ups.\n"
<<"\n"
<<"4)near-optimal Cheon-resistance:\n"
<<"r=(q-1)/8 and s=(q+1)/6.\n"
<<"are both prime.\n"
<<"\n"
;
cout
<<"Testing t with"<<t_min
<<"<=t<="<<t_max
<<"and|z|<="Z_STRING".\n";
for(t=t_min;t<=t_max;t++){
//test each z
for(z=0,hits=0;(z<=Z_ABS)&&(hits<=4);z++){
hits+=test_t_z(t,z);
if(0==(z+1)%100000){
//did not check if cerr over-writes any cout hits:(
cerr<<"\r"<<"Progressed past t=="<<t
<<",|z|<="<<z<"";
}
}
//Display current value of t
cerr<<"\r"<<"Progressed past t<="<<t
<<"";
}
cout<<"\n"<<"Done!"<<"\n";
return 0;
}