学习笔记6

第11章 Diffle-Hellman协议

  Diffle-Hellman协议主要用于密钥交换,使得在不安全线路上通信的两个人能够以这样的方式协商得到密钥:两个人都能得到相同的密钥,并且这个密钥不会泄露给监听二人会话的其他人。

11.1 群

11.2 基本的DH

  在基本的DH协议中,首先选取一个大素数\(p\)和群\(Z_p^*\)的本原元\(g\),并且\(p\)\(g\)都是公开的常数,包括攻击者在内的所有参与方都知道它们。

  协议的主要流程如下:首先Alice选择\(Z_p^*\)中的一个随机数\(x\),计算\(g^x mod \; p\)发送给Bob;然后Bob也在\(Z_p^*\)中选择一个随机数\(y\),计算\(g^y mod \; p\)发送给Alice;最好Alice与Bob分别计算\(k=(g^y)^x mod \; p\)\(k=(g^x)^y mod \; p\),所以两人都获得了同样的\(k\)\(k\)可以用作密钥。

  通过\(g^x mod \; p\)的结果来计算\(x\)的问题通常被称为离散对数问题,或者DL问题。

11.3 中间人攻击

  DH协议不能抵抗中间人攻击。回顾整个协议可以发现,Alice知道她在与某一个人进行通信,但是她不知道是在与谁通信。Eve可以处于协议的中间,当与Alice通信时伪装成Bob,而与Bob通信时伪装成Alice,如下图所示。对于Alice来说,这个协议看起来就像原始的DH协议,她没有办法发现她是在与Eve而不是Bob通信。对于Bob来说也是样的。只要Eve愿意,她可以一直这样伪装下去。如果 Alice和Bob使用他们所认为的已经建立起来的密钥进行通信,Eve需要做的就是转发Alice和Bob的所有通信,当然Eve必须解密从Alice那里得到的使用密钥\(k\)加密的所有数据,然后再使用密钥\(k'\)加密并发送给Bob,对相反方向的通信她也需要做相同的事情,但这并没有多大的工作量。

img1

11.4 一些可能的问题

  第一个问题,假如Eve拦截了通信并把\(g^x\)\(g^y\)都替换为数1,那么Alice和Bob最终都将得到密钥\(k=1\)。对于这个结果,密钥协商协议看起来好像成功地完成了,但是Eve却知道了所产生的密钥。这是很糟糕的,我们必须采取某种方法来防止这种攻击。

  第二个问题就是Alice和Bob都要确保\(p\)是素数,\(g\)是模\(p\)的本原元。

11.5 安全的素数

  安全素数是一个(足够大的)形如\(2q+1\)的素数\(p\),其中\(q\)也是素数。这样一来,乘法群\(Z_p^*\)只有下面的子群:

  1. 只包含1的平凡子群;
  2. 包含2个元素的子群,即\(1\)\(p-1\)
  3. 包含\(q\)个元素的子群;
  4. 包含\(2q\)个元素的整个群。

  前两个子群不安全,但是也容易避免,第三个是我们想要使用的子群,因为如果使用整个群的话就会带来另一个问题。在所有的模\(p\)数中,如果一个数能够写成另一个数的平方,那么我们就称这个数为平方数。事实上,\(1,2,\cdots,p-1\)中恰好有一半的数是平方数,而另一半是非平方数。整个群的任何一个生成元都是非平方数(如果它是一个平方数,那么它的任何次幂都不可能产生一个非平方数,所以它不可能生成整个群)。

11.6 使用较小的子群

  使用安全素数方法的缺点在于效率不高。如果素数\(p\)\(n\)位,那么\(q\)就有\(n-1\)位,所有的指数都是\(n-1\)位,那么平均求幂运算将大约需要\(3n/2\)次模\(p\)数的乘法运算。对于大素数\(p\)来说,这是相当大的工作量。

  标准的解决方案是使用较小的子群,下面是具体做法:选择一个256位的素数\(q\)(即\(2^{255}<q<2^{256}\)),然后找一个更大的素数\(p\)满足\(p=Nq+1\),其中\(N\)为任意值。要找到这样的\(p\),可以先在适当的范围内随机选择一个\(N\),计算\(p=Nq+1\),并检查\(p\)是否为素数。由于\(p\)定是奇数,容易发现\(N\)必为偶数。素数\(p\)可以有几千位长。

  然后需要找到一个阶为\(q\)的元素。我们使用类似于安全素数情况中的方法,在\(Z_p^*\)中选择一个随机数\(a\),令\(g=a^N\),验证\(g≠1\)并且\(g^p=1\)。如果\(g\)不满足这些条件,就选择另一个\(a\)并再次尝试。这样产生的参数集合
\((p,q,g)\)将适用于 Diffie-Hellman协议。

11.7 p的长度

  关于需要多大的素数\(p\),最好的估计方法可以在文献中找到。一个2048位的素数能够保护数据到2022年左右,3072位的素数在2038年之前是安全的,而4096位的素数可以使用到2050年。上面提到的6800位也是使用公式推导出来的。如果想要求攻击者执行\(2^{128}\)步才能完成一次攻击,P的长度就应该是6800位。

11.8 实践准则

  选择256位的素数\(q\),选择一个形如\(Nq+1\)的大素数\(p\),其中\(N\)是整数。随机选取\(g\),使其满足\(g≠1\)并且\(g^q=1\)

  接收到这个子群描述\((p,q,g)\)的任何一个参与方都应该验证:

  1. \(p\)\(q\)都是素数,\(q\)有256位,并且\(p\)足够大;
  2. \(q\)\(p-1\)的因子;
  3. \(g≠1\)并且\(g^q=1\)

img2

11.9 可能会出错的地方

  这里有一个Alice发生错误的例子:当她接收到重发的包含\(Y\)的消息时,她只是重新计算密钥\(k\)并发送正确的应答给Bob。虽然这样处理听起来完全没有问题,但是攻击者Eve现在就可以利用这一点来进行攻击。假设\(d\)\((p-1)\)的小因子。Eve可以把\(Y\)替换为一个阶数为\(d\)的元素,那么现在Alice的密钥\(k\)就只限于\(d\)种可能的值,并且完全由\(Y\)\((x mod \;d)\)确定。Eve尝试\((x mod \;d)\)的所有可能性,计 Alice可能得到的密钥\(k\),接着试图解密Alice发送的下一条消息。如果Eve正确地猜到了\((x mod \;d)\),那么这个消息将被正确地解密,Eve就知道了\((x mod \;d)\)

  如果\(p-1\)包含了多个小因子\((d_1,d_2,\cdots,d_k)\),那么Eve就对每一个因子重复进行此攻击,得到\((x mod \; d_1),\cdots,(x mod \; d_k)\),再利用通用形式的中国剩余定理,Eve就可以得到\((x mod \; d_1d_2\cdots d_k)\),从而获得相当多的关于\(x\)的信息。

  如果Eve是选择子群\((p,q,g)\)的人,那么攻击就变得更容易了。可能在刚开始选择\(p\)的时候她自己已经把小因子放入\(p-1\)了。或者,也许她担任了标准委员会的委员,能够推荐某些参数作为标准。

  最后,最简单的解决方案就是检查接收的每一个值都在正确的子群中。所有其他的防止小子群攻击的方法都要复杂很多。比如我们可以设法直接检测\(p-1\)的小因子,但是那种方法太复杂了,也可以要求产生参数集合的人提供\(p-1\)的因子分解,但那样会给整个系统增加大量复杂性。验证接收到的值属于正确的子群只需要很少的工作,也是到目前为止最简单、最健壮的解决方案。


第12章 RSA

  RSA系统是世界上最著名也最广泛使用的公钥密码系统。RSA能够同时提供数字签名方案和公钥加密方案,从而使其成为一个非常通用的工具。同时它是基于解决大整数分解问题的困难性而设计的,这个问题在过去的几千年里吸引了很多人并得到了广泛的研究。

12.1 引言

  RSA类似于Diffle-Hellman,但二者还是有很大的区别的。 Diffie-Hellman(或者简称DH)基于一个单向函数:假设\(p\)\(q\)是公开已知的,那么可以由\(x\)计算\((g^x mod \; p)\),但是给定\((g^x mod \; p)\)却不能计算出\(x\)。RSA则是基于一个陷门单向函数。给定公开已知的信息\(n\)\(e\),容易由\(m\)计算\(m^e mod \;n\),但相反的方向却不行。不过如果知道\(n\)的因子分解,那么反向计算就变得容易了。\(n\)的因子分解就是陷门信息,掌握了陷门信息就可以对函数求逆,否则就无法求逆。这种陷门功能使得RSA既可以用于加密,又可以用于数字签名。

12.2 中国剩余定理

  如果已知\((x mod \; p, \; x mod \; q)\),那么就能求出\(x\)

12.2.1 Garner公式

  计算上面\(x\)的解的最好办法是Garner公式:

\[x=(((a-b)(q^{-1} mod \; p)) \; mod \; p) \cdot q +b \]

12.2.2 推广

  CRT也适用于\(n\)为多个不同素数乘积的情形,Garner公式也可以推广到这些情况中去。

12.2.3 应用

  使用CRT进行模\(n\)运算,可以节省很多时间。
  设n有\(k\)位,那么素数\(p\)\(q\)大约都有\(k/2\)位。一次模\(n\)加法需要一次\(k\)位的加法,如果结果超过\(n\),接着还需要一次\(k\)位的减法。采用CRT表示需要对一半长度的数做两次模加法,计算量几乎是一样的。
  对于乘法运算,使用CRT就能够节省大量时间。两个\(k\)位的数相乘所需要的计算量远远超过两个\(k/2\) 位的数相乘计算量的两倍。在大多数实现中。CRT乘法的执行速率是完整的乘法的两倍,计算量明显减少。
  对于指数运算也是同样的道理。

12.2.4 结论

  当\(n=pq\)时,\(x\)\(n\)可以表示为\((x mod \; p, x mod \; q)\)对,而且这两种表示之间的转换相当简单。如果要做很多次模一个合数的乘法,而且已知该合数的因子分解,那么就可以使用CRT表示来加快计算(如果不知道\(n\)的因子分解,就不能用它来加快计算)。

12.3 模n乘法

  在RSA中,我们需要找到一个指数\(t\)使得\(x^t=1 mod \; n\)对(几乎)所
有的\(x\)都成立。

  利用CRT的结论,很容易找到这个\(t\)就等于\(lcm(p-1,q-1)\)

12.4 RSA

  下面将对RSA系统进行详细说明。首先随机选择两个不同的大素数\(p\)\(q\),计算\(n=pq\)。素数\(p\)\(q\)应该是(几乎)同样的长度,得到\(n\)的长度是\(p\)\(q\)的两倍。

  接下来选取两个不同的指数,通常称为\(e\)\(d\),并且满足\(ed=1 mod \; t\),或者也可以写成\(ed=1 mod \; \varphi(n)\)

  要加密消息\(m\),送者计算密文\(c=m^e mod \; n\),接收者收到\(c\)之后,计算\(m'=c^d mod \; n\),可以通过证明得出\(m'=m\)

  \((n,e)\)对构成了公钥,这些公钥被分发给很多不同的参与方。\((p,q,t,d)\)构成了私钥,由生成RSA密钥的人秘密保存。

12.4.1 RSA数字签名

  RSA的一个巨大优势在于既可以用于加密消息,又能够对消息签名。这两种操作的计算方式是相同的,为了签署一个消息\(m\),私钥的拥有者计算\(s=m^d mod \; n\)。现在\((m,s)\)就是一个经过签名的消息,要验证签名,任何知道公钥的人都可以验证\(m=s^e mod \;n\)是否成立。

  和加密一样,签名的安全性基于同样的事实:只有掌握了私钥,才可以计算\(m\)\(e\)次方根。

12.4.2 公开指数

  到目前为止,我们描述的过程有一个问题:如果公开的指数\(e\)\(t=lcm(p-1,q-1)\)有公因子,那么\(d\)就没有解。所以必须选取\(p\)\(q\)\(e\)使得这种情形不会发生,这个问题虽然有些麻烦,但是必须要处理。

  选取一个小的公开指数能够使RSA更高效,因为计算一个数的\(e\)次幂所需要的计算量更小了,所以要尽量为\(e\)选择一个比较小的值。

  \(e\)通常可以选取3、5、17和65537。

12.4.3 私钥

  如果攻击者只知道公钥\((n,e)\),那么计算私钥\((p,q,t,d)\)中的任何一个值都是极其困难的。只要\(n\)足够大,就没有算法能够在可以接受的时间内做到这一点。我们知道的最好的解决方案是把\(n\)分解为\(p\)\(q\),然后再计算\(t\)\(d\)。这也正是因子分解在密码学中如此重要的原因。

  前面已经谈到,私钥由\((p,q,t,d)\)组成,而事实上,知道其中的任何一个值都可以计算出其他3个值,这一点是非常重要的。

12.4.4 n的长度

  模\(n\)应该与DH中的模\(p\)具有相同的长度,需要重申的是:如果要保护数据20年,\(n\)的绝对最小长度是2048位。这个最小值会随着计算机速度的增长而缓慢增长。如果可能的话,在实际应用中就取\(n\)为4096位长,或者尽量接近于这个长度。此外,要保证软件能够支持最大8192位长的n值,毕竟我们不知道将来会怎样,如果能够使用更长的密钥而不必更换软件或者硬件,这种支持将会发挥作用。

  两个素数\(p\)\(q\)应该具有相同的长度,要得到一个\(k\)位的模\(n\),可以生成两个随机的\(k/2\)位的素数并把它们相乘。不过这样可能得到的是一个\(k-1\)位的模\(n\),但是影响不大。

12.4.5 生成RSA密钥

  下一个函数将生成所有的密钥参数。

12.5 使用RSA的缺陷

  使用目前给出的RSA是很危险的,问题就在于其数学结构。比如,如果Alice对两个消息\(m_1\)\(m_2\)进行了数字签名,那么Bob就能够计算出Alice对消息\(m3=m1m2mod \; n\)的签名。这是因为Alice计算了\(m_1^d\)\(m_2^d\),Bob可以把二者相乘从而得到\((m_1m_2)^d\)

  如果Bob使用Alice的公钥加密了一个很短的消息\(m\),就会产生另一个问题。具体地说,如果\(e=5\)并且\(m<\sqrt[5]n\),那么\(m^e=m^5<n\),所以不会进行模约化运算,攻击者Eve只要计算\(m^5\)的五次方根就可以恢复出\(m\),而由于没有模约化,这步运算就很容易完成。产生这种问题的一个典型例子就Bob在发送AES密钥给Alice时只是把256位的密钥看作一个整数,那么密钥经过加密后不会超过\(2^{256 \cdot 5}=2^{1280}\),这个值比\(n\)小很多,所以不会有模约化运算,Eve只需要计算加密后的密钥值的五次方根就得到了密钥。

12.6 加密

  加密是RSA的典型应用,但在实际中几乎从不使用。原因很简单:使用RSA所能够加密的消息的长度受限于\(n\)的长度。在实际系统中,我们甚至都不能加密和\(n\)一样长的消息,因为编码函数需要一定的开销。有限的消息长度对大多数应用来说太不实际了,而且在计算量方面,RSA操作相当耗时,因此我们不希望把一个消息分成小块而对每个小块进行单独的RSA加密。

  目前通用的解决方案都是选择一个随机的密钥\(K\),利用RSA密钥加密\(K\),然后使用密钥\(K\)通过分组密码或者流密码来加密实际的消息\(m\),所以最终发送的不是\(E_{RSA}(m)\),而是\(E_{RSA}(K)\)\(E_{K}(m)\)。这样,消息的长度不再有限制,而且即使对于很长的消息也只需要一次RSA操作。当然,我们需要额外传送少量的数据,但是与获得的好处相比,这个代价是很小的。

  接收者计算\(K=h(c^d mod \; n)\),得到同一个密钥\(K\)

12.7 签名

  在签名方案中,我们需要多做一部分工作。问题就在于要签名的消息\(m\)可能有许多结构,而我们不希望进行RSA操作的那些数具有任何结构,所以必须要破坏它们的结构。

  第一步对消息进行散列运算。所以,我们处理的不是可变长度的消息\(m\),而是固定长度的值\(h(m)\),这里h是一个散列函数。如果使用SHA-256,我们得到的结果有256位,但是\(n\)的值要大得多,所以不能直接使用\(h(m)\)

  所以,签名方案中一共有3个函数:第一个把消息映射为\(s\),第二个给消息进行签名,而第三个用于验证签名。

  当然,在实际应用中,如果签名验证失败则还要采取一定的措施,我们这里只是写下了一个断言以表明正常的操作该终止了。签名失败和密码协议中产生的其他错误一样,都明确地表示出我们正在受到攻击。遇到这种情况,除非不得已,千万不要发送任何应答,而且要销毁所有参与计算的数据。发送出去的信息越多,攻击者能够获得的信息也越多。

posted @ 2023-03-26 19:22  acacacac  阅读(58)  评论(0编辑  收藏  举报