水木看山
首发于水木看山
数学中的战争,战争中的数学——漫谈密码(3)

数学中的战争,战争中的数学——漫谈密码(3)

作者:@何钦尧

距离密码学系列的上一篇文章发出来到现在已经有一段时间了,大家是不是以为说好的本文的作者跑路了呢?好吧其实是因为之前的一段时间本文的作者一直在忙于期末考试和大作业,所以一直没有动静 TAT 。好吧,那么现在我们来进入密码学系列的第三篇,也是最后一篇。本篇主要介绍非对称密码体系。

非对称密码体系又称公钥密码体系。他和之前我们讲的对称密码体系完全是两种不同的套路。公钥密码体系的提出可以说得上是密码学历史上最伟大的一次革命(当然了,我们认为也只有这一次能称得上是革命)。现代各种安全体系中的密钥交换,数字签名,用户认证等都基于公钥密码体系。

那么现在就让我来带着大家领略公钥密码学的精彩。本篇在原理介绍部分将会涉及到一些数论方面的知识,我会尽可能的将其写的足够的易懂。当然如果实在是对此uncomfortable,不妨直接跳过原理部分,无伤大雅。

一、公钥密码体系概览

在之前介绍的对称密码体系中,我们知道,对于明文的加密和密文的解密使用的都是相同的密钥。正是因为这个原因我们把它叫做对称密码体系。比如Alice要给Bob发送一条消息,他会使用双方提前协商好的密钥对消息进行加密。Bob收到消息后用同样的密钥进行解密。这时候,加密和解密互为逆运算。由于密钥是只在Alice和Bob之间共享的,第三方不能知道密钥,因此即使有第三方截取了消息(在互联网上传播的数据被截取是一件很容易的事情),也不能恢复出原文。

而公钥密码体系,在加密和解密的时候使用两个不同的密钥,使用一个密钥加密的数据只能用另一个密钥来解密。我们称这样的两个密钥为一个公私密钥对,其中公钥可以公开,而私钥需要被妥善的保管避免泄露。

我们再次考虑Alice要给Bob发送一条消息,Alice需要使用Bob的公钥对消息进行加密。因为公钥总是公开的,所以任何人都可以获取Bob的公钥并给他发送消息。Bob收到消息之后使用自己的私钥进行解密。因为其他人都不知道Bob的私钥,所以都无法读取消息的原文。

于是,公钥加密的安全性就取决于以下几点:

  1. 两个密钥之一是保密的
  2. 知道一个密钥和若干密文消息是不能确定另一密钥的(计算上不可行)

为了达到这样的性质,公钥加密算法在设计的时候通常利用了一些数学上难解的问题,例如:

  • 大整数的质因数分解
  • 大整数的离散对数
  • 椭圆曲线上的离散对数

(以上列出几个名词仅用于装逼)


当然了,公钥密码体系的作用远远不止有加密这么简单。这里我先卖个关子,我们先来以著名的RSA算法为例,介绍公钥加密的原理。

二、RSA加密的原理

(前方出现大量数学公式,非战斗人员请尽快撤离,跳过到下一部分)

在介绍原理之前我们先来复习一些数论的知识。从我们都很熟悉的带余整数除法开始。对于任意正整数n和任意非负整数a,我们用a除以n,得到商q和余数r,他们可以写为:

a=qn+r, 0\le r < n, q=\lfloor a/n \rfloor

其中\lfloor x \rfloor表示小于等于x的最大整数。

在这个基础之上我们定义模运算,对于上面的例子,也就是

r=a \bmod n

如果a和b模n的余数相同,我们就说a和b是同余的,写作

a\equiv b \pmod n

如果a\equiv 0 \pmod n,也就是a除以n的余数为0,我们说n整除a,写作n|a

如果b|a,我们称b是a的一个因子。定义gcd(a,b)表示a和b的最大公因子,也就是同时能整除a和b的最大的整数。如果两个数的最大公因子是1,我们称这两个数互素。显然1与任何整数都互素。

如果对于一个整数p>1,仅有\pm 1\pm p能够整除它,我们就说p是一个素数。之后的讨论都会主要围绕素数来进行。

对于任意一个整数a>1,都可以唯一的分解为素数的乘积的形式,即

a=p_1^{a_1}\times p_2^{a_2}\times ...\times p_t^{a_t}

这个就是算数基本定理。此处略去不证,读者可以在任何一本数论的教材中找到他的证明。

有了以上的铺垫之后我们来引入两个非常重要而且大名鼎鼎的定理(为了节省空间我这里就都不给出证明了,感兴趣的读者不妨翻阅Wikipedia,有惊喜)。

费马定理(费马小定理)

若p是素数,a是正整数且不能被p整除,则

a^{p-1}\equiv 1 \pmod p

另一种形式为,若p是素数且a是任意正整数,则

a^p\equiv a \pmod p

欧拉定理

先引入一个非常重要的概念叫做欧拉函数\phi (n),它指的是小于n且与n互素的正整数的个数。很显然的(真的很显然吗),对于一个素数p,\phi (p)=p-1。这很容易理解,因为从1到p-1的整数都与p互素。

