密码编码学与网络安全----原理与实践(第八版)---第9章笔记

第九章 公钥密码学与RSA

学习目标:

  • 概述公钥密码体制的基本原理。
  • 阐述公钥密码体制的两个不同应用。
  • 列举和解释公钥密码体制的要求。
  • 概述RSA算法。
  • 理解计时攻击。
  • 总结算法复杂性的相关问题。

        公钥或对称密码学的发展是整个密码学发展史最伟大的一次革命。从密码学产生至今,几乎所有密码体制都是基于代替和置换这些初等方法的。几千年来,人们对算法的研究主要是通过手工计算完成的。随着转轮加密/解密机器的出现,对称密码学有了很大的发展,利用电子机械转轮可以开发出极其复杂的加密系统,利用计算机甚至可以设计出更加复杂的系统,最著名的例子是Lucifer在IBM公司实现数据加密标准(DES)时设计的系统。转轮机和DES是密码学发展的重要标志,但它们都是基于代替和置换这些初等方法的。                                                                                   公钥密码学与此前的密码学完全不同。首先,公钥算法基于数学函数而并非代替和置换,更重要的是,与只用一个密钥的对称密码不同,公钥密码学是非对称的,他使用两个独立的密钥。我们将会看到使用两个密钥在消息的保密性、密钥分发和认证领域有着重要意义。                                     下面首先讨论关于公钥密码的几种误解。第一种误解是,从密码分析的角度看,公钥密码要比传统密码更安全。事实上,任何加密方法的安全性都依赖于密钥的长度和破译密文所需的计算量。从抗密码分析的角度看,原则上不能说传统密码优于公钥密码,也不能说公钥密码优于传统密码            第二种误解是,公钥密码是一种通用方法,传统密码已经过时。事实正好相反,由于现有的公钥密码方法所需的计算量大,所以抛弃传统密码几乎不可能。就像公钥密码的发明者之一所说的[DIFF88],“公钥密码学仅限用在密码管理和签名这类应用中,这几乎是已被广泛接受的事实。”             最后一种误解是,传统密码中与密钥分发中心的会话是一件非常麻烦的事情,与之相比,用公钥密码实现密钥分发则非常简单。事实上,使用公钥密码也需要某种形式的协议,该协议通常包含一个中心代理,并且它包含的处理过程既不比传统密码中的那些过程简单,又不比之更有效(见文献[NEED78]中的分析)。                                                                                                                         本章和下一章简要介绍公钥密码。首先介绍其中的基本概念。有趣的是,这些概念在用于公钥密码中之前就已被提出;然后讨论RSA算法,它是公钥密码中最重要且切实可行的一种加密/解密算法,第10章中将介绍其他一些重要的公钥密码算法。                                                                          很多公钥密码体制的理论都基于数论。如果读者接受本章中给出的结论,那么就不必严格地理解数论的有关知识。然而,要完全理解公钥算法,就需要理解这些数论知识。第2章中简要介绍了与公钥密码有关的数论知识。

公钥密码的一些重要术语

非对称密钥        两个密钥:公钥和私钥,用来实现互补运算,即加密和解密,或者生成签名与验证签名。

公钥证书           认证机构将用户的姓名和公钥绑定在一起,用户用自己的私钥对数字文件签名后,通过证书识别签名者,因为签名者是唯一拥有与证书对应的私钥的用户。

公钥密码(非对称密码)算法        含两个密钥:公钥和私钥。从公钥推出私钥在计算上是不可能的。

公钥基础设施        由一系列协议、服务平台、软件和工作站组成,用于管理证书和公钥-私钥对,并且发出、维护和废除公钥证书。

9.1 公钥密码体制的原理

        公钥密码学的概念是为解决对称密码中最困难的两个问题提出的。第一个问题是将在第14章中详细讨论的密钥分发问题。                                                                                                                    如第14章所述,在对称密码中进行密钥分发时,要求:(1)通信双方已经共享一个密钥,且该密钥已通过某种方法分发给通信双方;(2)利用密钥分发中心。公钥密码的发明人之一Whitfield Diffie(另一个发明人是Martin Hellman,当时他们都在斯坦福大学工作)认为,第二个要求有悖于密码学的精髓,即应在通信过程中完全保持保密性。如Diffie所说[DIFF88],“如果必须要求用户与KDC共享他们的密钥,这些密钥可能因为盗窃或索取而被泄密,那么设计不可破的密码体制究竟还有什么意义呢?”                                                                                                                         Diffie考虑的第二个问题是“数字签名”问题,该问题显然与第一个问题无关。如果密码学不是只用于军事领域,而是广泛用于商业或个人目的,那么像手写签名一样,电子消息和文件也需要签名,也就是说,能否设计一种方法,确保数字签名出自某个特定的人,并且各方对此均无异议?对数字签名的要求比对认证的要求更为广泛,第13章将讨论数字签名的特征及相关的问题。                     1976年,Diffie和Hellman针对上述两个问题提出了一种方法,这种方法与此前四千多年来密码学中所有方法有着根本区别,是密码学发展取得惊人成就之一[DIFF76a,DIFF76]。                                 下面首先讨论公钥密码学的基本框架,然后讨论加密/解密算法应满足的一些条件,这些条件是公钥密码体制的核心内容。

