如何用通俗易懂的话来解释非对称加密?

给同行解释,其实也是一帮程序员,他们对加密没有概念。在他们眼中base64和md5都是用来加密的。 我已经可以通过通俗易懂的话加上简单的生活中的例子来…
关注者
1,073
被浏览
399,392
登录后你可以
不限量看优质回答私信答主深度交流精彩内容一键收藏

数据跑不完啊跑不完… 于是混知乎答答题。

=============================

这道题其实我关注很久了。这也是我一直头痛的问题… 怎么给一个完全不懂密码学的人讲解非对称(Asymmetric)/公钥(Public Key)加密体制呢。想起了我Boss的一句话:密码学都源于生活,是为了解决生活中实际问题而来的。而且几乎所有的密码学体制在实际生活中都有一个对应。

那么,我也来试着用生活中的例子来讲一讲公钥加密体制呗。这个答案中,我尽量不使用任何公式,而是尽量用通俗易懂的方式回答。

=============================

1. 引言:以门锁为例(对称/私钥加密体制,Symmetric / Private Key Encryption)

愚蠢的人类啊,为了保护自己的财产,天天都跟门锁和钥匙打交道。最开始的门锁是这样的:

这样的:

以及看起来高端点,但其实还是很脆弱的这样的:

看着挺结实,稍微来个钳子什么的马上就断了啊有木有!直到人们明确了什么叫做安全的锁,并且按照规定制造了这样的锁,门锁才变得比较安全。门锁大概有什么样的要求呢?简单地说有这么几条:

  • 锁芯前面的金属头必须非常坚固,非特殊工具无法打开。
  • 钥匙必须足够复杂,非常难复制(所以现在防盗门钥匙基本都很难配的)。
  • 当然了,门本身也必须足够结实…

按照这样的要求,人们制作了一些很安全的门锁,比如这样的:

以及这样的:


但是这些门锁都有一个共同的问题:就是锁门的时候必须用钥匙锁!在实际生活中这其实是个好事情。如果不用钥匙锁,那我把门撞上了结果没带钥匙岂不是瞎了(这种情况时常发生嘛)…不过,如果门锁只是锁自己家的还好,毕竟进自己家门的话当然需要自己的许可了。可是,如果锁门需要几个人的参与,事情可就比较麻烦了,考虑这样的情况:

  • 我亲戚(或者其他我比较信任的人)来我家做客,但我临时有事要出去,不知道几点回来。难道让我亲戚看家,等我回来再离开么?最好的方法就是他歇够了,出门把门一撞,完事~
  • 我新买的房子,需要装修队装修。装修过程中当然可以开着门谁都能进。装修完了呢?施工队等我回来验收后我主动来锁门他们才能走?

人类的智慧是无穷的。前面也提到了,我们可以找那种能把门撞上打不开的门锁嘛,比如球形锁这样的:

这个非常方便啊有木有。别人想锁门的时候,从里面把按钮按下去,一撞门,外面就打不开了,只有有钥匙的人才能打开。如果不把按钮按下去,外面还是可以打开的。更典型的是酒店的门锁,差不多是这样:

电子的哎,更高端了有木有。电子锁如果检测到门被关上了,它会自动弹出锁芯把门锁住,只有刷卡才能开。这非常好啊,彻底解决了这个问题。

=============================

2. 能“撞”上的保险箱(非对称/公钥加密体制,Asymmetric / Public Key Encryption)

数据加密解密和门锁很像。最开始的时候,人们只想到了那种只能用钥匙“锁”数据的锁。如果在自己的电脑上自己加密数据,当然可以用最开始这种门锁的形式啦,方便快捷,简单易用有木有。

但是我们现在是通信时代啊,双方都想做安全的通信怎么办呢?如果也用这种方法,通信就好像互相发送密码保险箱一样… 而且双方必须都有钥匙才能进行加密和解密。也就是说,两个人都拿着保险箱的钥匙,你把数据放进去,用钥匙锁上发给我。我用同样的钥匙把保险箱打开,再把我的数据锁进保险箱,发送给你。大概就这么个样子:

这样看起来好像没什么问题。但是,这里面最大的问题是:我们两个怎么弄到同一个保险箱的同一个钥匙呢?好像仅有的办法就是我们两个一起去买个保险箱,然后一人拿一把钥匙,以后就用这个保险箱了。可是,现代通信社会,绝大多数情况下别说一起去买保险箱了,连见个面都难,这怎么办啊?

