基于用到啥就要弄清楚啥的学习原则,今天来讲一下对称加密与非对称加密,本文不谈具体加密算法的实现细节,但会理清楚两种加密方式的设计思路,以及实际应用。
在实际接触的项目里,有这么两类需求:
(1)消息在网络传输过程中如果被截获,如何不泄露真实信息?(加密、解密)
(2)如何验证消息的合法性?(加签、验签)
基于前两个需求,人们提出了各种各样的方案,像古时候就有:虎符、密码棒等,当代则有对称加密和非对称加密。
对称加密
最简单的记法,对称加密就是只有一个密钥的加密算法,具体过程如图:
基本流程:
- 设备A、设备B事先确认好密钥(通过安全的方式,比如说面对面交流)。
- 设备A利用密钥对原文进行加密,再将密文通过网络传输到设备B。
- 设备B拿到密文后,利用密钥对数据进行解密,获得原文。
流程非常简单,因为数据是加密传输的,所以中间节点即使拿到了传输数据,也因为没有密钥而无法获得真实信息,满足了前文的需求(1)。至于何为对称?是因为反过来设备B给设备A发送消息,也是用一样的套路,所以就是对称加密。
对称加密算法有:DES、3DES、Blowfish、IDEA、RC4、RC5、RC6和AES,目前项目用的较多是AES和DES。
看完对称加密的基本流程,可以发现他有一个很明显的缺点,双方交流之前,要先认识(确认密钥)。然而实际场景中,大多数都是临时的交互,这时候还得先确认密钥,显然不太现实,我要访问简书难道还得先去简书公司要个密钥么?更何况这种密钥交流广泛后,也将不再安全。
这种问题自然难不倒大牛们,既然不方便沟通密钥,那就直接通过网络传输吧,但对称加密显然不能满足这种场景,于是就有了非对称加密。
非对称加密
非对称加密,就是有两个密钥的加密算法:公钥、私钥。
为了更好的说明非对称加密,先要简单说下非对称加密算法的具体实现(非常简单的那种,理解思路就行):
- 原文111,私钥333,加密算法是:密文 = 消息+密钥,所以第一次加密出来就是111+333=444(密文)。
- 公钥667,通过同样的加密算法操作,就是444+667=1111,舍去最高位1,那就是原文111(非对称加密算法显然需要支持这种简单的去位操作)。
虽然图里将第二步给标明为了“解密”,但这显然和之前加密是同一个操作,因为只是加密用的密钥不同,但算法是一模一样的。
这就是非对称加密算法实现的基本思路,消息加密经过两次同样的加密操作能恢复,一次用私钥加密,一次用公钥加密(其实仔细点看,先公钥再私钥也能恢复,但在真实的算法里,私钥可以推算出公钥,所以这两者不是等价的)。
知道了这些,接下来就讲讲在网络环境中,非对称加密是如何操作的:
- 设备A先通过自己的私钥(设备A私钥)加密原文,同时将密文和自己的公钥(设备A公钥)一起发送给设备B。
- 设备B拿到密文和设备A公钥后,对密文解密(就是用设备A公钥再进行一次加密算法),得到明文。
- 同样的设备B如果想发消息给设备A,就用自己的密钥进行同样的操作即可。
4.成功给了对方自己的公钥后,后续只需用私钥加密数据即可。
虽然设备A将公钥暴露了出去,但其他节点是无法伪造设备A给设备B发送数据的(因为没有设备A的私钥,无法通过私钥加密后给设备B传输数据,那么设备B拿到数据后,可以通过设备A公钥解密)。反过来设备B给设备A发消息也是类似的操作,只是里面密钥变成了设备B的公、私钥,所以这也叫非对称加密。
非对称加密算法有RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法),目前使用最广泛的是RSA算法。
看似好像解决了对称加密里密钥无法在网络传输的问题,但仅仅是这样的话,会有这个一个麻烦,假设设备A和设备B需要通过一个中间节点来通信(实际网络中一般不止一个),那中间节点自然有能力拦截双方消息,此时就会有一个场景:
- 设备A发送消息给设备B: "我要和你聊天,这是我的设备A公钥"。
- 中间节点拦截消息,读取到设备A的公钥,替换为自己的公钥,同时消息转发给设备B: "我要和你聊天,这是我的中间人钥"(被替换)。
- 设备B拿到消息后,回答:“好的,这是我的设备B公钥”。
- 中间节点此时拦截设备B的消息,得到设备B的公钥,同时替换消息中的设备B公钥为自己的中间人公钥,再发送给设备A:“好的,这是我的中间人公钥”(被替换)。
- 设备A得到消息后,相信是B的公钥,后续则用该公钥来加密自己的消息,发送:“我们今天吃点好的(中间人公钥加密)”。
- 由于消息是用中间人的公钥加密的,那么中间人拿到消息就能解密,阅读、篡改,再用设备B的公钥加密后发送:“我们分手吧(篡改,同时设备B公钥加密)”
- 设备B接到消息,用中间人公钥加密,回复:“不要啊,我去找你聊,等我(中间人公钥加密)”。
- 中间人拿到消息,用自己中间人私钥解密,同时修改消息,再用设备A公钥加密:“我们分手吧!”(篡改,同时用设备A公钥加密)。
- ................
两个设备最后咋样了不好说,但从过程来看,由于中间人同时欺骗了设备A和设备B,让他们都用自己的公钥来加密数据,所以这两个设备之间的交互将完全暴露给中间人。
之所以会这样,就是因为两个设备缺乏一种手段,一种能验证来对方公钥是否合法的手段,那就得提到另外一个操作了,加签!
加签、验签
由于设备A的大嘴巴,把自己的公钥到处发,导致设备B难以分辨数据来源(虽然无法直接伪造,但可以间接攻击),那只要有一种办法,让设备B对到来的数据,能明确知道是设备A的就可以了,这就需要设备A对数据进行签名,只要签上设备A的大名,那就能真正确认数据是设备A发的,而不是中间人。
- 设备A准备发送消息”我是A“,先通过自己私钥加签得到一个密文,然后将"我是A"和密文组合起来,成为”我是A&密文“,接着将组合内容和自己公钥一起发送给设备B。
- 设备B拿到组合消息”我是A&密文“与设备A公钥后,单独对用公钥对密文进行验签,的到验签结果”我是A“,接着和’&‘前面的”我是A“进行对比,如果一致,就说明真的是A发来的消息。(虽然换了个名字加签、验签,但本质上和前面是一回事)。
方案很简单,就是利用设备A私钥只有设备A才有这一特点,可以准确识别是不是设备A的消息。不过,为了验这个签,把自己原文都发送出去了,那还加个啥密啊,而且也影响不了中间人攻击,根本没有解决问题额。
感觉再说下去就到了Https了,这个另开一坑来说。就目前的几种方式来看,还是对称加密让人省心些,虽然不太好用,但是安全啊!