9.1.1 公钥密码体制 

对称算法依赖于一个加密密钥和一个与之相关的不同的解密密钥,这些算法具有如下重要特点。

  • 仅根据密码算法和加密密钥来确定解密密钥在计算上是不可行的。

另外,有些算法(如RSA)还有以下特点。

  • 两个密钥中的任何一个都可用来加密,另一个用来解密。

公钥密码体制有6个组成部分

  • 明文    算法的输入。它们是可读信息或数据。
  • 加密算法    加密算法对明文进行各种转换。
  • 公钥和私钥    算法的输入。在这对密钥中,一个用于加密,另一个用于解密。加密算法执行的变换依赖于公钥或私钥。
  • 密文    算法的输出。它依赖于明文和密钥,对于给定的消息,不同的密钥生成不同的密文。
  • 解密算法    该算法接收密文和相应的密钥,并且生成原始明文。

                                   

主要步骤如下:

  1. 每个用户生成一对密钥,用来加密和解密消息。
  2. 每个用户将其中的一个密钥存储在公开寄存器或其他可访问的文件中,该密钥成为公钥,另一个密钥是私有的。如图9.1(a)所示,每个用户都可拥有若干其他用户的公钥。
  3. 若Bob要发消息给Alice,则Bob用Alice的公钥对信息加密。
  4. Alice收到消息后,用其私钥解密消息。由于只有Alice知道自身的私钥,所以其他接收者均不能解密消息。

        利用这种方法,通信各方均可访问公钥,而私钥是各通信方在本地产生的,所以不必进行分发。只要用户的私钥收到保护,保持保密性,那么通信就是安全的。在任何时刻,系统都可改变其私钥,并公布相应的公钥来代替原来的公钥。

        表9.2中小结了对称加密和公钥加密的一些重要的特征。为了区分二者,一般将对称加密中使用的密钥成为秘密钥,而将公钥密码中使用的两个密钥分别成为公钥和私钥。私钥总是保密的,但是为了避免与对称密码中的密钥混淆,我们将之称为私钥而非秘密钥。

        下面利用图9.2(对照图3.2)深入分析公钥密码体制的基本要素。消息源A产生明文消息X=[X_{1},X_{2},\cdots,X_{M}],其中X的M个元素是一个有穷字母表中的字符,A要将消息X发送给B。B产生公钥PU_{b}和私钥PR_{b},其中只有B知道PR_{b},而PU_{b}则是可以公开访问的,所以A也可访问PU_{b}Y=[Y_{1},Y_{2},\cdots,Y_{N}]

 

         对作为输入的消息X和加密密钥PU_{b},A生成密文Y=[Y_{1},Y_{2},\cdots,Y_{N}]:

 Y=E(PU_{b},X)

期望的接收方因为拥有相应的私钥,所以可以进行逆变换:

X=D(PR_{b},Y)

敌手可以观察到Y访问PU_{b},但不能访问PR_{b}或X,所以敌手肯定会想方设法恢复X和/或PR_{b}。假设敌手知道加密(E)算法和解密(D)算法,如果他只关心X这一条消息,那么就会集中精力试图通过产生明文估计值\hat{X}来恢复X。但是,敌手通常还希望获得其他消息,因此会产生估计值P\hat{R}_{b}来试图恢复PR_{b}

        前面提到,两个密钥中的任何一个都可用来加密,而另一用来解密,这样就可利用公钥密码实现其他一些功能。图9.2所示的方法可提供保密性,而图9.1(b)和图9.3说明公钥密码可用于认证:                                             Y=E(PR_{a},X)X=D(PU_{a},Y)

 

         这是,A在向B发送消息之前,先用A的私钥对消息加密,B则用A的公钥对消息解密。由于是用A的私钥对消息加密的,所以只有A可以加密消息,因此加密后的整个消息就是数字签名。此外,因为只有拥有A的私钥才能生成加密后的消息,所以该消息可用于认证源和数据的完整性。

        上述方法加密的是整条消息,尽管这种方法可以验证发送方和内容的有效性,但需要大量的存储空间。在实际使用中,每个文件必须既要以明文形式保存,又要以密文形式保存,以便在发生争执的时候能够验证源及其发送的消息。解决这个问题的有效途径是,只对一个称为认证符的小数据块加密,它是该消息的函数,对该消息的任何修改必然导致认证符的变化。如果用发送方的私钥对认证符加密,那么加密的结果就可作为数字签名,它能验证源、消息和通信序列的有效性。第13章中详细讨论这种技术。

        需要强调的是,图9.1(b)和图9.3中描述的加密过程不能保证消息的保密性,也就是说,它可以防止发送的消息被修改,但不能防止搭线窃听。在基于对部分消息签名的方法中,消息的其余部分是以明文形式传输的,这种方法显然不能保证保密性。由于任何人都可用发送方的公钥对消息解密,所以即使用图9.3所示的方法对整条消息加密,也不能保证被发送消息的保密性。

        然而,如果两次使用公钥方法,那么既可提供认证功能,又可保证被发送消息的保密性(见图9.4):                Z=E(PU_{b},E(PR_{a},X)) ,           X=D(PU_{a},D(PR_{b},Z))

         这时,发送方首先用其私钥对消息加密,得到数字签名,然后用接收方的公钥加密,得到的密文只能被拥有相应私钥的接收方解密,这样就可保证消息的保密性。但是,这种方法的确定是,在每次通信时,都要执行4次而非2次复杂公钥算法。