于是,人们想到了“撞门”的方法。我这有个可以“撞上”的保险箱,你那里自己也买一个这样的保险箱。通信最开始,我把保险箱打开,就这么开着把保险箱发给你。你把数据放进去以后,把保险箱“撞”上发给我。撞上以后,除了我以外,谁都打不开保险箱了。这样听起来好像很合理的样子,大概是这么个情况:

=============================

3. 权威机构造保险箱(可信第三方,Trusted Third Party)

这种锁看起来好像很不错,但是锁在运输的过程中有这么一个严重的问题:你怎么确定你收到的开着的保险箱就是我发来的呢?对于一个聪明人,他完全可以这么干:

  1. 装作运输工人。我现在把我开着的保险箱运给对方。运输工人自己也弄这么一个保险箱,运输的时候把保险箱换成他做的。
  2. 对方收到保险箱后,没法知道这个保险箱是我最初发过去的,还是运输工人替换的。对方把数据放进去,把保险箱撞上。
  3. 运输工人往回运的时候,用自己的钥匙打开自己的保险箱,把数据拿走。然后复印也好,伪造也好,弄出一份数据,把这份数据放进我的保险箱,撞上,然后发给我。

从我的角度,从对方的角度,都会觉得这数据传输过程没问题。但是,运输工人成功拿到了数据,整个过程还是不安全的,大概的过程是这样:

这怎么办啊?这个问题的本质原因是,人们没办法获知,保险箱到底是“我”做的,还是运输工人做的。那干脆,我们都别做保险箱了,让权威机构做保险箱,然后在每个保险箱上用特殊的工具刻上一个编号。对方收到保险箱的时候,在权威机构的“公告栏”上查一下编号,要是和保险箱上的编号一样,我就知道这个保险箱是“我”的,就安心把数据放进去。大概过程是这样的:

如何做出刻上编号,而且编号没法修改的保险箱呢?这涉及到了公钥体制中的另一个问题:数字签名。不过题主的问题里面既然没有问道的话,我也就不劳心答了~

=============================

2015.08.04晚22:00继续更新

本来就想到此为止了,不过评论区2个知乎er们希望我继续讲下去,那么就继续?

=============================

4 在保险箱上刻个字(数字签名,Digital Signature)

上回说到如何做出刻上编号,而且编号没法修改的保险箱。那么我们继续楼。要知道,刻字这种事情吧,谁都能干,所以想做出只能自己刻字,还没法让别人修改的保险箱确实有点难度。那么怎么办呢?这其实困扰了人们很长的时间。

直到有一天,人们发现:我们不一定非要在保险箱上刻规规矩矩的字,我们干脆在保险箱上刻手写名字好了。而且,刻字有点麻烦,干脆我们在上面弄张纸,让人直接在上面写,简单不费事。

具体做法是,我们在保险箱上嵌进去一张纸,然后每个出产的保险箱都让权威机构的CEO签上自己的名字。然后,CEO把自己的签名公开在权威机构的“公告栏”上面。比如这个CEO就叫“学酥”,那么整个流程差不多是这个样子:

这个方法的本质原理是,每个人都能够通过笔迹看出保险箱上的字是不是学酥CEO签的。但是呢,这个字体是学酥CEO唯一的字体。别人很难模仿。如果模仿我们就能自己分辨出来了。要是实在分辨不出来呢,我们就请一个笔迹专家来分辨。这不是很好嘛。这个在密码学上就是数字签名

=============================

5 在保险箱上刻的字不能一样(带时间戳 / 随机数的签名,Signature with Timestamp / Randomness)

上面这个签字的方法虽然好,但是还有一个比较蛋疼的问题。因为签字的样子是公开的,一个聪明人可以把公开的签字影印一份,自己造个保险箱,然后把这个影印的字也嵌进去。这样一来,这个聪明人也可以造一个相同签字的保险箱了。

解决这个问题一个非常简单的方法就是在看保险箱上的签名时,不光看字体本身,还要看字体是不是和公开的字体完全一样。要是完全一样,就可以考虑这个签名可能是影印出来的。甚至,还要考察字体是不是和其他保险柜上的字体一模一样。因为聪明人为了欺骗大家,可能不影印公开的签名,而影印其他保险箱上的签名。

