我们先不去探究ssl的实现原理,我们先从设计者的角度去思考如何去建立一个安全的传输通道
从第一个消息开始
客户端A向服务端B发送一条消息,这个消息可能会被拦截以及篡改,我们如何做到A发送给B的数据包,及时被拦截了,也没办法得知消息内容并且也不能查看呢?
利用对称加密
要做到消息不能被第三方查看以及篡改,那么第一想法就是对内容进行加密,同时,该消息还需要能被服务端进行解密。所以我们可以使用对称加密算法来实现,密钥S扮演着加密和解密的角色。在密钥S不公开的情况下,就可以保证安全性?
没那么简单
在互联网世界,通信不会这么简单,也许是这样。
会存在多个客户端和服务端产生连接,而这个客户端也许是一个潜伏者,如果他也有对称密钥S,那相当于上面的方案是不可行的?如果服务端和每个客户端通信的时候使用不同的加密算法呢?
似乎能够完美解决问题,然后?密钥如何分配呢?也就是服务端怎么告诉客户端该使用那种对称加密算法呢?
解决办法似乎只能通过建立会话以后进行协商了?
协商过程又是不安全的
协商过程,意味着又是基于一个网络传输的情况下去动态分配密钥,可是这个协商过程又是不安全的,怎么破?
非对称加密出马
非对称加密算法的特点是:私钥加密后的密文,只要有公钥,都能解密,但是公钥加密后的密文,只有私钥可以解密。私钥只有一个人有,而公钥可以发给所有人
这样就可以保证A/B向服务器端方向发送的消息是安全的。似乎我们通过非对称加密算法解决了密钥的协商的问题?但是
公钥怎么拿?
使用非对称加密算法,那么如何让A、B客户端安全地持有公钥?
那么我们逐步思考,有两种我们能想到的方案:
1. 服务器端将公钥发送给每一个客户端
2. 服务器端将公钥放到一个远程服务器,客户端可以请求到 (多了一次请求,还得解决公钥放置问题)
方案一
似乎不可行,因为,传输过程又是不安全的?公钥可能会被调包
引入第三方机构
到上面这一步,最关键的问题是,客户端如何知道给我公钥的是黄蓉还是小龙女?只能找本人去证实?或者有一个第三者来帮你证实,并且第三者是绝对公正的。
所以,引入一个可信任的第三者是一个好的方案 服务端把需要传递给客户端的公钥,通过第三方机构提供的私钥对公钥内容进行加密后,再传递给客户端? 通过第三方机构私钥对服务端公钥加密以后的内容,就是一个简陋版本的“数字证书”。这个帧数中包含【服务器公钥】
客户端拿到这个证书以后,因为证书是第三方机构使用私钥加密的。客户端必须要有第三方机构提供的公钥才能解密证书。这块又涉及到第三方机构的公钥怎么传输?(假设是先内置在系统中)以及还有一个问题,第三方机构颁发的证书是面向所有用户,不会只针对一家发放。如果不法分子也去申请一个证书呢?
如果不法分子也拿到证书?
如果不法分子也申请了证书,那它可以对证书进行调包。客户端在这种情况下是无法分辨出收到的是你的证书,还是中间人的。因为不论是中间人的、还是你的证书
都能使用第三方机构的公钥进行解密。
验证证书的有效性
事情发展到现在,问题演变成了,客户端如何识别证书的真伪?在现实生活中,要验证一个东西的真伪,绝大部分都是基于编号去验证(比如大学毕业证书,比如买的数码产品是否是山寨),我之前讲过,计算机领域的解决方案都是人为去实现的,所以在这里,解决方案也是一样,如果给这个数字证书添加一个证书编号?是不是就能达到目的呢?
证书上写了如何根据证书的内容生成证书编号。客户端拿到证书后根据证书上的方法自己生成一个证书编号,如果生成的证书编号与证书上的证书编号相同,那么说明这个证书是真实的。这块有点类似于md5的验证,我们下载一个软件包,都会提供一个md5的值,我们可以拿到这个软件包以后通过一个第三方软件去生成一个md5值去做比较,是不是一样如果一样表示这个软件包没被篡改过
对服务端的数据进行MD5算法得到一个MD5的值,生成证书编号,使用第三方机构的私钥对这个证书编号进行加密,并且会在证书中添加证书编号的生成算法
浏览器内置的CA公钥可以解密服务端CA私钥加密的证书,通过浏览器内置的CA证书的证书编号算法对服务端返回的证书编号进行验签
第三方机构的公钥证书存哪里?
浏览器和操作系统都会维护一个权威的第三方机构列表(包括他们的公钥)
因为客户端接收到的证书中会些颁发机构,客户端就根据这个办法机构的值在本地找到响应的公钥
说到这里,我想大家一定知道,证书就是HTTPS中的数字证书,证书编号就是数字签名,而第三方机构就是数字证书的签发机构(CA)