9.1.2  公钥密码体制的应用 

        首先必须澄清公钥密码体制中容易混淆的一个问题。公钥密码体制的特点是,他使用有两个密钥的密码算法,其中的一个密钥是私有的,另一个密钥是公有的。根据不同的应用,发送方可用其私钥或接收方的公钥或同时使用二者来执行密码功能。一般来说,公钥密码体制的应用可分为三类。

  • 加密/解密   发送方用接收方的公钥对消息加密。
  • 数字签名   发送方用其私钥对消息“签名”。签名可以通过对整条消息加密或对消息的小数据块加密来生成,其中的小数据块是整块消息的函数。
  • 密钥交换   通信双方交换会话密钥。密钥交换有几种不同的方法,这些方法都使用通信一方或双方的私钥。

        有些算法适用于上述三种应用,而其他一些算法只适用于其中的一种或两种应用。表9.3中列出了本书中讨论的算法及其支持的应用。

9.1.3 公钥密码的要求 

        图9.2至图9.4所示的密码体制依赖于具有两个相关密钥的密码算法。Diffie和Hellman假定这一体制是存在的,但未证明这种算法的存在性,不过给出了这些算法应满足的条件[DIFF76b]。

  1. B产生一对密钥(公钥PU_{b},私钥PR_{b})在计算上是容易的。
  2. 已知公钥和要加密的消息M,发送方A产生相应的密文在计算上是容易的:C=E(PU_{b},M)
  3. 接收方B使用其私钥对接收的密文解密以恢复明文在计算上是容易的:M=D(PR_{b},C)=D[PR_{b},E(PU_{b},M)]
  4. 已知公钥PU_{b}时,敌手要确定私钥PR_{b}在计算上是不可行的。
  5. 已知公钥PU_{b}和密文C时,敌手要恢复明文M在计算上是不可行的。
  6. (可增加一个有用的条件,但并非所有公钥密码应用都需要满足这个条件。)两个密钥的顺序可以交换,即M=D[PU_{b},E(PR_{b},M)]=D[PR_{b},E(PU_{b},M)]

        在公钥密码学概念提出后的几十年中, 只有几个满足这些条件的算法(RSA、椭圆曲线密码学、Diffe-Hellman和DSS)为人们普遍接受,这一事实表明要满足上述条件是不容易的。

        下面首先对上述条件做进一步分析,然后详细说明为什么这些条件很难满足。事实上,要满足上述条件,就要找到一个单向陷门函数。单向函数是满足下列性质的函数,即每个函数值都存在唯一的逆,并且计算函数值是容易的,但求逆却是不可行的:

Y=f(X)    容易;X=f^{-1}(Y)   不可行

        通常,“容易”是指一个问题可以在输入长度的多项式时间内解决。也就是说,若输入长度为n位,则计算函数值的时间与n^{a}成正比,其中a是一个固定的常数,这样的算法被称为P类算法。“不可行”的定义比较模糊,一般而言,若解决一个问题所需的时间比输入规模的多项式时间增长更快,则称该问题是不可行的。例如,若输入长度是n位,计算函数的时间与2^{n}成正比,则认为是不可行的。遗憾的是,我们很难确定算法是否具有这种复杂性。另外,传统的计算复杂性注重算法的最坏情况或平均情况复杂度,但最坏情况复杂性和平均情况复杂性这种方法不适用于密码学,因为密码学要求对任何输入都不能求出函数的逆,而不是在最坏情况或平均情况下不能求出函数的逆。文献[LAI18]对计算复杂性理论做了很好的介绍。

        下面给出单向陷门函数的定义。如果计算一个函数的值很容易,并且在缺少一些附加信息时计算函数的逆时不可行的,但是已知这些附加信息时壳子啊多项式时间内计算出函数的逆,那么称这样的函数为单向陷门函数,即单向陷门函数时满足下列条件的一类不可逆函数f_{k}

若k和X已知,则容易计算Y=f_{k}(X)

