转载自:https://www.toutiao.com/a6613628254299357703/?tt_from=mobile_qq&utm_campaign=client_share×tamp=1539909614&app=news_article&utm_source=mobile_qq&iid=46547913405&utm_medium=toutiao_android&group_id=6613628254299357703
写在前面
最近在看了解HTTP相关的一些知识,主要在看《图解HTTP》这本书,感觉还不错。所以结合自己的理解,做一下笔记。话说之前还大概过了下《HTTP权威指南》,感觉这本书内容过多了,不太适合新手看。新手还是建议看《图解HTTP》。
什么是HTTPS
HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。
HTTPS在应用层(HTTP)和传输层(TCP)之间加入了一个安全层(SSL或TLS)。目的是为了解决HTTP协议的几个缺点:
HTTPS是位于安全层之上的HTTP,这个安全层位于TCP之上
HTTP的几个缺点
通信使用明文(不加密),内容可能会被窃听。
HTTP协议并没有对通信以及数据进行加密,是明文发送的。而我们使用HTTP请求的时候,数据会经过许多个路由器,代理之类的设备,在这个过程中,只要有人在某一个环节抓取了数据包(这个操作并不难),那这个请求的数据就会被看到。如果请求里面有一些重要的数据,比如银行卡账号、手机号、密码等信息,就会有泄露的风险。
无法证明报文的完整性,所以有可能早已篡改。
由于HTTP协议无法证明通信的报文完整性,因此,在请求或响应送出之后直到对方接收之前的这段时间内,即使请求或响应遭到篡改,也没有办法获悉。
换句话说,没有任何办法确认,发出的请求/响应和接收到的请求/响应是相同的。
数据在传输过程中可能会遭到篡改
不验证通信方的身份,因此有可能遭遇伪装。
HTTP协议的实现本身非常简单,不论是谁发过来的请求都会返回响应,因此不确认通信方,会存在以下隐患:
即使是无意义的请求也会照单全收。无法阻止海量请求下的DoS攻击。
HTTP+加密+完整性保护+认证=HTTPS
我们来看下HTTPS是如何解决上面的问题的。
使用通信加密解决HTTP的明文发送问题
不同于HTTP的明文通信,HTTPS的通信是经过加密的。所以,就算有人在通信的过程中抓取到了数据包,因为没有密钥,所以无法知道数据包的具体内容,这样可以对传输的数据进行保护。
HTTPS中,网络传输的数据(请求和响应)都是经过加密的
HTTPS通信中,客户端和服务器都会有两个相同的通信密钥(设为密钥A),客户端发送请求时,会使用密钥A对请求进行加密成密文,服务器接收到请求之后,会使用密钥A对请求内容进行解密,得到客户端发送的明文,进行处理。响应过程也相似。
因此,在网络传输的过程中,因为数据被加密了,所以就算有人获取到了数据包,因为没有密钥A,所以就无法解密出数据包的内容,看到的是一堆乱码。
像这种加密和解密都是使用同一个密钥的加密方式叫做对称加密(也叫共享加密,共同拥有一个密钥)。使用密钥A加密的内容,只能用密钥A来解密,其他的密钥都无法解密。常用的对称加密算法有DES,3DES,AES。
还有一种加密方式叫非对称加密(也叫公开密钥加密)。非对称加密需要使用两个密钥,公开密钥(public key)和私有密钥(private key)。公开密钥是公开的,所有人都知道。私有密钥是保密的,除了自己,不让任何人知道。
HTTPS不仅仅使用了对称加密的方式,还使用了非对称加密的方式。事实上,HTTPS通信过程中,客户端会持有一个公钥,服务器会持有一个私钥。使用非对称加密可以完成好几个关键的操作。比如验证身份,比如协商通信的对称密钥,比如数据传输过程中加密摘要。
HTTPS中使用摘要算法来验证数据完整性,使用非对称密钥加解密摘要,使用对称密钥对数据进行加解密
如上图所示,在请求和响应过程中,除了加密后的数据,还会发送一个报文摘要,通过这个摘要,可以验证数据是否被篡改。
拿响应为例,
然后客户端会将自己计算出来的摘要跟服务器发送过来的摘要进行对比,如果两个是相同的,那么证明服务器发出的响应数据跟客户端收到的响应数据是相同的。也就是数据是完整的,没有丢失,也没有遭到篡改。
但是这里的前提是,服务器发过来的摘要没有被篡改,如果有人在篡改了数据之后,连摘要也改了,那就有点坑了。所以HTTTPS会使用非对称加密对摘要进行加密,防止摘要被篡改。
然后客户端会将自己计算出来的摘要跟解密出来的服务器发送过来的摘要进行对比,如果两个是相同的,那么证明服务器发出的响应数据跟客户端收到的响应数据是相同的。也就是数据是完整的,没有丢失,也没有遭到篡改。
为什么非对称加密可以保证服务器发送的摘要不被修改呢?
因为私钥只有服务器有,也就是说,只有服务器能够使用私钥进行加密。而使用私钥加密的数据,只有公钥可以解密。换句话说,用公钥能够解密出来的数据,就是使用私钥加密过的。所以,只要客户端使用公钥能够解密出来加密过的摘要,那么这个摘要就是服务器使用私钥加密的。而且私钥只有服务器知道,别人无法篡改加密后的摘要。
这里其实我有个疑问,反过来,在请求过程中,客户端使用公钥加密摘要,然后服务器私有私钥解密摘要。貌似只有证明这个摘要是使用公钥加密的,但是,公钥是公开的,别人也能知道,那别人不就可以篡改这个摘要?
使用数字证书验证服务器的身份
HTTPS是如何确认服务器的真实性的呢?也就说,怎样确认跟客户端通信的服务器就是我们的域名指向的服务器,而不是其他服务器冒充的?
HTTPS采用非对称加密方式解决问题。
服务器拥有私钥,这个私钥只有服务器有,所以,只要客户端拥有服务器的公钥,那么,当服务器使用私钥加密数据发送给客户端,而客户端能够解密出数据,说明公钥和私钥是配对的,而公钥是对应着我们想要的那个服务器的,所以就代表服务器是真的。
那么问题又来了,我们怎么拿到该服务器的公钥呢?在客户端内置?怎么多网站,怎么看都不现实。
那我们就在建立连接的时候发送给客户端。
嗯,HTTPS就是这么做的。
不对,那发送公钥的时候,公钥也可能被篡改啊,要是被篡改成其他服务器的公钥,以后就是跟其他冒充的服务器通信了,那怎么玩?
嗯,HTTPS引入了权威的第三方机构来确保这个公钥确实是该服务器的。
如果要使用HTTPS,服务器管理人员需要向CA(权威的证书颁发机构)购买证书。CA会将该服务器的域名、公钥、公司信息等内容封装到证书中。并且使用CA自己的私钥对证书进行签名。那么,服务器将证书发给客户端,客户端如果验证出证书是有效的,并且证书的域名跟目前通信的域名一致,那么这个证书里面的公钥就是有效的。而且当前是域名指向的服务器的公钥。所以,我们就能确保拿到的公钥是真的了。
嗯,这个CA机构颁发的证书就叫做数字证书。
问题又来了,客户端如何验证服务器发过来证书是有效的呢?
证书上有CA用其私钥做的签名,而一般客户端都会内置这些权威机构(CA)的公钥的,所以能够直接拿到CA的公钥对证书上的签名进行解密,然后自己根据证书上的说明计算摘要,两个摘要一致的话,代表证书是有效。因为只有CA自己才有私钥,别人是不可能冒充这个签名的。
说了那么多,HTTPS在连接建立时会发给客户端一个数字证书,客户端验证了数字证书之后,就能确认服务器的身份。同时还可以用数字证书上的公钥加密随机生成的共享密钥A,与服务器协商接下来通信过程中加密数据所用的共享密钥A。
HTTPS握手过程
HTTPS握手过程
SSL 协议既用到了公钥加密技术又用到了对称加密技术,对称加密技术虽然比公钥加密技术的速度快,可是公钥加密技术提供了更好的身份认证技术。SSL 的握手协议非常有效的让客户和服务器之间完成相互之间的身份认证,其主要过程如下:
①客户端向服务器请求HTTPS连接。
客户端向服务器传送客户端SSL 协议的版本号,加密算法的种类,产生的随机数,以及其他服务器和客户端之间通讯所需要的各种信息。
②服务器确认并返回证书。
服务器向客户端传送SSL 协议的版本号,加密算法的种类,随机数以及其他相关信息,同时服务器还将向客户端传送自己的证书。
③客户端验证服务器发来的证书。
客户端利用服务器传过来的信息验证服务器的合法性,服务器的合法性包括:证书是否过期,发行服务器证书的CA 是否可靠,发行者证书的公钥能否正确解开服务器证书的“发行者的数字签名”,服务器证书上的域名是否和服务器的实际域名相匹配。如果合法性验证没有通过,通讯将断开;如果合法性验证通过,将继续进行第四步。
④信息验证通过,客户端生成随机密钥A,用公钥加密后发给服务器。
从第③步验证过的证书里面可以拿到服务器的公钥,客户端生成的随机密钥就使用这个公钥来加密,加密之后,只有拥有该服务器(持有私钥)才能解密出来,保证安全。
⑤服务器用私钥解密出随机密钥A,以后通信就用这个随机密钥A来对通信进行加密。
我们这个握手过程并没有将验证客户端身份的逻辑加进去。因为在大多数的情况下,HTTPS只是验证服务器的身份而已。如果要验证客户端的身份,需要客户端拥有证书,在握手时发送证书,而这个证书是需要成本的。