精子生于 1995 年,英文 ID jysperm.
笔记:公钥加密算法
在一年多以前,我曾计划写一个系列,关于密码学基础的科普文章。但当我写完第一篇,散列算法的时候,便觉得自己功力尚浅,仍需修炼。今天重新捡起来,写下去。
公钥密码学,也称非对称加密,可以说是现代密码学的基础设施之一。公钥密码学也可以说标志着现代密码学的诞生,让密码学从政府,军方之间的斗智斗勇,成为了具有严谨数学基础的学科。
目前使用最为广泛的公钥加密算法:RSA, 其发明者因此获得图灵奖(计算机领域的最高奖项).
应该说密码学一直以来和军队,战争都是密不可分的。
我们设想这样一个场景,同属一个阵营的两个部队,被相隔一段距离,其间都被地方部队占领,这意味着他们之间通过信使传递的所有信息,都是可能被敌人监控(阅读)的。
那么如何在事先没有沟通的情况下安全地交换信息呢?
对于经典的对称加密算法(对等加密, 共享密钥加密), 这是很难做到的。因为对称加密需要一个密钥(密码), 而两个部队事先是没有沟通过的,没有对密钥达成共识。
而且他们现在也不可能再协商密钥,因为现在他们所有的通信都是被监控的了,一旦他们在这种环境下协商密钥,那么敌人也会知道密钥,便也能解密他们之后传送的加密信息。
对称加密对加密和解密都使用同一个密钥,我们可能需要的是一种针对加密和解密,使用不同密钥的加密算法,这便是非对称加密的含义。
试想,部队A可以生成一对密钥,分别用于加密(公钥)和解密(私钥), 然后将公钥发送给部队B. B便可以使用这份密钥对信息进行加密,再将加密信息发送回A了。
这里的公钥,即使被敌人获取也没有关系,因为这里的公钥,仅仅能够用于加密数据,而唯一可以解密数据的私钥,自始自终都在A手中,从未公布出去。
这样一来,A和B便可以在受监控的情况下,没有实现沟通,便能安全地交换信息了。
让我们进一步设想,如果敌人可以篡改A和B之间发送的信息呢?
例如当A发送公钥给B的时候,敌人将公钥拦截下来,自己生成一堆公私钥,将自己的公私钥发送给B. 相当于敌人冒充了B与A建立联系,建立了两个加密通道,分别是从A到敌人,和从敌人到B.
这样以来,敌人便可以在两个通道之间,监控到A和B通信的明文了,同时敌人还可以任意篡改A和B之间发送的信息,即使它们已经被加密。
这便是经典的“中间人攻击”. 应该说如果A和B没有事先沟通过,而且没有一个可信的第三方,那么这个问题几乎是无解的。
但如果允许A和B事先进行沟通,该如何在敌人可以篡改信息的前提下,安全地交换信息呢?
其实这个问题很好解决,只需在实现沟通时互相交换密钥即可,其后敌人(中间人)便无法再进行冒充了,因为密钥根本没有在这时被交换。
然而更为通用的做法是使用“数字签名”,数字签名恰好是公钥加密的逆运算。即将加密密钥保密,而将解密密钥公布出去,使得只有自己可以加密信息,而任何人都可以解密信息。
要实现数字签名,只需自己将要签名的信息(通常是一个散列摘要值)加密并公布即可,其他人可以认为,凡是用你公布出去的解密密钥能解密的信息,都是你自己加密(签名)过的。
这样便可以识别一段信息,是否真正地由其宣传的发信人所发送,识别出被中间人所篡改的信息。
在前面的情况下,我们还需要考虑的是“重放”攻击,即中间人虽然不知道A和B传输的实际内容,但却可以将其中的一份信息复制两遍甚至更多,已达到干扰的目的。通常应对重放攻击只需在加密信息中约定一个递增的编号,或者时间戳即可。
下面我们来讨论公钥加密算法(RSA)背后的数学原理,本人数学很渣,只能大概谈谈应用RSA时需要了解的一些原理,更详细的数学原理请围观各种大牛的文章,如: http://www.matrix67.com/blog/archives/5100
RSA基于这样一个原理:计算两个数的乘积是十分容易,但对一个数进行因式分解,得到这两个数却十分不易。
可能这个原理并不直观,甚至有点反常识,但RSA选择的两个数的乘积,都是2^2048这样数量级的数字,换算为十进制,那么将会是1后面跟6000多个0.
直到目前,对大数进行因式分解仍是一个难题,数学家还没有找到比试除法更高效一点的方法,因此在目前,对一个足够大的数进行因式分解可以认为是一项不可能完成的任务。但也不排除今后有数学家发明进行因式分解的简单方法,届时,RSA算法,甚至整个密码学,整个世界都会坍塌。
有点虎头蛇尾啊,本来打算最后举一个RSA计算的例子的,结果还是写不下去 …