若k和Y已知,则容易计算X=f^{-1}_{k}(Y)

若Y已知但k未知,则计算X=f^{-1}_{k}(Y)是不可行的

        由此可见,寻找合适的单向陷门函数是公钥密码体制应用的关键。 

 9.1.4 公钥密码分析

        类似于对称密码,公钥密码也易受穷举攻击,解决方法也是使用长密钥。但同时应考虑使用长密钥的利弊,公钥体制使用的是某种可逆的数学函数,计算函数值的复杂性可能不是密钥长度的线性函数,而是比线性函数增长更快的函数。因此,为了抗穷举攻击,密钥必须足够长;同时,为便于实现加密和解密,密钥又必须足够短。在实际应用中,现已提出的密钥长度确实能够抗穷举攻击,但是它也使得加密/解密速度变慢,所以公钥密码目前仅限于密钥管理和签名。

        针对公钥密码的另一种攻击方法是,找出一种从给定的公钥计算出私钥的方法。到目前为止,人们还未在数学上证明对某个特定公钥算法这种攻击是不可行的,所以包括已被广泛使用的RSA在内的任何算法都是值得怀疑的。密码分析的历史表明,同一个问题从某个角度看时是不可破解的,但是从另一个不同的角度看时则可能时可解的。

        最后,还有一种攻击形式是公钥体制所特有的,这种攻击本质上是穷举消息攻击。例如,假定要发送的消息是56位的DES密钥,那么敌手可用公钥对所有可能的密钥加密,并与传送的密文匹配,从而解密任何信息。因此,无论公钥体制的密钥有多长,这种攻击都可转化为对56位密钥的穷举攻击。抗这种攻击的方法是,在要发送的消息后附加一个随机数。

9.2 RSA算法

        RSA算法使用指数运算,明文以分组为单位进行加密,每个分组的二进制值均小于n,也就是说,分组的大小必须小于等于\log _{2} n+1位;在实际应用中,分组的大小是i位,其中2^{i} < n \leq 2^{i+1}。对明文分组M和密文分组C,加密和解密过程如下:

C = M^{e} \mod n,M=C^{d} \mod n = (M^{e})^{d} \mod n = M^{ed} \mod n

其中收发双方均已知n,发送方已知e,只有接收方已知d,因此公钥加密算法的公钥为PU =\left\{e,n\right\},私钥为PR=\left\{d,n \right\}。该算法用于公钥加密时,必须满足下列条件:

  1. 可以找到e、d和n,使得对所有M<n,有M^{ed} \mod n =M
  2. 对所有M<n,计算M^{e} \mod nC^{d} \mod n是相对容易的。
  3. 由e和n确定d是不可行的。

        首先讨论第一个问题,其他问题将在以后讨论。我们需要找出下列关系式:

M^{ed} \mod n =M

当e和d互为模\phi(n)的乘法逆时,上述关系式成立,其中\phi(n)为欧拉函数。在第2章已经证明,对素数p和q,有\phi(pq) =(p-1)(q-1)。e和d的关系如下:

 ed \mod \phi(n) = 1                                 (9.1)                      

 上式等价于

ed \equiv 1 \mod \phi(n) , d\equiv e^{-1} \mod \phi(n)

也就是说,d和e是模\phi(n)的乘法逆元。根据模算术的性质,仅当d和\phi(n)互素(因此e也与\phi(n)互素),即gcd(\phi(n),d) = 1时,d和e是模\phi(n)的乘法逆元。式(9.1)满足RSA要求的证明请参阅关于RSA的原始论文[RIVE78]。

下面介绍RSA算法,该算法用到了下列元素:

两个素数p、q                                                       (保密的,选定的)

n=pq                                                                     (公开的,计算得出的)

 e,满足gcd(\phi(n),d) = 11<e<\phi(n)           (公开的,选定的)

 d \equiv e ^{-1} (\mod \phi(n))                                        (保密的,计算得出的) ​​​​​​​

 私钥为{d,n},公钥为{e,n}。假定用户A公布了其公钥,用户B要发送消息M给A,那么用户B计算C=M^{e} \mod n并发送给C;在接收端,用户A计算M=C^{d} (\mod n)以解密出消息M。

图9.5归纳了RSA算法。与图9.1(a)描述的一样,Alice产生了一个公钥/私钥对,Bob用Alice的公钥加密,Alice用自己的私钥解密。图9.6所示是文献[SING99]中给出的一个例子,其密钥生成过程如下:

9.2.2 计算问题

下面讨论RSA的计算复杂性问题,它实际上包括两个方面:加密/解密和密钥生成。首先讨论加密和解密过程,然后讨论密钥生成问题。

模算术中的幂运算   在RSA中,加密和解密都需要计算某个整数模n的整数次幂,如果先求出整数的幂,在模n,那么中间结果非常大。所幸的是,如前例所示,我们可用模算术的下列性质:

[(a \mod n) \times (b \mod n)] \mod n = (a \times b) \mod n