这种解决方法虽然简单,但是验证签名的时候麻烦了一些。麻烦的地方在于我不仅需要对比保险箱上的签名是否与公开的笔迹一样,还需要对比得到的签名是否与公开的笔迹完全一样,乃至是否和所有发布的保险箱上的签名完全一样。有没有什么更好的方法呢?

当然有,人们想到了一个比较好的方法。那就是,学酥CEO签字的时候吧,不光把名字签上,还得带上签字得日期,或者带上这个保险箱的编号。这样一来,每一个保险箱上的签字就唯一了,这个签字是学酥CEO的签名+学酥CEO写上的时间或者编号。这样一来,就算有人伪造,也只能伪造用过的保险箱。这个问题就彻底解决了。这个过程大概是这么个样子:

=============================

6 造价问题(密钥封装机制,Key Encapsulation Mechanism)

解决了上面的各种问题,我们要考虑考虑成本了… 这种能“撞”门的保险箱虽然好,但是这种锁造价一般来说要比普通的锁要高,而且锁生产时间也会变长。在密码学中,对于同样“结实”的锁,能“撞”门的锁的造价一般来说是普通锁的上千倍。同时,能“撞”门的锁一般来说只能安装在小的保险柜里面。毕竟,这么复杂的锁,装起来很费事啊!而普通锁安装在多大的保险柜上面都可以呢。如果两个人想传输大量数据的话,用一个大的保险柜比用一堆小的保险柜慢慢传要好的多呀。

怎么解决这个问题呢?人们又想出了一个非常棒的方法:我们把两种锁结合起来。能“撞”上的保险柜里面放一个普通锁的钥匙。然后造一个用普通的保险柜来锁大量的数据。这样一来,我们相当于用能“撞”上的保险柜发一个钥匙过去。对方收到两个保险柜后,先用自己的钥匙把小保险柜打开,取出钥匙。然后在用这个钥匙开大的保险柜。

这样做更棒的一个地方在于,既然对方得到了一个钥匙,后续再通信的时候,我们就不再需要能“撞”上的保险柜了啊,在以后一定时间内就用普通保险柜就好了,方便快捷嘛。这个过程大概是这么个样子:

=============================

7 迎接美妙生活吧

最终,我和对方可以充分利用各种各样的锁,通过一些很棒的方法,在公开场合下面做安全的通信啦。现在网络通信中的过程大致就是如此,不过里面还有很多细节的东西。在此我卖个关子,大家可以按照实际生活中的解决方法想一想如何才能解决呢。一些其他的细节问题大致如下:

  • 既然能“撞上”的保险箱都是权威机构产生的,那么权威机构怎么把这个保险箱的钥匙发给用户呢?
  • 我们如何保证权威机构生产的保险箱是安全的呢?要是权威机构生产的保险箱本身就不安全怎么办(这实际上就是棱镜门事件的一个理论原因)?

另一方面,对于普通的保险箱,或者能“撞上”的保险箱,在现今社会我们还有一些其他需求,这些需求怎么解决呢?比如下面的问题:

  • (密钥委托,Key Delegation):我想让我的亲属能打开我一部分的保险箱。否则遇到突发情况的时候,谁帮我用我的钱交医药费啊…同时,我又不能让他们能打开我全部的保险箱,比如锁着我日记的保险箱,锁着我不可告人的秘密的保险箱。
  • (全同态加密/签名,Fully Homomorphic Encryption/Signature):我在保险箱里锁了一些金子,我想让金匠帮我造个首饰,但是我又不想让金匠在加工过程中偷我的金子。在实际中解决的方法就是我保险箱上面装了好多工具。金匠可以用这些工具对我保险箱里面的金子进行加工。但是因为金子还在保险箱里面锁着,金匠拿不出金子来。
  • (函数加密,Functional Encryption):我想锁一些数据在保险箱里面。但是其实我也不知道这些数据谁能够打开。不过,我可以确定,满足某某某某条件的那些人可以打开保险柜,把数据取走。比如说:名字叫学酥的人;只要是个知乎er,还对密码学感兴趣;甚至,是个知乎er,而且年龄在25岁以下的;甚至,我们可以定义任意的条件,反正能满足的才能打开就对了~

更多的功能等待各位知乎er们来挖掘啦。没准就是一个很好的密码学点子呢。

=============================

以上。