from:2017 CCF计算机课程改革导教班. 陈道蓄
16
公钥密码
有谁没想过要发一封密信呢?就连凯撒也这么做过。据传说他把信中每个字母按字母表顺序后移三个位置;这样A就写成D,而B就写成E,等等。最后的X,Y,Z就变成了A,B,C。
如果你知道这个过程,当然很容易对截获的密件解码。你能猜出来下面的报文是什么吗?
凯撒的密码
ZH ORYH FUBSWRJUDSKB
这里加密的报文应该是什么?
将这个思想推广一点,我们选一个整数k(k<26)。待加密的报文(称为明文)中每个字母按照字母表顺序向右移k个位置。这样我们就得到了“密文”,也就是密信。加密的方法就是在字母表中向右移动,如果遇到结尾便绕回开头。这里k称为(密)钥。解码时只不过是将每个字母向左移动k个位置。
不管是谁,只要知道密钥就既能加密也能解密。因此这称为对称密码系统。第15章中介绍的一次性加密方法就属于对称密码系统。
这就意味着,能对报文加密的人不仅能对此密文解码,也能对其它采用同样方法加密的密文解码。
另一方面,这个方法的缺陷在于正常的收件人不仅要知道所用加密方法,还必须知道使用的密钥才能对密文解码。如果通信双方距离遥远该如何交换密钥呢?
下一节中我们将会知道加密与解密不一定非得使用相同的密钥。两个密钥不同甚至还有好处。我们可以分别设置两个密钥,一个可以公开,另一个保密。基于这种思想的方法称为非对称密码系统。
公钥
初次看到这个标题可能让人觉得没有意义,既然是用于加密怎么能公开,它该如何工作呢?对于对称密码系统,一旦密钥被公开就没有任何秘密可言了。因为在对称加密系统中知道加密用的密钥就能得出解密的密钥。
不过在仔细想想,我们可以公开加密的密钥,但对解码用的密钥(不同于加密密钥)保密。我们只需确保任何人无法从加密密钥推导出解码密钥。
这样的系统很有吸引力,因为谁都可以给你发密件,但只有你才能解码。
实际上建立这样的系统并不复杂。你不妨假设你有几千个挂锁,用同一个钥匙开锁(注意:这个要求不同寻常,一般是一把锁配几个钥匙)。你可以将锁分发给朋友们,甚至可以把锁放在学校办公室或者图书馆。但只有你手上有钥匙。
现在,任何人都可以将给你个人的信放在一个盒子中。盒子加锁并不需要钥匙,他锁上即可。一旦锁上,只有你才能看这封信,因为只有你有打开盒子的钥匙。你的朋友甚至可以请一个嘴最不牢靠的熟人将盒子带给你。
这个例子说明这样的系统是有可能的。不过还是有个缺点。这个例子代价太大,我们得买很多锁,还得将它们散发出去。这要花很多钱,也需要费很大工夫。
如果提供公钥的系统不必用这么多锁,那就好多了。使用第14章介绍的单向函数,理论上可以做到这一点。粗略地说,单向函数正方向,即计算函数值很容易;但其反方向,即由函数值计算原来自变量的值很困难。
我们希望的是:加密很容易(每个人都能给我们发信息),但解码很困难。当然,正确的收件人应该很容易解码。你需要给自己留下某种后面。第14章中讨论的逆向电话号码簿是可选的办法。不过本章内我们会介绍另一种方法。
受限代数
实用的公钥密码系统采用高等代数方法,利用计算机加密与解码。我们不打算在这里讨论高等代数,只是用一种受限的代数来描述公钥系统的原理。
在受限代数中只有整数的加、减和乘。在这样的系统中没有人能做除法运算。你可以回想一下小学里刚学了乘法,还没学除法时的情景。
基于受限代数,我们看看Bob怎样给Alice发信。作为示例,假设信件就是一个数字。
整个过程分三部分,首先是生成公钥和私钥,接下来是加密,最后是解码。
创建密钥
我们需要两个密钥,一个保密,另一个公开。信件是Bob发给Alice的,所以Alice需要一个私钥用于解码。为了创建私钥,Alice想出两个数并计算它们的乘积。这两个数中的第一个是私钥,另一个乘数以及乘积即为公钥。换句话说,私钥是一个数(乘数之一),公钥是两个数(一个乘数以及乘积)。
公钥和私钥
P 私钥(保密的乘数)
11 公开的乘数
143 公开的乘积
其实你很容易算出私钥,因为你会做除法。私钥p=143/11=13。但在受限代数中,私钥是保密的。
在学校的公告牌上Alice贴了一张如下的告示,任何人都能看到。但没有人能做除法,所以私钥只有Alice自己知道。
加密
Bob打算给Alice发信,他也看了这个告示。假设Bob打算告诉Alice在他家举办的晚会的日期12月5日。由于事前已商定在12月,所以信的内容就是数字5。
Bob按如下方法加密。他拥有的信息是信的内容5以及Alice的公钥11,143。Bob想出第4各数,称为发送密字。他用发送密字计算加密的数据。数据包括两部分,一是密文,即对内容5加密的部分,另一部分是解密办伴字。
Bob用发送密字和Alice公开的乘积相乘,再将报文内容加到相乘的结果上就得到加密的报文。假设Bob选择的发送密字是3,加密的报文则是5+3×143=434。434可以公开,但3必须保密,否则任何人都能算出原来的报文:434-3×143=5。
既然我们已经知道了发送密字,就让Bob另选一个,假设是s,值不公开。Bob计算密文:
计算密文
5 + s×143 = 1292
1292是公开的,但s保密。
只有Bob知道发送密字,所以没人能读出密文。但Alice怎么能知道信的内容呢?为了让Alice能对1292解码,Bob提供了解码伴字,就是发送密字和Alice公开的那个乘数的乘积。
计算解码伴字
s×11 = 99
Bob在学校的公告栏上贴出如下告示:
任何人都能看到公告牌上的告示,所以下列数字对任何人是公开的:
加密与发布告示之后公开的数字
11 Alice公钥中的乘数
143 Alice公钥中的乘积 11×p
1292 加密的报文 5 + s×143
99 解码伴字 s×11
即使知道Bob的计算过程,在没有除法的条件下,发送密字s和密钥p也不可能被算出来。 不知道发送密字也就不可能读出Bob的报文。
解码
现在Alice要对Bob发来的加密的报文解码了。像其他人一样Alice也不能做除法。不过Alice知道自己的密钥。我们再仔细看看加密过程:
对报文加密
1292 报文 + 发送密字×143
= 报文 + 发送密字×公钥的乘积部分
= 报文 + 发送密字×公钥的乘数部分×私钥
= 报文 + 解码伴字×私钥
Alice通过下面所示的计算即可得到报文内容:
解码
1292 - 99×(私钥p) = 5
如你所见,Alice的计算并不需要除法。
窃听者
在间谍电影中我们看到过间谍窃听电话或其它通信。通常用安全信道防止窃听。但我们怎么能确信信道是安全的呢?
在Bob给Alice发信的小例子中根本不需要安全信道。所有通信都是在学校公告牌上进行的。窃听者不能做除法也就无法对报文解码。主要Bob和Alice各自不让自己的秘密数字暴露,他们之间的通信就可保私密。况且这个方法并不要求Bob和Alice碰过头。比起第15章中的一次性加密方法,这是公钥系统最主要的优点。
没有受限代数
上述系统的安全完全基于任何人做不了除法。可我们大家在学习都学过如何除。
如果你仔细读后果本书前面的章节,你能发现除法可以执行的很快(如第1章)。任给两个自然数a,b,要计算a/b,只要在0和a之间猜一个候选的商c,然后我们计算b×c是否真等于a。如果结果大于a,正确的结果必然比c小;若结果大于a,则相反。基于同样想法,我们可以始终在需要考虑的区间内取中间值为候选商,很快就能得到结果(就相当于做二分搜索)。
这个方法基于一个事实:b增大时a/b会减小。若非如此,二分搜索就不能用了。
不过假如我们采用的是剩余计算,二分搜索也无效。后面我们将介绍模计算的数学原理。除法同样可以有效地进行模算术运算,所以我们必须用其它方法替代除法。
ElGamal方法
数学中除了基本算术运算还有很多其它运算。我们可以聪明地选择容易执行的其它运算来代替基本算术系统中的加、减、乘、除。我们选择的运算如下:
l 用模乘代替加法。模乘是对特定值取余数的乘法,参见第17章中模乘用于共享秘密的算法。
l 用模除代替减法。
l 用模乘幂代替乘法。
l 用模对数代替除法。
由此得到的方法称为ElGamal密码系统。迄今为止,还没有人知道如何对很大的数(十进制千位以上)有效地计算模对数(又称为离散对数)。所有已知算法在最快的计算机上也得算好几个世纪。就算在将来某个时刻,不要私钥也能解码了,可晚会的时间早已过了。
模乘和模乘幂
在讨论如果有效计算模乘幂之前,我们先花一点时间看看模乘。
早模算术中所有计算都要用一个素数p,也就是除1及其自身外没有其它整除因子的自然数。最小的几个素数是2,3,5,7,11,13,17,19,…。
素数p称为计算的“模数”。a和b模乘的结果记为(a×b) mod p,定义为a和b乘积除以p的余数。例如5×8=40,除以17商为2(在模计算中商被忽略),余数为6。因此(5×8) mod 17 = 6。
现在我们仔细看看模乘幂。模乘幂 (ab )mod p定义为b个a模乘,即每次相乘均对p取余数。
(39) mod 17=14,其计算过程如下:
计算(39) mod 17
39 mod 17 = (3×3×3×3×3×3×3×3×3) mod 17 = ((38 mod 17)×3) mod 17
38 mod 17 = ((34 mod 17)×(34 mod 17)) mod 17
34 mod 17 = ((32 mod 17)×(32 mod 17)) mod 17
32 mod 17 = (3×3) mod 17 = 9
34 mod 17 = (9×9) mod 17 = 13
39 mod 17 = (13×13×3) mod 17 = 14
这个例子表明只要巧妙地利用乘法中间结果,计算(39) mod 17并不需要执行8次乘法。下面的过程就利用了这一思想:
计算(ab) mod p
1 如果b=0,结果为1。
2 如果b=1,结果为a。
3 如果b是奇数,结果为((ab-1 mod p) ×a) mod p。
4 这里只需要考虑b是偶数,计算如下:
5 h = (ab/2) mod p。
6 结果为 (h×h) mod p。
在计算(ab) mod p时我们用到同样形式的其它值(cd) mod p,其中的c,d总是小于a,b。因此这个过程最后总会终止,我们可以将其写为如下的递归算法:
计算(ab) mod p的递归算法
1 ExpMod (a,b,p)
2 If b=0 then return 1.
3 If b=1 then return a.
4 If b是奇数 then
5 begin
6 h=ExpMod(a,b-1,p)
7 return (h×a) mod p
8 end
9 h=ExpMod(a,b/2,p)
10 return (h×h) mod p
在下表中给出了对于偶数b,2b mod 59的值。与一般乘法不同,表中的值并不随着指数增大而增大,这是由于中间结果取模的原因。
2b mod 59的值 (b为偶数)
模对数问题进行与模乘幂相反的运算,例如对于数x(比如x=42),要找数b,满足2b=42。当然,如果模数为59,我们总可以通过尝试所有可能的指数找到b。但如果数很大,那就费工夫了。不过即使对于很大的数,模乘幂还是能计算的,因为在前面的算法中,数会很快减小。
如果指数是100位十进数,在模对数中至少有100万个可能的解需要考虑。反之,计算指数为100位十进数的乘幂只需要执行65次模乘法。这表明模对数与模乘幂之间复杂度巨大的差异。今天,ElGamal方法中用的数大到千位以上,复杂度差异就更大了。尝试所有可能的解是绝对不可能的。其实,我们现在不知道有任何算法,对于这么大的p能够在合理时间之内解决模对数问题。
ElGamal密码系统
现在我们可以来介绍ElGamal密码系统了。其实它就是对于我们前面讨论的基于受限代数的系统的简单改造。
上述方法中用到乘法的结合律:(a×b)×c = a×(b×c)。在ElGamal密码系统中用到一个类似的运算法则:(ga×b)c = g(a×b)×c = ga×(b×c) = (ga)b×c。这里只给出法则,略去证明。
还有一个重要的数学性质:1和p-1之间的任何数均能表示为gx mod p;换句话说,对1到p-1之间的任何数i,一定存在某个数j,满足i=gj mod p。这里,g称为生成元素(mod p),因为用g的乘幂可以表示集合{1,2,…,p-1}中所有元素。从下表中可见,4不是模7的生成元素,但3和5都是。
模7的生成元素:3和5
Alice先确定了一个素数p以及p的一个生成元素g。假设她选的素数是59,生成元素是2。然后Alice又选定了自己的私钥x。以此她算出公钥的第一部分y=(gx) mod p,这里就是42=(2x) mod 59。她在学校公告牌上公布了p=59, g=2, y=42。注意前面的表中并没有42,这说明Alice的私钥是奇数。你能算出Alice的私钥吗?
Alice的ElGamal系统中的数字
59 Alice选的素数
2 Alice选的生成元素
X Alice的私钥
42 Alice的公钥
Bob想告诉Alice晚会的日期。今年的晚会安排在十天后,因此密信的内容应该是15。为了发送密信,Bob首先记下了公告牌上的三个数,并选择9作为发送密字,由此可算出a=29 mod p=40。Bob还算出解码伴字b=(15×42) mod 59=38。他在学校公告牌上公开了这两个数。
Bob的ElGamal系统中的数字
40 给Alice的解码伴字
38 发送给Alice的密件内容
Alice开始解码,首先计算h=40x mod 59,结果是34。用模除Alice可知33×34 mod 59=1。我们称33是34模59的逆元素。
我们对逆元素进一步解释一下。在做加法时,x的逆元素是-x,因为x+(-x)=0。对乘法,x的逆元素是1/x,因为x×(1/x)=1。而对于模乘,x的逆元素y满足(x×y) mod p=1。
给定素数p和1到p-1之间的x,通过快速乘幂即可算出x模p的逆元素(这是唯一的):计算y=xp-2 mod p,显然x×y mod p=xp-1 mod p。根据数论中的费马小定理,这个数一定是1。
通过计算38×39 mod 59,Alice就得到15,这就是原报文。
我们一直避免说出Alice的私钥究竟是什么。你试试看能否找出这个值,也许你会发现当这个值很大时找出它会非常困难。
其它方法
使用中的公钥密码系统还有许多,其原理都是一样的。为了更安全,系统采用更复杂的运算,例如“圆锥曲线”,甚至“超圆锥曲线”。
安全性
我们自然会问:这样的系统究竟有多安全呢?一个重要的因素是用的数字有多大。数字必须很大,这样计算机用尝试的方式就得要很长世间。这个时间应该保证不会比需要的保密期短。例如在我们的例子中,这个秘密至少得保持到晚会开完。
另一方面,当然也有可能有人突然发现了计算模对数的有效算法。至今也没人能证明这样的算法不存在。数学家和计算机科学家为了找这样的方法已经努力了许多年。因此科学家认为这样的算法不存在。
如果有一天找到了解模对数问题的算法,ElGamal的方法就不安全了。我们希望这不会发生。不过也应该知道,即使上面的算法不能用了,我们还是可以换一种数学运算继续使用类似的想法。