这样,就简化为对中间结果模n,而这一计算是可行的。

        因为RSA中用到的指数很大,所以还应考虑幂运算的效率问题。为了说明如何提高效率,下面以计算x^{16}为例进行说明。如果直接计算,那么需要15次乘法:

x^{16}= x \times x\times x\times x\times x\times x\times x\times x\times x\times x\times x\times x\times x\times x\times x\times x

然而,如果重复取每个部分结果的平方得到(x^{2},x^{4},x^{8},x^{16}),那么只需要4次乘法就可算出x^{16}。又如,对于整数x和n,计算x^{11} \mod n。由于x ^{11} = x^{1+2+8}=(x)(x^{2})(x^{8}),先计算x \mod n ,x^{2} \mod n,x^{4} \mod n, x^{8} \mod n,再计算[(x \mod n) \times (x^{2} \mod n) \times (x^{8} \mod n)] \mod n

        更一般地假设要计算a^{b} \mod n,其中a、b、n是正整数。若将b表示为二进制数b_{k} b_{k-1} \cdots b_{0},则

b = \sum_{b_{i} \neq 0} 2^{i}

因此,                                               a^{b} = a^{(\sum_{b_{i} \neq 0} 2^{i})}=\prod _{b_{i} \neq 0} a^{2^{i}}

a ^{b} \mod n = [ \prod_{b_{i} \neq 0} a^{(2^{i})}] \mod n = (\prod_{b_{i} \neq 0}[a^{(2^{i})} \mod n]) \mod n

        下面讨论计算a^{b} \mod n算法,如图9.8所示。表9.4举例说明了该算法的执行过程。注意,这里的变量c不是必须的,引入它只是为了便于解释算法,c的终值即是指数值。

 

 

使用公钥进行有效运算     为了加快RSA算法在使用公钥时的运算速度,通常会选择一个特定的e,大多数情况下选择e为65537(即2^{16} +1),另外两个常用的选择是3和17。这些指数都只有2位,所以幂运算需要的乘法次数应是最少的。

        然而,指数太小时,如e=3,RSA甚至会遭受一些简单的攻击。假设有三个不同的RSA用户,他们都使用指数e=3,但他们的模数n各不相同,分别为n_{1} ,n_{2}n_{3}。现在用户A以加密方式给他们发送了相同的消息M,三个密文分别为C_{1}=M^{3} \mod n_{1}C_{2}=M^{3} \mod n_{2}C_{3}=M^{3} \mod n_{3}n_{1} ,n_{2}n_{3}很可能是两两互素的,所以运用中国剩余定理(CRT)可用算出M^{3} \mod (n_{1} n_{2} n_{3})。根据RSA算法规则,M应比模数小,所以有M^{3} < n_{1} n_{2} n_{3},从而敌手只需计算M^{3}的立方根。给每条待加密的消息M填充唯一的伪随机位串可以阻止这种攻击,详见随后的讨论。

        读者可能发现在RSA算法的定义中(见图9.5),密钥生成阶段要求用户选择的e与\phi(n)互素。因此,如果用户选择e,接着生成素数p和q,那么很可能gcd(\phi(n),e) \neq 1。这时,用户应该删除p和q的值,并且生成新的p和q值。

使用私钥进行有效运算     我们不能为了计算效率而简单地选择一个小数值d。d值太小容易遭受穷举攻击和其他形式的密码分析[WIEN90]。然而,运用中国剩余定理可以加快运算速度。我们希望计算M=C^{d} \mod n。首先定义一些中间结果:

V_{p} =C ^{d} \mod p , V_{q} = C^{d} \mod q\small M =C^{d} \mod n

根据CRT,使用(2.16)定义

X_{p} =q \times (q^{-1} \mod p) , X_{q} = p \times ( p^{-1} \mod q)

使用(2.17),由CRT得

M = (V_{p}X_{p} +V_{q}X_{q}) \mod n

        此外,可用费马定理简化V_{p}V_{q}得计算。费马定理说,若p和q互素,则a^{p-1} \equiv 1 (\mod p)。不难看出如下公式是成立的:

\tiny V_{p} =C^{d} \mod p = C ^{d \mod (p-1)} \mod p , V_{q} =C^{d} \mod q = C^{d \mod (q-1)} \mod q

式中,\small d \mod (p-1)\small d \mod (q-1)可以事先算出。与直接计算\small M=C^{d} \mod n相比,上述计算的速度约快4倍[BONE02]。​​​​​​​

密钥生成     在应用公钥密码体制之前,通信各方都须生成一对密钥,即需要完成以下工作。

  • 确定两个素数p和q。
  • 选择e或d,并计算d或e。