再更进一步的,对于两个素数p,q,n=p\times q,那么\phi(n)=(p-1)\times (q-1)。不妨这里简单证明如下。

考虑集合\{1,2,...pq-1\},于n互素且小于n的整数只能在这个集合中。其中,p和q的整数倍一定不和n互素(和n的最大公因子为p或者q),这些数包含\{p, 2p, 3p...,(q-1)p \}\{q, 2q,...,(p-1)q\}。这两个集合肯定是没有重合的元素的,否则,若mp=nq,也就是p|nq。而p和q都是素数,只能是p|n。而我们知道n<p,于是这是不可能的。

所以\phi(n)=(pq-1)-(p-1)-(q-1)=(p-1)\times (q-1)

那么欧拉定理表示为,对于任意互素的a和n,有

a^{\phi(n)}\equiv 1 \pmod n

另一种形式为,对于任意a和n(不要求互素),有

a^{\phi(n)+1}\equiv a \pmod n

于是,欧拉定理实际上是费马定理的一种推广。

有了这些基础铺垫之后我们就可以开始介绍RSA加密算法的原理啦(笔者写到这里已经累死了)。

RSA加密算法将明文,密文,密钥等当做一个超大的整数来看待。加密之前需要明文分段编码为超大的整数(一般为1024或2048个二进制位)。以下我们为了简单就先无视怎么编码这个过程,仅用整数的运算来分析RSA的加密过程。这样也已经能够清楚的认识到基本的原理了。

RSA首先需要生成公私钥对,我们就先从密钥的生成讲起。

  1. 首先让我们选择两个大素数p和q
  2. 计算n=p\times q,可以知道知道\phi(n)=(p-1)\times (q-1)
  3. 选择一个整数e,使得gcd(e,\phi(n))=11<e<\phi(n)
  4. 计算d,d<\phi(n),使得ed\equiv 1 \pmod{\phi(n)}

以上的各种数的选择都可以使用随机生成,然后在进行素数的检测这样来进行。第4步中的d可以使用扩展欧几里得算法很快的求解。

然后丢弃p和q不再保留(这是安全性的保证)。产生的公钥为{e, n},私钥为{d, n}。

