HTTPS协议
由于HTTP协议在通信过程中,是基于明文通信,并且底层是基于TCP/IP协议进行通信,那么按照 TCP/IP 协议族的工作机制,通信内容在所有的通信线路上都有可能遭到拦截和窃取。 窃取这个过程其实很简单,通过抓包工具Wireshark就可以截获请求和响应的内容。
https 安全传输协议
由于 HTTP 协议通信的不安全性,所以人们为了防止信息在传输过程中遭到泄漏或者篡改, 就想出来对传输通道进行加密的方式https。
https是一种加密的超文本传输协议,它与HTTP在协议差异在于对数据传输的过程中,https 对数据做了完全加密。由于http协议或者https协议都是处于TCP传输层之上,同时网络协 议又是一个分层的结构,所以在 tcp 协议层之上增加了一层 SSL(Secure Socket Layer,安全层)或者TLS(Transport Layer Security)
安全层传输协议组合使用用于构造加密通道; Ssl 是 netscape 公司设计的(Secure sockets layer),后来互联网标准化组织 ISOC 接替了 NETScape公司,发布了SSL的升级版TLS。接着TLS的版本又进行了多次升级; 实际上我 们现在的 HTTPS 都是用的 TLS 协议,但是由于 SSL 出现的时间比较早,并且依旧被现在浏览器所支持,因此SSL依然是HTTPS的代名词。
逆向推导 https 的设计过程
- 我们先不想ssl是如何实现的,假设我们需要自己在http协议的基础上对数据进行加密我们该如何去做?
从第一个消息开始
客户端A向服务端B发送一条消息,这个消息可能会被拦截以及篡改,我们如何做到A发送给B的数据包,及时被拦截了,也没办法得知消息内容并且也不能查看呢?
使用对称密钥
要做到消息不能被第三方查看以及篡改,那么第一想法就是对内容进行加密,同时,该消息还需要能被服务端进行解密。所以我们可以使用对称加密算法来实现,密钥 S 扮演着加密和解密的角色。在密钥S不公开的情况下,就可以保证安全性?
- 在互联网的世界中永远不可能只有一台客户端,一定是很多很多
- 那么这种情况下密钥不公开就相当于一个笑话了。
- 黑客拿到对称密钥,就可以得到想要的任何数据
- 那么一个密钥不行,我们给每个客户端都准备一个密钥。
- 问题又来了,客户端怎么知道到底使用什么密钥,那么首先想到的办法就是协商。
- 协商过程又是不安全的
- 第一次向服务端询问密钥的时候,肯定是明文协议,那么就可以拦截到这个请求,用自己的密钥进行掉包,然后返回给客户端,客户端用该密钥进行加密返回给中间端,然后在进行解密加密,返回给服务端,拿到真实数据。
-
黑客很轻松就能拿到数据
-
第二个问题,服务端存放这么多密钥消耗了这么大的空间,并且保存了这么多的解密算法,太浪费了。
非对称加密
非对称加密算法的特点是:私钥加密后的密文,只要有公钥,都能解密,但是公钥加密后的密文,只有私钥可以解密。私钥只有一个人有,而公钥可以发给所有人
这样就可以保证A/B向服务器端方向发送的消息是安全的。似乎我们通过非对称加密算法解决了密钥的协商的问题?
- 但是第一个问题又出来了,公钥怎么保证不被黑客拿到,如何黑客拿到公钥,拦截到服务端返回的信息又可以用公钥解密。
那么我们逐步思考,有两种我们能想到的方案:
- 服务器端将公钥发送给每一个客户端
- 服务器端将公钥放到一个远程服务器,客户端可以请求到 (多了一次请求,还得解决公钥 放置问题)
方案一肯定不行,传输过程不安全,公钥可能会被调包
方案二的思想貌似可行,我们可以找一个绝对信任的第三方机构
- 引入第三方机构
到上面这一步,最关键的问题是,客户端如何知道给我公钥到底是不是真的?只能找本人去证实?或者有一个第三者来帮你证实,并且第三者是绝对公正的。 所以,引入一个可信任的第三者是一个好的方案
服务端把需要传递给客户端的公钥,通过第三方机构提供的私钥对公钥内容进行加密后,再传递给客户端? 通过第三方机构私钥对服务端公钥加密以后的内容,就是一个简陋版本的 “数字证书”。这个帧数中包含【服务器公钥】
客户端拿到这个证书以后,因为证书是第三方机构使用私钥加密的。客户端必须要有第三方机构提供的公钥才能解密证书。这块又涉及到第三方机构的公钥怎么传输?(假设是先内置 在系统中)以及还有一个问题,第三方机构颁发的证书是面向所有用户,不会只针对一家发放。如果不法分子也去申请一个证书呢?
- 如果不法分子也拿到证书?
如果不法分子也申请了证书,那它可以对证书进行调包。客户端在这种情况下是无法分辨出收到的是你的证书,还是中间人的。因为不论是中间人的、还是你的证书都能使用第三方机构的公钥进行解密。
- 验证证书的有效性
事情发展到现在,问题演变成了,客户端如何识别证书的真伪?在现实生活中,要验证一个 东西的真伪,绝大部分都是基于编号去验证(比如大学毕业证书,比如买的数码产品是否是山寨),
我之前讲过,计算机领域的解决方案都是人为去实现的,所以在这里,解决方案也是一样,如果给这个数字证书添加一个证书编号?是不是就能达到目的呢? 证书上写了如何根据证书的内容生成证书编号。客户端拿到证书后根据证书上的方法自己生成一个证书编号,如果生成的证书编号与证书上的证书编号相同,那么说明这个证书是真实的。
这块有点类似于md5的验证,我们下载一个软件包,都会提供一个md5的值,我们可以拿到这个软件包以后通过一个第三方软件去生成一个 md5 值去做比较,是不是一样如果一样表示这个软件包没被篡改过
对发送给服务端的数据进行 MD5 算法得到一个 MD5的值,生成证书编号,使用第三方机构 的私钥对这个证书编号进行加密,并且会在证书中添加证书编号的生成算法
浏览器内置的 CA 公钥可以解密服务端 CA 私钥加密的证书,通过浏览器内置的 CA 证书的证书编号算法对服务端返回的证书编号进行验签
-
第三方机构的公钥证书存哪里?
浏览器和操作系统都会维护一个权威的第三方机构列表(包括他们的公钥) 因为客户端接收到的证书中会些颁发机构,客户端就根据这个办法机构的值在本地找到响应 的公钥说到这里,我想大家一定知道,证书就是HTTPS中的数字证书,证书编号就是数字签名,而第三方机构就是数字证书的签发机构(CA)
- Google浏览器内置证书
Https 原理分析
服务端 HTTPS 证书的申请过程
- 服务器上生成 CSR 文件(证书申请文件,内容包括证书公钥、使用的 Hash 签名算法、申请的域名、公司名称、职位等信息)
- 把 CSR 文件和其他可能的证件上传到 CA 认证机构,CA 机构收到证书申请之后,使用申请中的 Hash 算法,对部分内容进行摘要,然后使用 CA 机构自己的私钥对这段摘要信息进行签名(相当于证书的唯一编号)
- 然后 CA 机构把签名过的证书通过邮件形式发送到申请者手中。
- 申请者收到证书之后部署到自己的 web 服务器中
客户端请求交互流程
- 客户端发起请求(Client Hello包)
a) 三次握手,建立TCP连接
b) 支持的协议版本(TLS/SSL)
c) 客户端生成的随机数client.random,后续用于生成“对话密钥”
d) 客户端支持的加密算法
e) sessionid,用于保持同一个会话(如果客户端与服务器费尽周折建立了一个HTTPS链接, 刚建完就断了,也太可惜)
- 服务端收到请求,然后响应(Server Hello)
a) 确认加密通道协议版本
b) 服务端生成的随机数server.random,后续用于生成“对话密钥”
c) 确认使用的加密算法(用于后续的握手消息进行签名防止篡改)
d) 服务器证书(CA机构颁发给服务端的证书)
- 客户端收到证书进行验证
a) 验证证书是否是上级 CA 签发的, 在验证证书的时候,浏览器会调用系统的证书管理器 接口对证书路径中的所有证书一级一级的进行验证,只有路径中所有的证书都是受信的, 整个验证的结果才是受信
b) 服务端返回的证书中会包含证书的有效期,可以通过失效日期来验证 证书是否过期
c) 验证证书是否被吊销了
d) 前面我们知道CA机构在签发证书的时候,都会使用自己的私钥对证书进行签名证书里的签名算法字段 sha256RSA 表示CA机构使用sha256对证书进行摘要,然后 使用 RSA 算法对摘要进行私钥签名,而我们也知道 RSA 算法中,使用私钥签名之后,只有公钥才能进行验签。
e) 浏览器使用内置在操作系统上的CA机构的公钥对服务器的证书进行验签。确定这个证 书是不是由正规的机构颁发。验签之后得知CA机构使用sha256进行证书摘要,然后 客户端再使用sha256对证书内容进行一次摘要,如果得到的值和服务端返回的证书验签之后的摘要相同,表示证书没有被修改过
f) 验证通过后,就会显示绿色的安全字样
g) 客户端生成随机数,验证通过之后,客户端会生成一个随机数pre-master secret,客户端根据之前的:Client.random + sever.random + pre-master生成对称密钥然后使用证书中的公钥进行加密,同时利用前面协商好的 HASH 算法,把握手消息取 HASH 值, 然后用 随机数加密 “握手消息+握手消息 HASH 值(签名)” 并一起发送给服务端 ( 在这里之所以要取握手消息的 HASH 值,主要是把握手消息做一个签名,用于验证握手消息在传输过程中没有被篡改过。 )
- 服务端接收随机数
a) 服务端收到客户端的加密数据以后,用自己的私钥对密文进行解密。然后得到client.random/server.random/pre-master secret, HASH值,并与传过来的HASH值做 对比确认是否一致。
b) 然后用随机密码加密一段握手消息(握手消息+握手消息的HASH值 )给客户端
- 客户端接收消息
a) 客户端用随机数解密并计算握手消息的 HASH,如果与服务端发来的 HASH 一致,此时握手过程结束,
b) 之 后 所 有 的 通 信 数 据 将 由 之 前 交 互 过 程 中 生 成 的 pre master secret / client.random/server.random通过算法得出session Key,作为后续交互过程中的对称密钥
证书
在生产环境中的SSL 证书都需要通过第三方认证机构购买,分为专业版 OV 证书(浏览器地 址栏上不显示企业名称)和高级版EV(可以显示企业名称)证书,证书所保护的域名数不同 也会影响价格(比如只对www认证和通配*认证,价格是不一样的),且不支持三级域名。代 表证书过期或者无效,如果是黄色的话代表网站有部分连接使用的仍然是http协议。