首先考虑p和q的选择问题。由于任何敌手都可以知道n=pq,所以为了避免敌手用穷举法求出p和q,应该从足够大的集合中选择p和q(即p和q必须是大素数)。另一方面,选择大素数的方法必须是有效的。

        目前还没有有效的方法产生任意大的素数,因此需要使用其他方法来解决这一问题。通常使用的方法是,随机挑选一个期望大小的奇数,然后测试它是否是素数。若不是,则挑选下一个随机数,直至检测到素数为止。

        各种素性测试方法因此应运而生(文献[KNUT98]中介绍了若干素性测试方法),它们几乎都是概率测试方法,也就是说,这些测试方法只能确定一个给定的整数可能是素数。尽管存在这种不确定性,但是以某种方式执行这些测试可以使得一个整数是素数的概率接近1.0。例如,第2章中介绍的Miller-Rabin算法就是非常有效且被广泛使用的素性测试方法。Miller-Rabin算法及其他许多类似算法测试一个给定的数n是否是素数的过程是执行某种计算,这种算法涉及n和一个随机选择的整数a。若n“未通过”测试,则n不是素数;若n通过测试,则n可能是素数,也可能不是素数。若对许多随机选择的不同a,n均能通过测试,则几乎可以相信n就是素数。

挑选素数的过程归纳如下。

  1. 随机选择一个奇整数n(如利用伪随机数生成器)。
  2. 随机选择一个整数a<n。
  3. 执行诸如Miller-Rabin之类的概率素数测试。若n为通过测试,则拒绝n,并转到步骤1。
  4. 若n通过测试足够多次,则接受n;否则转到步骤2。

这个过程有些烦琐,但一般不会很频繁地执行这个过程,因为只有在需要一对新密钥(PU,PR)时才会执行它。

        注意在找到一个素数之前可能有多少个整数会被拒绝。由数论中的素数定理可知,在N附近平均每隔\small \ln N个整数就有一个素数,于是在找到一个素数之前,平均要测试约\small \ln N个整数。由于每个偶数会被立即拒绝,所以实际上只需测试约\small \ln(N)/2个整数。例如,要找到一个大小约为\small 2^{200}的素数,在找到这个素数之前大约需要进行\small \ln(2^{200})/2 = 70次尝试。

        确定素数p和q后,可选择e并计算d,或者选择d并计算e来生成密钥。假定是前者,那么需要选择满足\tiny \gcd (\phi(n),e) =1的e,并计算\tiny d \equiv e^{-1}(\mod \phi(n))。所幸的是,存在求两个整数的最大公因子的算法,并且在它们的最大公因子为1时,算法还能同时求出其中一个数模另一个数的逆元,这个算法称为扩展欧几里得算法,已在第2章中讨论过。由上可知,生成密钥的过程就是要生成若干随机数,直至找到与\tiny \phi(n)互素的数为止。于是,我们再次面临这样一个问题:在找到一个可用的数,即与\tiny \phi(n)互素的数之前,要测试多少个随机数呢?容易证明,两个随机数互素的概率约为0.6,因此再找到一个恰当的数之前只需进行非常少的测试。

9.2.3 RSA的安全性

针对RSA算法的攻击可能有如下5种。

  • 穷举攻击     这种方法试图穷举所有可能的私钥。
  • 数字攻击     存在多种数学攻击方法,它们的实质都是试图分解两个素数的乘积。
  • 计时攻击     这类方法依赖于解密算法的运行时间。
  • 基于硬件故障的攻击      这种方法使用的是生成签名过程中的处理器故障。
  • 选择密文攻击     这种攻击利用的是RSA算法的性质。

        如其他密码体制那样,RSA抗穷举攻击的方法也是使用大密钥空间,所以e和d的位数越大越好,但是密钥生成过程和加密/解密过程都包含复杂的计算,因此密钥越大,系统运行速度就越慢。

本节简要介绍数学攻击和计时攻击。