对于一条消息M的加密,我们计算(需要保证M<n

C=M^e \bmod n

C就是加密后的密文。

解密的时候我们计算

C^d \bmod n=M^{ed}\bmod n=M

上面等式的最后一步由欧拉定理保证。由于ed\equiv 1 \pmod{\phi(n)},于是ed=1+k\phi(n)。那么

M^{ed}=M^{1+k\phi(n)}=M(M^{\phi(n)})^k

而欧拉定理说明M^{\phi(n)}\equiv 1 \pmod n,所以M^{ed}\equiv M \pmod n。在限制的M<n的条件下,就有M^{ed} \bmod n = M。于是我们就从密文解密出了明文。

而RSA加密的安全性的保证在于对于大整数进行质因数分解的困难性。已知了n,无法恢复出p和q。进而就无法从公钥恢复出私钥。为了保证这种分解的困难性,需要选择足够大的整数。实际的RSA加密标准中使用的整数都长达1024到2048个二进制位。

三、公钥加密体系的实际应用

好了前面讲了很多严肃的东西,接下来开始轻松一点的模式。

我们说了,公钥加密(非对称加密)和对称加密是两种不同的模式。那么既然已经有了对称加密方式,非对称的方式又有什么特别的地方使得其能够广泛的应用呢?

我们知道,使用对称密码的时候,每需要进行通信的两个实体都需要共享他们的密钥。假设总共有N个实体,他们之间要相互通信所需要的密钥的总量就是

\frac{N(N-1)}{2}

在N比较大(实际中我们也可以想象这有多大)的时候,这个密钥的总量是一个非常夸张的数字。这给密钥的保存,分发都带来了很大的问题。

而在非对称密码当中,任何一方只要知道对方的公钥,就可以发消息给他进行通信。所以N个实体,只需要N个公私钥对就可以满足互相通信的需要了。

而且,公钥体系在其他的方面有更多的应用。我们逐个的来讲解。

数字签名

最开始的时候我们说到,Alice想要给Bob发送消息,只需要使用Bob的公钥进行加密即可。Bob能解密这条消息,也能确定这条消息不能被发送者之外的其他人知道,但是他却不能确定发送者的身份是不是就是Alice,因为任何一个人都可以使用Bob的公钥给其发送消息。

这还了得。这种情况也就意味着任何一个人都可以伪造Alice给Bob发送消息,或者是Alice发送给Bob一条消息后可以否认自己发过该消息!

这种问题在对称密码里面是不存在的,因为只有Alice和Bob能够知道通信的密钥,因此Bob如果能正常的解密消息,就能确认消息一定是来自Alice的。

在公钥加密里面我们同样也有一种手段来解决问题。试想Alice要给Bob发送一条消息,如果Alice使用自己的私钥对消息进行加密,Bob接收到消息后使用Alice的公钥对消息进行解密。因为Alice的私钥只有他自己知道,因此如果Bob能够成功解密消息的话,就一定能确认消息就是来自于Alice的!


不过这里带来的问题就是,任何一个人都可以窃听该消息并用Alice的公钥进行解密。所以这种方案满足了认证的需求,却没有满足加密的要求。

当然了聪明的读者一定想到了,如果既要认证又要加密的话,Alice可以先用自己的私钥加密消息,然后再用Bob的公钥加密一遍就可以了。Bob接收到消息之后先用自己的私钥解密,再用Alice的公钥解密即可。

讲到这里我们就涉及到了一个重要的概念叫做数字签名。当密码被应用在商业和个人目的中的时候,如同重要的文件需要手写签名一样,重要的电子文件也需要签名。密码学里面我们就做出这样的考虑,能否设计一种方法,能够确保数字签名一定是出自某个特定的人,并且双方都对此没有异议呢?(也就是这个签名的结果不能被任何一方否认)

一般来说,数字签名必须要满足:

  1. 能够验证签名者,签名日期和时间
  2. 能够验证签名内容
  3. 能由第三方进行仲裁

(背景音:说人话)

好吧其实也就是接受方收到这条消息之后,可以确认这条消息一定是发送方发送的,且消息的内容没有被篡改过。发送方也不能抵赖这一个事实。

上面说到的将整个消息用发送方的私钥进行加密是一种可能的数字签名手段。但是由于公钥加密一般来说的运算量都太大,对整个消息完整的进行加密太费时。而为了解决这个问题,先让我们引入Hash函数的概念。

有些时候我们需要快速的判断两个消息(文档)的内容是否相同,但是如果文件过大的话,比对两个文档的每一个字节耗时太多。数字签名的场景下,加密整个文档耗时过大。这种情况下,我们使用一种折中,对于整个文档计算一个定长的Hash值,用来代表文件的内容。这种Hash值由于长度是定的,所以一定会存在重复(即两个相同的文档对应了一个Hash值)。但是密码学中的构造方法保证,很难通过一个Hash值来反推出一个文档来。这样就可以让我们放心的使用Hash来作为文档完整性的检验。

因此在数字签名中一般采用的手段是,Hash函数计算出原消息的一个Hash值,然后对这个Hash值用发送方的私钥进行加密,并将加密后的消息拼接在原本的消息之后作为一个签名,发送出去(发送中仍然可以使用其他的加密手段来保证通信的保密性)。接收方收到消息之后,可以同样的计算消息的Hash值,然后和签名解密出来的值进行比对,如果相同,就完成了这个对发送方的认证。

实际的数字签名方案当然要复杂的多,也采用了很多除了RSA以外的公钥算法。不过上面这样的简化的讲法,依然是对理解整个的框架是有益的。

证书体系

在讲完上面的各种公钥加密和数字签名之后,相信大家都一定知道了,对于公钥密码体系来说,公私钥是非常重要的。首先私钥必须要被妥善的保管而不能被窃取,否则就会威胁该个体的通信安全。而对于公钥,我们也必须要有能力确认,某个公钥确实是属于某个人的。否则可以有一个第三方声称自己是Alice并公布自己的公钥,而在Alice发现这一点之前,冒充者都可以获取本应发送给Alice的消息。要解决这个问题,我们需要研究公钥如何分发。

我们可以设想有一个可信的第三方来保存所有人的公钥,用户在需要的时候向其获取某个用户的公钥。这个第三方有义务去认证在这里存放公钥的每个人的身份。但是这样就导致这个中心化的证书存储成为了一个瓶颈,如果被攻击者攻破,就可以修改任何人的公钥达到伪造的目的。而现在广泛使用的证书体系则是对于这个问题的一种解决。

在这种体系当中,需要一个可信的第三方,我们叫做CA(certificate authority),但是不需要中心化的证书存储。Alice需要将自己的公钥交给CA,CA在对Alice本人认证之后,会使用CA自己的私钥对Alice的公钥进行签名,并将Alice的公钥和签名合在一起作为证书。之后Alice就可以将证书发送给任何需要和自己通信的实体,比如Bob。

Bob收到证书之后,使用CA的公钥对签名进行解密,就可以判断该证书是否是由CA签发的。如果能够确认证书是由CA签发的,Bob就可以确认这个公钥一定是属于Alice的而不是冒充的(因为CA需要验证身份)。

在实际的使用中不会只有一个CA,而是很多个CA组成一个树状的结构,处于最顶端的叫做根CA。二级或者三级的CA也可以颁发证书,而他们自己的公钥是由上一级的CA签发的证书。这样我们就可以一级一级的向上验证证书的合法性。通常,处于最顶端的根CA的证书(也就是公钥)是被广泛接受,并内置在操作系统,浏览器等当中的。我们通常在系统里遇到的『受信赖的根证书颁发机构』,就是这种东西。

好了,虽然公钥密码学还有很多有意思的东西,但是贪大求全不如做小而精,而且篇幅太长实在难读。本篇仅在于介绍一些基本的概念,为大家入个门。如果能激起一些同学深入探索密码学的兴趣的话,那便是足够了。

好了,水木看山密码学部分的三篇到这里就全部结束了。请大家期待水木看山未来更多精彩的作品~

编辑于 2016-07-15

文章被以下专栏收录