什么是HTTPS
HTTP协议是明文传输
明文传输简单来说,你想发送123,那么你发送给tcp层的实际值就是123,而不是特殊编码后的值。
明文传输的问题
我们都知道,浏览器与服务器之间的通讯需要通过各种路由器、网关、运营商设备的中转。因此,明文传输意味着在传输过程的任意一个节点上,黑客都可以拦截传输,查看和修改传输的内容,造成一些攻击、安全、信息泄漏问题。注意,此处我们说的是传输过程中的拦截,所以拦截只会发生在TCP或IP层,并不会发生在HTTP层,HTTP层的攻击只能通过服务器的逻辑判断来辨别,比方说校验用户输入的内容是否符合要求。
到了现代,安全问题越来越受到重视,需要对HTTP进行改造,进行加密,让它在传输过程中,黑客虽然能够拦截请求,但是无法进行解密,不知道拦截的内容具体是什么,安全问题就可以解决了。HTTPS应运而生。
HTTPS协议
HTTPS并不是一个全新的协议,而是在HTTP协议和TCP协议之间加了一层安全层,有SSL和TLS,这俩先不做区分,只是版本不同。
也就是说,我们依旧需要使用HTTP,而且HTTP依旧是明文传输,看下图,只不过我们发送数据时在ssl层把http层的明文数据加密后再发送给TCP,接收方SSL层对接收到的TCP层的密文数据进行解密,把解密后的数据传给http层。在这个过程我们需要保证加密和解密的密钥不能让黑客知道,让黑客无法加密解密。因此https只是HTTP+SSL/TLS的组合,并不是真正意义上的一个新的协议,SSL和TLS才是新的协议。接下来将介绍,SSL层是如何对数据进行加密和解密的。
如何对数据加密
加密类型
先来了解下两种加密类型:对称加密和非对称加密。
对称加密:通信双方采用同一个密钥对传输数据进行加密和解密,加密后形成的结果自然也一模一样(只有一个密钥)。
非对称加密:通讯双方采用两个不同的密钥A、B对数据进行加密,使用密钥A加密的数据只能用密钥B解密,反过来,使用密钥B加密的数据只能用密钥A解密(两个不同的密钥)。
有的人想问,非对称加密这么神奇?是的。具体原理涉及到密码学的知识,不用去研究。
知道了加密类型,我们针对上面的问题,出几个方案。
几个加密方案
- 使用对称加密
浏览器使用一个密钥对发送数据进行加密,并把密钥传输给服务器,让服务器使用该密钥进行加密和解密。这样一来,浏览器加密后的数据,服务器收到后就能解开查看内容。
但是,http是明文传输,把密钥发给服务器的过程中,黑客从TCP层拦截下来是可以清楚的看到密钥的内容的。因此,黑客也可以用这个密钥对伪造数据进行加密。
所以这种加密方式无效,放弃。
- 使用非对称加密
服务器生成一个密钥B,这个密钥B只有服务器自己知道,不对外传输。然后再生成一个密钥A,这个密钥A会发送给浏览器,让它用该密钥A进行数据加密。
因为我们说过,非对称加密,使用A加密的数据,只能使用B密钥来进行解密。而B密钥始终没有对外传输过,只有服务器自己知道,所以除了服务器以外,没有人能解开这段由密钥A加密的数据。
这听起来很完美,但是有两个问题。
非对称加密非常消耗性能,如果每个传输过程都进行加密解密,那速度简直慢到吐。
虽然只有服务器能够解密浏览器传输过来的数据,但是因为密钥A是服务器通过明文传输,传给浏览器的,所以,可以说密钥A是公开的,大家都可以知道。有了密钥A,我们就可以随意地解密服务器传输过来的数据了,因为服务器传输过来的数据是用密钥B加密的,自然我用密钥A可以解密。这就泄露了服务器返回的信息。
因此,这个方案也不行,放弃。
- 认证阶段使用非对称加密,传输阶段使用对称加密
上面说到非对称加密特别损耗性能,所以,传输过程中绝对不能用非对称加密,而应该使用对称加密。
对称加密只需要一个密钥,而且这个密钥必须双方都得知道。但是又不能直接通过传输来告诉对方,那可怎么办呢?只有一个办法,不经过传输,那就是让他们各自生成一个密钥,而且生成的这个密钥是一模一样的。
神奇?他们不交流,怎么能生成一模一样的密钥呢?
他们不是不交流,而是不直接交流密钥,而是只交流一个随机数X。
我们可以利用一次非对称加密,来实现一个场景:浏览器生成一个随机数X,然后用密钥A(公开的密钥,以下称它为公钥),对X进行加密,然后传输到服务端,因为加密后的X只能由服务端的密钥B来解密,即使黑客拦截到了加密后的X,他也获取不了内容。服务端用密钥B(服务器私有的密钥,以下称它为私钥)来解密得到X。
此时,浏览器端和服务端有了一个只有他俩才知道的数X。
双方用相同的加密规则,对这个数X进行处理,就可以生成一模一样的密钥了。(这个加密规则可以是固定的,也可以是传输过程中商量好的,都可以,因为数值X已经保证不对外暴露了)
双方之后的数据传输都使用这个密钥进行加密,除了他俩,不管是谁,都无法进行解密了。黑客拦截之后也没有用。
这个方案可行。只不过实际需要的参数,比我这里说的更多一点,原理相同。
但是,这个方案还有一个问题,如果黑客把我的请求给转到一个黑客服务器上怎么办(通过DNS劫持,更改目标ip地址),我浏览器这边根本不知道对面是真是假,黑客服务自己搞一个公钥和私钥,完全可以正常进行通讯,这不就又有安全问题了吗?我怎么能知道当前给我返回数据的服务器就是我要找的那台服务器呢?
来看第四个方案-数字证书。
数字证书
日常生活中,只有证件才表明你对某个物件的合法所有权,比如房产证可以证明房子是你的,大家都相信房产证的颁发机构不会弄虚作假,社会都认可房产证。同理,你要证明这台服务器就是你自己的,办法就是找一个大家都相信的机构(Certificate Authority,以下称CA,来给你签发证书。因此,在这里有个大前提:所有的浏览器都会完全信任证书颁发机构,认为他们颁发的证书都是真实有效的。没有这个基础,不可能建立起信任体系。浏览器端验证一下证书是否有效就可以得知该请求安不安全。
企业去认证机构申请证书,表明自己的公司名、地址、公钥等信息,通过一系列材料来证明企业是真实存在的。然后认证机构就给他颁发个证书,公司只提供公钥,私钥不对外公开,只有自己知道。
在第三种方案中,服务器会返回给浏览器一个公钥。而在数字证书这个方案中,服务器会返回它的数字证书,数字证书中包含该服务器的公钥和认证机构的信息。浏览器会验证该证书上的数字签名是否是该认证机构颁发的,如果是,那就表明这正是我想要访问的服务器。反之,就会弹出安全警告。
数字证书安全吗
我们看下数字证书的生成和认证过程。
在这里先明确几点:
证书的颁发机构本身也是有数字证书的,是由它的上级机构颁发给它的。
证书颁发机构也是有自己的公钥和私钥。注意和申请证书的企业的公钥和私钥区分开。
证书的电子签名也是加密的,而且是非对称加密。
生成过程:
数字证书包含两部分:明文信息和数字签名。
明文信息就是企业申请证书时的资料,包含公司名、公司的公钥等
数字签名是将明文信息进行摘要算法处理生成一个摘要信息,对摘要信息使用认证机构的私钥进行加密而成。
认证过程:
首先浏览器端和服务器要先建立TCP连接,三次握手这是必须的。
握手之后,服务器向浏览器返回自己的数字证书。
客户端拿到证书的两个部分:明文信息和数字签名。
对明文信息使用摘要算法处理生成一个摘要信息A,这个摘要算法和CA生成证书时的那个算法一致。
浏览器端会内置认证机构的数字证书,该证书包含该认证机构的公钥,使用该公钥可以对服务器的数字证书签名进行解密,得到摘要信息B。
比对下摘要信息A和B,一样就是有效的证书,就可以认为这是正确的那个服务器。
之后就可以生成随机数X,使用该服务器的公钥来加密,传给服务端。后面的就跟方案三一致了。
但是证书难道就不能伪造吗?答案是不能。我们在下面做探讨。
下面是我的猜想哈,不一定对。
既然服务器的数字证书是公开的,那么我获取到了之后可以进行更改吗?或者说我可以冒充它吗?
获取后修改。修改了数字证书明文信息中的企业公钥,浏览器端解析出来的摘要信息A就变了,和摘要信息B就会不一致。同理,修改了数字签名,也会产生不一致的摘要信息。
获取后复制为自己所用。因为没有企业的私钥,一样解不开浏览器端传的数据,因此生成的随机数X,服务端也解不出来。
证书链
证书的签发机构有很多,如果浏览器不识别某个证书的颁发机构A,那么就会寻找机构A的电子证书的颁发机构B,如果浏览器也不认识B,那就找给B颁发证书的机构C。就这样一直的往上找,直到能识别或者是到了根证书。