因子分解问题     用数学方法攻击RSA的途径有以下三种。

  1. 将n分解为两个素因子。于是可以算出\tiny \phi(n) = (p-1)(q-1),从而确定\tiny d \equiv e^{-1} (\mod \phi(n))
  2. 直接确定\tiny \phi(n)而不先确定p和q。同样,这也可确定\tiny d \equiv e^{-1} (\mod \phi(n))
  3. 直接确定d,而不先确定\tiny \phi(n)

        针对RSA的密码分析的讨论主要集中于第一种攻击方法,即将n分解为两个素因子。由给定的n来确定\tiny \phi(n)等价于因子分解n[RIBE96]。现在已知的、从e和n确定d的算法至少与因子分解问题一样费时[KALI95]。因此,我们以因子分解的性能为基准来评价RSA的安全性。

        尽管因子分解具有大素数因子的数n仍然是一个难题,但现在已不像以前那么困难。下面来看一个著名的例子。1977年RSA的三位发明者让杂志《科学美国人》的读者对他们发表在“数学游戏”专栏[GARD77]中的密文进行解密,解得明文者可获得100美金奖金,他们预言需要\tiny 4 \times 10^{16}年才能解得明文。但是,一个研究小组利用因特网只花了8个月的时间,于1994年4月解决了这个问题[LEUT94]。他们所用的公钥大小(n的长度)是129位十进制数,即约428位二级制。类似于针对DES算法的处理,RSA实验室同时发布了用位数为100、110、120等的密钥加密的密文供有兴趣者解密。最近被解密的是RSA-768,其密钥长度为232个十进制数字或768位。

        注意这些连续分解挑战所用的因子分解方法。在20世纪90年代中期以前,人们一直用二次筛选法来进行因子分解的,对RSA-130的攻击使用了被称为一般数域筛法(GNFS)的新算法,该算法能够因子分解比RSA-129更大的数,但计算开销仅是二次筛法的20%。

        计算能力的不断增强和因子分解算法的不断改进,给大密钥的使用造成了威胁。我们已经看到,更换一种算法可以使得速度明显加快。我们期望GNFS还能进一步改进,以便设计出更好的算法。事实上,对某种特殊形式的数,用特殊数域筛法(SNFS)进行因子分解比用一般数域筛法要快得多。我们相信算法会有突破,使普通因子分解的性能在时间上约与SNFS一样,甚至比SNFS更快[ODLY95]。因此,我们在选择RSA的密钥大小时应谨慎。分解768位整数的团队[KLEI10]观察发现:分解一个RSA-1024约比RSA-768难1000倍,分解一个RSA-768约比RSA-512难几千倍。根据成功分解512位到768位的时间跨度,通过学术界的努力,我们完全有理由认为在今后十年内攻破RSA-1024。因此,为谨慎起见,该团队建议在未来几年内(从2010年算起)应该逐渐淘汰RSA-1024。

许多政府机构也发布了RSA密钥尺寸选取的推荐建议。

  • NIST SP 800-131A(Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths, 2015年11月)建议密钥长度为2048位或更长。
  • 欧盟网络信息安全局在Algorithms,Key Size and Parameters Report - 2014中建议密钥长度为3072位或更长。
  • 加拿大政府通信安全机构在Cryptographic Algorithms for UNCLASSFIED,PROTECTED A,and PROTECTED B Information(2016年8月)中建议密钥长度至少为2048位,到2030年扩展到至少3072位。

        除指定n的大小外,研究人员还提出了其他一些限制条件。为了防止很容易地分解n,RSA算法的发明者建议p和q还应满足下列限制条件。

  1. p和q的长度应只相差几位。这样,对1024位(309个十进制位)密钥而言,p和q就都应在区间\tiny 10^{75} \sim 10^{100}内。
  2. p-1和q-1都应有一个大的素因子。
  3. \tiny \gcd(p-1,q-1)应该较小。

另外,已证明,若\tiny e<n\tiny d<n^{1/4},则d很容易被确定[WIEN90]。

计时攻击     如果想知道评价密码算法的安全性有多难,那么计时攻击的出现就是最好的例子。密码学顾问Paul Kocher已经证明,敌手可通过记录计算机解密消息所用的时间来确定私钥[KOCH96KALI96b]。计时攻击不仅可以攻击RSA,而且可以攻击其他公钥密码系统,由于这种攻击的完全不可预知性及它仅依赖于密文,所以计时攻击的威胁很大。

        计时攻击类似于窃贼通过观察他人转动保险柜拨号盘的时间长短来猜测密码,我们可通过图9.8中模幂算法来说明这种攻击,但这种攻击可以攻击任何运行时间不固定的算法。在图9.8所示的算法中,模幂运算是逐位实现的,每次迭代都执行一次模乘运算,该位为1时还需在执行一次模乘运算。

        如Kocher在其论文中指出的那样,在下述极端情况下,我们很容易理解计时攻击的含义。假定在模幂算法中,模乘函数的执行时间只在几种情形下的执行时间比整个模幂运算的平均执行时间长得多,但在大多情形下得执行速度相当快。计时攻击是从最左(最高有效)位\tiny b_{k}开始,逐位地进行的。假设敌手已知前面的j位(为了得到整个指数,敌手可从j=0开始重复攻击,直至已知整个指数为止),则对给定的密文,敌手可以完成for循环的前j次迭代,其后的操作依赖于未知的指数位。若该位为1,则执行\tiny d \leftarrow (d \times a) \mod n。对有些a和d值,模乘运算的执行的速度非常慢,并且敌手知道是哪些值。位是1时,对这些值进行迭代运算的速度很慢,若敌手观察到解密算法的执行总是很慢,则可认为该位是1;若敌手多次观察到整个算法的执行都很快,则可认为该位是0.

        在实际中,模幂运算的实现并无这么大的时间差异,导致一次迭代的时间超过整个算法的平均执行时间,但存在足够大的差异时会使得计时攻击切实可行,详见文献[KOCH96]。

