Http协议
由于 HTTP 协议在通信过程中,是基于明文通信,并且底层是基于 TCP/IP 协议进行通信,那么按照 TCP/IP 协议族的工作机制,通信内容在所有的通信线路上都有可能遭到拦截和窃取。
https 安全传输协议
由于 HTTP 协议通信的不安全性,所以人们为了防止信息在传输过程中遭到泄漏或者篡改,就想出来对传输通道进行加密的方式 https。https 是一种加密的超文本传输协议,它与 HTTP 在协议差异在于对数据传输的过程中,https对数据做了完全加密。由于 http 协议或者 https 协议都是处于 TCP 传输层之上,同时网络协议又是一个分层的结构,所以在 tcp 协议层之上增加了一层 SSL(Secure Socket Layer,安全层)或者 TLS(Transport Layer Security) 安全层传输协议组合使用用于构造加密通道。
推导 https 的设计过程
我们先不去探究 ssl 的实现原理,我们先从设计者的角度去思考如何去建立一个安全的传输通道,客户端 A 向服务端 B 发送一条消息,这个消息可能会被拦截以及篡改,我们如何做到 A 发送给 B 的数据包,即使被拦截了,也没办法得知消息内容并且也不能查看呢?
我们首先了解几个基本概念。
共享密钥加密(对称密钥加密):加密和解密同用一个密钥。加密时就必须将密钥传送给对方。
公开密钥加密(非对称密钥加密):公开密钥加密使用一对非对称的密钥。一把叫做私有密钥,一把叫做公开密钥。私有密钥不能让其他任何人知道,而公开密钥则可以随意发布,任何人都可以获得。使用此加密方式,发送密文的一方使用公开密钥进行加密处理,对方收到被加密的信息后,再使用自己的私有密钥进行解密。利用这种方式,不需要发送用来解密的私有密钥,也不必担心密钥被攻击者窃听盗走。
利用对称加密
要做到消息不能被第三方查看以及篡改,那么第一想法就是对内容进行加密,同时,该消息还需要能被服务端进行解密。所以我们可以使用对称加密算法来实现,密钥 S 扮演着加密和解密的角色。在密钥 S 不公开的情况下,就可以保证安全性?
在互联网世界里,通信不会这么简单,会存在多个客户端和服务端产生连接,而这个客户端也许是一个潜伏者(黑客),如果他也有对称密钥 S,那相当于上面的方案是不可行的。
如果服务端和每个客户端通信的时候使用不同的加密算法呢?
似乎能够完美解决问题,然后?密钥如何分配呢?也就是服务端怎么告诉客户端该使用哪种对称加密算法呢?解决办法似乎只能通过建立会话以后进行协商了。但协商过程又是不安全的?怎么破?
非对称加密
非对称加密算法的特点是:私钥加密后的密文,只要有公钥,都能解密,但是公钥加密后的密文,只有私钥可以解密。私钥只有一个人有,而公钥可以发给所有人
这样就可以保证 A/B 向服务器端方向发送的消息是安全的。似乎我们通过非对称加密算法解决了密钥的协商的问题?但是公钥怎么拿?使用非对称加密算法,那么如何让 A、B 客户端安全地持有公钥?那么我们逐步思考,有两种我们能想到的方案:
1. 服务器端将公钥发送给每一个客户端
2. 服务器端将公钥放到一个远程服务器,客户端可以请求到
方案一似乎不可行,因为,传输过程又是不安全的,公钥可能会被调包
引入第三方机构
到上面这一步,最关键的问题是,客户端如何知道给我公钥的是黄蓉还是小龙女?只能找本人去证实?或者有一个第三者来帮你证实,并且第三者是绝对公正的。所以,引入一个可信任的第三者是一个好的方案。
服务端把需要传递给客户端的公钥,通过第三方机构提供的私钥对公钥内容进行加密后,再传递给客户端? 通过第三方机构私钥对服务端公钥加密以后的内容,就是一个简陋版本的“数字证书”。这个证书中包含【服务器公钥】。
客户端拿到这个证书以后,因为证书是第三方机构使用私钥加密的。客户端必须要有第三方机构提供的公钥才能解密证书。这块又涉及到第三方机构的公钥怎么传输?(假设是先内置在系统中)以及还有一个问题,第三方机构颁发的证书是面向所有用户,不会只针对一家发放。如果不法分子也去申请一个证书呢?
如果不法分子也拿到证书?
如果不法分子也申请了证书,那它可以对证书进行调包。客户端在这种情况下是无法分辨出收到的是你的证书,还是中间人的。因为不论是中间人的、还是你的证书都能使用第三方机构的公钥进行解密。
验证证书的有效性
事情发展到现在,问题演变成了,客户端如何识别证书的真伪?在现实生活中,要验证一个东西的真伪,绝大部分都是基于编号去验证(比如大学毕业证书,比如买的数码产品是否是山寨)所以在这里,解决方案也是一样,如果给这个数字证书添加一个证书编号?是不是就能达到目的呢?证书上写了如何根据证书的内容生成证书编号。客户端拿到证书后根据证书上的方法自己生成一个证书编号,如果生成的证书编号与证书上的证书编号相同,那么说明这个证书是真实的。 这块有点类似于 md5 的验证,我们下载一个软件包,都会提供一个 md5 的值,我们可以拿到这个软件包以后通过一个第三方软件去生成一个 md5 值去做比较,是不是一样如果一样表示这个软件包没被篡改过。
对服务端的数据进行 MD5 算法得到一个MD5 的值,生成证书编号,使用第三方机构的私钥对这个证书编号进行加密,并且会在证书中添加证书编号的生成算法。
浏览器内置的 CA 公钥可以解密服务端 CA 私钥加密的证书,通过浏览器内置的 CA 证书的证书编号算法对服务端返回的证书编号进行验签。
第三方机构的公钥证书存哪里?
浏览器和操作系统都会维护一个权威的第三方机构(CA)列表(包括他们的公钥)因为客户端接收到的证书中会有颁发机构,客户端就根据这个颁发机构的值在本地找到对应的公钥
Https 原理分析
HTTPS 证书的申请过程
1. 服务器上生成 CSR 文件(证书申请文件,内容包括证书公钥、使用的 Hash 签名算法、申请的域名、公司名称、职位等信息)
2. 把 CSR 文件和其他可能的证件上传到 CA 认证机构,CA 机构收到证书申请之后,使用申请中的 Hash 算法,对部分内容进行摘要,然后使用 CA 机构自己的私钥对这段摘要信息进行签名(相当于证书的唯一编号)
3. 然后 CA 机构把签名过的证书通过邮件形式发送到申请者手中。
4. 申请者收到证书之后部署到自己的 web 服务器中
客户端请求交互流程
1. 客户端发起请求(Client Hello 包)
2. 服务端收到请求,然后响应(Server Hello)
3. 客户端收到证书进行验证
4. 服务端接收随机数
5. 客户端接收消息
https原理图: