多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
# 加密的问题 ## 对称加密 HTTP的通信是明文的, 任何一个人都可以监听上面的通信,截取里面的数据包。最容易想到的解决方法无非就是**加密。** 每次传输之前把消息用加密算法加密,服务器收到了以后再解密。 如下图所示 ![image.png](http://upload-images.jianshu.io/upload_images/1323506-d83f7df38ce1b2cc.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 这种**加密和解密用的是同一个密钥的算法称为对称加密算法**。那么实际上**加密和解密算法是公开的,密钥是保密的** 那么问题就来了,如果密钥在网络上发送的时候被截取了怎么办,也就是说密钥同样不能在网络上传输,但是加密双方都必须知道。 ## 非对称加密 之前的算法需要协商一个保密的**密钥**,而这个密钥在网络上传输的时候存在被窃取的风险。然后出现了一个**RSA非对称加密算法。** 这个算法有一对密钥,一个是**私钥,**它是保密的,一个是**公钥**,是对外公开的。 那么用**私钥加密的数据,只能用对应的公钥来解密** 同样,用**公钥**加密的数据,只有对应的**私钥**才能解密。 于是浏览器给服务器发消息的时候,浏览器先使用**服务器的公钥**进行加密,然后服务器可以使用自己的**私钥**去解密。 反之亦然,服务器给浏览器发信息的时候,使用浏览器的**公钥**进行加密。 ## 非对称加密 + 对称加密 使用非对称加密好是好,但是特别的慢。相对于非对称加密而言,对称加密会快很多。那么能不能折中一下呢? 我们知道之前用对称加密的时候,问题在于密钥无法安全传输。那么现在能不能**先对密钥使用非对称加密**,这样保证了密钥的安全传输。等到密钥被对方收到了以后,就使用**对称加密**,这样可以兼顾安全和性能呢。 # 身份认证的问题 上面说了,可以对密钥进行非对称加密,对报文进行对称加密,这样可以保证性能和安全性。但是新的问题来了,我们怎么保证对方的身份。也就是说如果服务器给浏览器发的**公钥**给中间人**截取了**,然后冒充服务器给浏览器发了一个公钥,这个时候,浏览器并不知道这一切,所以会使用中间人的公钥进行加密,中间人当然就可以解密到消息了。 这就如同古代的时候,新上任的县官被人半路上被绑匪给截了,然后绑匪拿着他的印信冒名顶替,下面的人并不知道此人并非真实县官,这样绑匪自然可以窃取各种机密。 所以**问题在于公钥是公开的,完全可以被冒名顶替** ## 公证处 所以问题根源在于,**如何证明这个公钥确实是服务器发出来的。** 这个问题在现实中就有,公证处就是这样的第三方的存在,他提供的资料受到大家的信任。所以我们也可以搞一个认证中心,给大家颁发一个**数字证书**,证明这个人的身份。同时证书里面一定有**这个人的公钥**。 但是证书依然有怎么安全传输,怎么避免被篡改的问题。我们可以使用HASH算法生成一个**消息摘要**,这就是**数字签名。** HASH算法有个特性,**只要输入有变化,那生成的数字签名就会有巨大的变化**,这样就可以防篡改。 中间人说,虽然改不了**公钥**,但是可以替换整个原始的信息啊。就如果我们破解开机密码一样,不也是把原来加密以后的密码文件给替换了吗? 道高一尺,魔高一丈,我们再让公信处(CA)用**它的私钥对消息摘要**加密,形成签名。 **原始信息 + 数字签名** = **数字证书** ![image.png](http://upload-images.jianshu.io/upload_images/1323506-1de1bb7699767c0e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 这样有了第三方的证书,相当于有个参考。我们可以用**CA的公钥**对数字签名进行解密,以此为**基线** 当服务器把它的**证书**给我们的时候,我们可以使用相同的Hash算法生成消息摘要,然后与“基线”对比,就知道是否被篡改过了没。 ![image.png](http://upload-images.jianshu.io/upload_images/1323506-289ca0646b585699.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) **总结一下**,因为公钥传输有可能被截取,所以我们希望有一个**第三方机构**能提供**基线**,我们只要对比**基线**就知道是否被人篡改过了。这样每个网站它的基线应该是不同的,所以可以使用HASH算法对网站的个人信息生成一个**消息摘要**。那么我们只需要核对从网站收到的**消息摘要**与第三方给的**消息摘要**是否是一样的就可以了。 好了,保证**基线**正确非常的关键,而第三方机构的证书同样存在没有加密的问题,容易被篡改的问题。 - 加密的问题:可以让第三方机构使用其私钥对**基线**加密,我们用其公钥解密即可。 - 容易被篡改的问题:无解,只能说对CA进行信用分级,在操作系统/浏览器内置一些顶层的CA证书,高层的CA给底层的CA做背书。 这样,网站在给我们发送**公钥**的时候,实际上是把**公钥**和**加密后的消息摘要**放到一起发过来的,我们 - 使用CA的**公钥**对加密后的**消息摘要**进行解密,得到**基线** - 再对含有**公钥**的个人信息同样使用HASH算法也得到消息摘要 如果没有被篡改过,这两者应该是相等的 # 小结 我们可以对上面的过程进行简单的总结。 如果传输的信息没有加密,则信息容易在传输的过程中被窃取掉。那么我们可以使用同一个密钥对信息加密,但是在传输之前,必须把密钥在网络上传输一次,所以一样存在密钥被窃取的风险。 那么可以使用非对称加密算法,也就是发送方使用对方**公钥**进行加密,然后接收方使用自己的**私钥**进行解密。但是非对称加密算法需要消耗大量的资源,速度比较的慢。 那么可以中和一下。对于**公钥**我们使用**非对称加密**,对于要发送的信息使用**对称加密**,这里面存在的问题是如果我把**密钥**用另一个伪装的密钥进行全文替换,依然存在安全的风险。 那么可以加上一个**身份验证**的环节。 - 首先将**接收方**的公钥+个人信息进行Hash,得到一个消息摘要,这样如果传输过程中公钥被篡改,则**消息摘要**肯定会改变。 - 然后对消息摘要使用第三方证书中心的**私钥**进行加密,这样就可以保证消息摘要不会再传输过程中被篡改。 也就是说CA证书中心的私钥加密的是公钥+个人信息进行hash以后的消息摘要,得到数字签名。 这个数字签名里面包含了**公钥**的信息,而且被加密过了,不担心被人篡改,可以作为**基线** ![image.png](https://upload-images.jianshu.io/upload_images/1323506-37811ec702ed9b28.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - 那么如何进行**校验**呢? 发送方会把公钥信息+通过公钥等信息生成的数字签名一起发送过去。 接收方首先对数字签名进行解密,这样就可以获得消息摘要。 同样,再对公钥信息进行Hash,同样可以获得消息摘要。 这两者一核对,如果相同,则验证通过,不同,则出现了问题呗。 ![image.png](https://upload-images.jianshu.io/upload_images/1323506-2e41fd5e351f2fac.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 也就是由一个第三方证书中心使用其**私钥**对接收方的**公钥**进行一次加密,也就是一个**基线**, # HTTPS ![image.png](http://upload-images.jianshu.io/upload_images/1323506-94b719a51c27b504.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - 首先浏览器请求服务器的**公钥** - 服务器返回一个含有公钥的**数字证书**,这个数字证书怎么得到的呢?由含有公钥的原始数据进行HASH以后,再使用CA私钥加密得到**数字签名**,再和原始数据一起组成了**数字证书** - 浏览器通过数字证书,既验证了服务器的身份,又得到了**公钥** - 使用公钥加密**对称加密**的密钥 - 使用对称加密进行通信 # 参考 [一个故事讲完https](https://mp.weixin.qq.com/s?__biz=MzAxOTc0NzExNg==&mid=2665513779&idx=1&sn=a1de58690ad4f95111e013254a026ca2&chksm=80d67b70b7a1f26697fa1626b3e9830dbdf4857d7a9528d22662f2e43af149265c4fd1b60024&scene=21#wechat_redirect)