尽管计时攻击会造成严重威胁,但是有一些简单可行的解决方法,包括:

  • 不变的幂运算时间     保证所有的幂运算在返回结果前执行的时间都相同。这种方法虽然很简单,但会降低算法的性能。
  • 随机延时     在求幂算法中加入随机延时来迷惑计时攻击,可以提高性能。Kocher认为,若不加入足够的噪声,则敌手可通过收集额外的观察数据来抵消随机延时,进而导致攻击成功。
  • 隐蔽     在执行幂运算前先将密文乘以一个随机数。这个过程可使敌手不知道计算机正在处理的是密文的哪些位,因此可以防止敌手逐位地进行分析,这种分析正式计时攻击的本质。

RSA数据安全公司在其产品中使用了隐蔽方法。使用私钥实现操作\tiny M=C^{d} \mod n的过程如下:

  1. 产生0至n-1之间的一个秘密随机数r。
  2. 计算\tiny C^{'}=C(r^{e}) \mod n,其中e是公开的指数。
  3. 像普通的RSA运算那样,计算\tiny M'=(C')^{d} \mod n
  4. 计算\tiny M=M'r^{-1} \mod n,其中\tiny r^{-1}\tiny r \mod n的乘法逆元,关于乘法逆元的讨论见第2章。根据\tiny r^{ed} \mod n = r \mod n,可以证明结论是正确的。

RSA数据安全公司声称使用隐蔽方法后,运算性能降低了2%~10%。

        基于故障的攻击      还有另一种攻击RSA的非传统方法,详见文献[PELL10]。这种方法对正在生成签名的处理器进行攻击。这种攻击通过降低处理器的输入电功率来在签名计算中引入故障。故障导致软件生成无效签名,然后敌手通过分析就可恢复私钥。作者展示了如何完成这样的分析工作,并用具体的实例进行了说明,即利用商业通用微处理器提取了1024位RSA私钥约100小时。

        这种攻击算法通过引入单个位错误来观察结果,详见文献[PELL10]及其他基于硬件故障来攻击RSA的方法。这种攻击值得关注,但还未对RSA构成严重威胁,原因是这种攻击需要敌手物理接触目标及其,并能直接控制处理器的输入功率。虽然对于大多数硬件来说,控制输入功率要比控制交流电源更容易,但是这也涉及芯片上的供电控制硬件。

        选择密文攻击和最佳非对称加密填充     基本的RSA算法容易收到选择密文攻击(CCA)。进行选择密文攻击时,敌手选择一些密文并得到相应得明文,这些明文是用目标的私钥解密获得的。因此,敌手可以选择一条明文,运用目标的公钥加密,然后用目标的私钥解密得到明文。显然,这么做并未向敌手提供任何新信息。然而,敌手能够利用RSA的性质,选择数据分组并使用目标的私钥处理时,产生密码分析所需的信息。

        对RSA进行选择密文攻击的一个简单例子利用了RSA的如下性质:

\tiny E(PU,M_{1}) \times E(PU,M_{2}) =E (PU,[M_{1} \times M_{2}])                             (9.2)

利用CCA,可按照如下方式解密\tiny C=M^{e} \mod n

  1. 计算\tiny X=(C\times 2^{e}) \mod n
  2. 将X作为选择明文提交,并收到\tiny Y=X^{d} \mod n

由于

\tiny X=(C \mod n)\times (2^{e} \mod n) =(M^{e} \mod n) \times (2^{e} \mod n)=(2M)^{e} \mod n

所以\tiny Y=(2M) \mod n。由此,可以得到M。为了防止这种简单的攻击,基于RSA的使用密码体制在加密前都会对明文进行随机填充。这会使得密文随机化,即使得式(9.2)不再成立。然而,复杂一些的CCA攻击仍然是可能的,简单的随机填充已被证明不足以提高安全性。为了防止这种攻击,RSA安全公司(RSA的主要厂商,也是RSA专利的持有人)推荐使用一种称为最优非对称加密填充(Optimal Asymmetric Encryption Padding,OAEP)的程序对明文进行修改。对安全威胁和OAEP的全面讨论超出了本书的范围,文献[POIN02]中有一些介绍,文献[BELL94a]中做了彻底的分析。下面简要介绍OAEP。

        图9.9描述了OAEP加密算法。第一步,填充待加密的消息M。可选参数集P作为哈希函数\tiny H的输入,输出用0加以填充以获得期望的长度,从而放入整个数据块DB。接着,随机选择一个种子,并作为一个哈希函数的输入,该哈希函数称为掩码生成函数(MGF),输出哈希值和DB按位异或,生成掩码DB(maskedDB)。maskedDB反过来又作为MGF的输入生成一个哈希值,哈希值和种子进行异或,生成掩码种子。掩码种子和掩码DB连接后构成编码后的消息EM。注意,EM包括填充后的消息,该消息由种子掩蔽,而种子又由maskedDB掩蔽。最后用RSA对整个EM加密。

 图9.9  使用最优非对称加密填充(OAEP)加密

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值