共计 2276 个字符,预计需要花费 6 分钟才能阅读完成。
大多使用 HTTPS 协议的原因是因为 HTTP 在使用上是不如 HTTPS 安全的。比如当我们在往服务器发送比较隐私的数据时,如果使用 HTTP 进行通信,安全性没办法得到保障。数据在传输的过程中,是比较容易被中间人抓包窃取的。
其次,如果在不安全的环境下发送数据,数据也有可能在传输过程被篡改,当接收数据的服务器收取数据时,也没办法确定数据是否有被修改和替换过。当然,服务器也没办法判断数据就是真的来源于客户端。
<< 阿里云 SSL 证书,2 年仅需 567 元
目前,HTTP 是存在一些弊端的,例如无法保证保密性,没法保证消息的完整、准确性,没法保证消息的可靠性。对比于这些问题,HTTPS 是可以解决掉的。可以间接的把 HTTPS 理解为 HTTP 的升级版,包容了 HTTP 的功能,并逐步在 HTTP 的基础上增加了安全性能。
为 http 的内容是明文传输的,明文数据会经过中间代理服务器、路由器、wifi 热点、通信服务运营商等多个物理节点,如果信息在传输过程中被劫持,传输的内容就完全暴露了,他还可以篡改传输的信息且不被双方察觉,这就是中间人攻击。所以我们才需要对信息进行加密。最简单容易理解的就是对称加密。
为了保证消息的保密性,就会涉及到加密和解密的问题。目前主流的分为对称加密和非对称加密两种。
什么是对称加密?
就是有一个密钥,它可以对一段内容加密,加密后只能用它才能解密看到原本的内容,和我们日常生活中用的钥匙作用差不多。
用对称加密可行吗?
如果通信双方都各自持有同一个密钥,且没有别人知道,这两方的通信安全当然是可以被保证的(除非密钥被破解)。
然而最大的问题就是这个密钥怎么让传输的双方知晓,同时不被别人知道。如果由服务器生成一个密钥并传输给浏览器,那这个传输过程中密钥被别人劫持弄到手了怎么办? 之后他就能用密钥解开双方传输的任何内容了,所以这么做当然不行。
换种思路? 试想一下,如果浏览器内部就预存了网站 A 的密钥,且可以确保除了浏览器和网站 A,不会有任何外人知道该密钥,那理论上用对称加密是可以的,这样浏览器只要预存好世界上所有 HTTPS 网站的密钥就行啦! 这么做显然不现实。
什么是非对称加密?
有两把密钥,通常一把叫做公钥、一把叫做私钥,用公钥加密的内容必须用私钥才能解开,同样,私钥加密的内容只有公钥能解开。
用非对称加密可行吗?
鉴于非对称加密的机制,我们可能会有这种思路:服务器先把公钥直接明文传输给浏览器,之后浏览器向服务器传数据前都先用这个公钥加密好再传,这条数据的安全似乎可以保障了! 因为只有服务器有相应的私钥能解开这条数据。
其实 HTTPS 的加密原理,主要在于充分利用了对称加密和非对称加密的优点,以及数字证书的作用。根据加密的特点,将 HTTP 进行了一次升级,升级到 HTTPS 的形态,就具备了一层加密的外壳了。
非对称加密 + 对称加密?
既然非对称加密耗时,非对称加密 + 对称加密结合可以吗? 而且得尽量减少非对称加密的次数。当然是可以的,而且非对称加密、解密各只需用一次即可。
请看一下这个过程:
某网站拥有用于非对称加密的公钥 A、私钥 A’。
浏览器像网站服务器请求,服务器把公钥 A 明文给传输浏览器。
浏览器随机生成一个用于对称加密的密钥 X,用公钥 A 加密后传给服务器。
服务器拿到后用私钥 A’解密得到密钥 X。
这样双方就都拥有密钥 X 了,且别人无法知道它。之后双方所有数据都用密钥 X 加密解密。
完美!HTTPS 基本就是采用了这种方案。完美? 还是有漏洞的。
为什么制作数字签名时需要 hash 一次?
我初学 HTTPS 的时候就有这个问题,似乎以上过程中 hash 有点多余,把 hash 过程去掉也能保证证书没有被篡改。
最显然的是性能问题,前面我们已经说了非对称加密效率较差,证书信息一般较长,比较耗时。而 hash 后得到的是固定长度的信息(比如用 md5 算法 hash 后可以得到固定的 128 位的值),这样加密解密就会快很多。
怎么证明 CA 机构的公钥是可信的?
你们可能会发现上文中说到 CA 机构的公钥,我几乎一笔带过,“浏览器保有它的公钥”,这是个什么保有法? 怎么证明这个公钥是否可信?
让我们回想一下数字证书到底是干啥的? 没错,为了证明某公钥是可信的,即“该公钥是否对应该网站 / 机构等”,那这个 CA 机构的公钥是不是也可以用数字证书来证明? 没错,操作系统、浏览器本身会预装一些它们信任的根证书,如果其中有该 CA 机构的根证书,那就可以拿到它对应的可信公钥了。
实际上证书之间的认证也可以不止一层,可以 A 信任 B,B 信任 C,以此类推,我们把它叫做信任链或数字证书链,也就是一连串的数字证书,由根证书为起点,透过层层信任,使终端实体证书的持有者可以获得转授的信任,以证明身份。
另外,不知你们是否遇到过网站访问不了、提示要安装证书的情况? 这里安装的就是跟证书。说明浏览器不认给这个网站颁发证书的机构,那么没有该机构的根证书,你就得手动下载安装(风险自己承担 XD)。安装该机构的根证书后,你就有了它的公钥,就可以用它验证服务器发来的证书是否可信了。
HTTPS 必须在每次请求中都要先在 SSL/TLS 层进行握手传输密钥吗?
这也是我当时的困惑之一,显然每次请求都经历一次密钥传输过程非常耗时,那怎么达到只传输一次呢? 用 session 就行。
服务器会为每个浏览器 (或客户端软件) 维护一个 session ID,在 TSL 握手阶段传给浏览器,浏览器生成好密钥传给服务器后,服务器会把该密钥存到相应的 session ID 下,之后浏览器每次请求都会携带 session ID,服务器会根据 session ID 找到相应的密钥并进行解密加密操作,这样就不必要每次重新制作、传输密钥了!