一次网络的请求,会经过很多的中间人,比如路由器,猫,网络运营商的基站等等。如果使用HTTP
这协议,些中间人,是可以直接查看浏览器和服务器之间的数据的,相当于在裸奔。
以前在网络监管没有那么严格的时候,xx
公司就会在服务器返回给客户端的数据上面添油加醋,比如说返回的网页上面加入广告,让你冲话费啥的。。。
思考:怎么保证这些中间人不能查看客户端和服务器之间的数据?
加密。用一个只有客户端和服务器知道的密码对数据进行加解密。中间人不知道密码,即使截获到了数据,也是一堆乱码,也不能进行查看修改。
记得上大学的时候,到银行办理过一个网上银行的服务。银行会给你发一个类似U
盘的东西,当你想要转账的时候,就把这个东西插在电脑上,然后就能进行安全的转账了。
其实,这个U
盘里面包含的就是客户端和服务端用来加密数据的密码。密码只有客户端和服务端知道,保证了绝对的安全。
客户端和服务端使用的都是同一个密码,这就是对称加密。
思考:在互联网应用中,如果每个应用的客户都下发一个U盾,来传递密码,全世界这么多应用、这么多用户,这是一个指数级的问题,没有办法实现。那么如何在互联网上安全的传输这个对称加密的密码而不被外泄呢?
引入非对称加密,用来传输对称加密所使用的秘钥。加密和解密用的不是同一个秘钥。公钥加密只有私钥能解,私钥加密只有公钥能解。
在TCP
三次握手之后,https
中的ssl
协议还会要求一次四次握手,主要用于商量对称加密的算法以及对称加密使用的秘钥。
- 客户端会
say
一个Hi
,并且将自己支持的对称加密算法集合(cipher suites
)发送给服务器,服务器会从这些算法中挑选一个自己也支持的对称加密的算法,并且返回给客户端。同时将自己的public key
发送给客户端。 - 客户端得到响应之后,知道了要使用的对称加密的算法是什么,接下来,就会和服务器商量一个对称加密的秘钥。
- 客户端会随机生成一串秘钥,并且用服务端的
public key
进行加密。发送给服务器。 - 服务器在收到秘钥之后,使用自己的私钥进行解密得到对称加密的秘钥。由于公钥加密只有私钥能够解密,而私钥只有服务器才有,其它的中间人是没有的,中间人无法解密,所以保证了对称加密所使用的秘钥的安全。
思考:上面的流程绝对安全了吗?
并不是。中间人可以冒充服务器和客户端的。
如果服务器在下发公钥的时候,公钥被中间人拦截。
1)冒充服务端:我不把这个公钥传递给客户端,而是我自己生成一对公私钥,然后将自己的公钥传给客户端。这样我就能冒充服务器和客户端进行通信了。
2)冒充客户端:我不把客户端的请求转发给服务器,而是用服务器的公钥将自己生成的对称加密的秘钥加密之后,发给服务器,这样后面我就能够冒充客户端和服务器通信了。
思考:如何解决中间人冒充客户端或者服务器的问题?
这时候就需要引入第三方机构CA
了。
Server
提供一些信息,比如网站的域名、邓白氏编码、营业执照、自己的公钥给CA
机构CA
机构对这些信息进行一个鉴别,主要是鉴别这个网站是不是属于你的。防止有人申请同一个网站的证书。一般验证的方法是让你在网站的某个目录放一个文件,并且在文件里面写上指定的内容。- 验证通过之后,
CA
机构会拿自己的私钥,给server
提供的信息签一个名。这样就得到了一个CA
证书。CA
私钥签名只有CA
的公钥能够解开。 - 获得
CA
证书之后,网站的管理员需要将证书部署到server
上。 - 客户端在请求服务器的时候,服务器会将包含自己的
public key
的证书发送给客户端 - 客户端拿到证书之后,会用
CA
的公钥对证书进行解密。CA
的公钥也是包含在证书中的,一般是内置在操作系统中。 - 这样一来,就得到了
server
的public key
了。后面再使用这个key
协商对称加密的秘钥。
思考:中间人能够解开server
的证书吗?
能。既然客户端的操作系统能够内置CA
机构的公钥,那么中间人的操作系统也可以。所以中间人也能够解开证书得到服务器的公钥。
思考:既然中间人能解开证书得到server
的公钥,那么它还能冒充服务器吗?
不能。中间人如果需要冒充服务器,它需要创建一个伪证书。它不可能从CA
再去申请一个相同域名的证书了,因为CA
机构会进行验证(如果真的申请成功了怎么办?CA
机构会为你的损失给你赔钱)。既然不能申请证书,那么可不可以自己伪造一个?
即使伪造了也没啥用。因为中间人需要拿自己的私钥签名一个伪证书,而客户端现在会用内置的CA
机构的公钥去解密收到的证书。中间人发过来的伪证书,客户端是没有办法使用内置的公钥解开的。(当然如果你的系统受到了攻击导入了一些包含公钥的不正常的证书话,就不能避免这个问题,所以我们不能随便给系统导入证书)
思考:中间人现在能够冒充客户端吗?
这时候是可以的。因为中间人能够得到server
的公钥。中间人不把客户端的请求发给服务器,而是用服务器的公钥将自己生成的对称加密的秘钥加密之后发给服务器,这样后面就能够冒充客户端和服务器通信了。
解决办法:到这里,都是客户端去验证server
端是不是真正的server
,这就是https
的单向认证。HTTPS
还有一个双向认证,server
端也去验证下是不是真正的客户端在和自己通信。既然server
端能够申请证书,那么客户端能不能也去CA
申请一个证书?证明自己是真正的客户端。可以的。
双向认证可以参考这篇文章:https://www.jianshu.com/p/2b2d1f511959?utm_campaign=haruki