HTTPS
HTTPS也是一个应用层协议.在HTTP协议的基础上引入了一个加密层.
HTTP协议内容都是按照文本的方式明文传输的.
这就导致了在传输过程中出现了一些被篡改的情况.
臭名昭著的"运营商劫持"
下载一个天天动听.
未被劫持的效果,点击下载按钮,就会弹出天天动听的下载链接.
已被劫持的效果,点击下载按钮,就会弹出QQ浏览器的下载链接.
由于我们通过网络传输的任何数据包都会经过运营商的网络设备(路由器,交换机等),那么运营商的网络设备就可以解析出你传输的内容,并进行篡改.
点击"下载按钮",其实就是在给服务器发送了一个HTTP请求,获取到的HTTP响应就包含了该APP的下载链接.运营商劫持之后,就发现这个请求是要下载天天动听,那么就自动把交给用户的响应给篡改成"QQ浏览器"的下载地址了.
当然,他们这么做,是为了钱~
不止运营商可以劫持,其它的黑客也可以用类似的手段进行劫持,来窃取用户隐私信息,或者篡改内容
试想一下:如果黑客在用户登录支付宝的时候获取到用户余额,甚至是密码~
在互联网上,明文传输是比较危险的事情!!!
HTTPS就是在HTTP的基础上进行了加密,进一步来保护用户的信息安全~
"加密"是什么
加密就是把明文(要传输的信息)进行一系列变换,生成密文.
解密就是把密文再进行一系列变换,还原成密文.
在加密和解密的过程中,往往需要一个或者多个的中间数据,辅助进行这个过程,这样的数据称为密钥.
HTTPS的工作过程
既然要保证数据安全,就需要进行"加密".
网络传输中不再直接传输明文,而是加密以后的"密文".
加密的方式有很多,但可以整体分为两大类:对称加密和非对称加密.
引入对称加密
对称加密其实就是通过同一个"密钥",把明文加密成密文,
一个简单的对称加密,按位异或.
假设明文a=1234,密钥key=8888
则加密a^key得到的密文b为9834.
然后针对密文9834再次运算b^key,得到的就是原来的明文1234.
(当然对于字符串的对称加密也是同理,每一个字符都可以表示成一个服务器).
当然,按位异或只是最简单的对称加密,HTTPS中并不是使用按位异或.
引入对称加密之后,即使数据被截获,由于黑客不知道密钥是啥,因此就无法解密,也就不知道真实的请求内容是啥了.
但是事情没有这么简单,服务器同一时刻肯定是给很多客户端提供服务的.这么多客户端,每个人用的密钥都必须是不同的(如果是相同那密钥就容易扩散了,黑客也就拿到了),因此每个服务器就需要维持每个客户端和每个密钥之间的关联关系,这也是个很麻烦的事情~
比较理想的做法,就是能在客户端和服务器建立连接的时候,双方协商确定这次的密钥是啥~
但是如果直接把密钥明文传输,那么黑客也就能获取到密钥了~后续的加密操作也就形同虚设了.
因此密钥的传输也必须加密传输!
但是想要对密钥进行对称加密,就仍然需要先协商确定一个"密钥的密钥".这个也会被黑客截获,所以密钥的传输再用对称加密就行不通了.就需要引入非对称加密.
引入非对称加密
非对称加密要用到两个密钥,一个叫做"公钥",一个叫做"私钥".
公钥和私钥是配对的,最大的缺点就是运算速度非常慢(因此不会用来加密header和body的,只用来加密对称密钥),比对称加密要慢很多.
通过公钥对明文加密,变成密文.
通过私钥对密文解密,变成明文.
也可以反着用
通过私钥对明文加密,变成密文.
通过公钥对密文解密,变成明文.
举个栗子:A要给B一些重要的文件,因此A和B提前做出约定:
B说:我桌子上有一个盒子,然后我给你一把锁,你把文件放盒子里用锁锁上,然后我回头拿着钥匙来开锁取文件.
在这个场景中,这把锁就相当于公钥,要是就是私钥.公钥给谁都行(不怕泄露),但是私钥只有B自己持有.持有私钥的人才能进行解密.
客户端在本地生成对称密钥,通过公钥加密,发送给服务器.
由于中间的网络设备没有私钥,即使截获了数据,也无法还原出内部的原文,也就无法获取到对称密钥.
服务器通过私钥解密,还原出客户端发送的对称密钥.并且使用这个对称密钥加密给客户端返回的响应数据.
后续客户端和服务器通信都只用对称加密即可.由于该密钥只有客户端和服务器两个主机知道,其它设备/主机不知道密钥,即使截获了信息也没有意义.
由于对称加密的效率比非对称加密高很多,因此只是在开始阶段协商密钥的时候使用非对称加密,后续的传输仍然使用对称加密.
那么接下来问题又来了:
客户端如何获取到正确的公钥?
客户端如何确定这个公钥不是黑客伪造的?
中间人攻击
黑客可以使用中间人攻击,获取到对称密钥.
服务器可以创建出公钥和私钥,那么黑客就可以冒充服务器,也创建出一个自己的公钥和私钥.
过程如下:
引入证书
服务端在使用HTTPS前,需要向CA机构申领一份数字证书,数字证书里含有证书申请者信息,公钥信息等.服务器把证书传递给浏览器,浏览器从证书中获取公钥就行了,证书就如同身份证,
证明服务端公钥的权威性.
分为六步:1.服务端申请认证(证书). 2.CA机构审核信息 3.CA机构为服务端签发证书
4.服务端给客户端返回证书 5. 客户端验证证书 6.客户端向服务端发起密钥协商.
这个证书可以理解成是一个结构化的字符串,里面包含了以下信息:
证书发布机构
证书有效期
公钥
证书所有者
签名
......
需要注意的是:申请证书的时候,需要在特定的平台生成,会同时生成一对儿密钥对儿,即公钥和私钥.这对密钥对儿就是用来在网络通信中进行明文加密及数字签名的.
此时就有:
一个关键问题:返回证书的时候,证书数据也是经过了黑客的设备,此时黑客是否能修改证书中的公钥?替换成自己的公钥呢?
不行!!! 客户端拿到证书之后,会先针对证书校验真伪.
证书的验证过程
关键就是证书的签名.
颁布证书的公正机构,会在发布证书的时候,给这个证书计算出一个校验和.
然后公证机构使用自己的私钥(和服务器的私钥无关)针对校验和进行加密,此时就得到了证书的签名. (市面上的公证机构一共也没多少.这些公证机构持有自己的私钥,对应的公钥都包含在常见的系统中,windows里面就内置了大量的公钥,如果没有,也可以额外安装).
此处所谓的签名本质上就是经过加密的校验和!!
当客户端获取到这个证书之后,会对证书进行校验(防止证书是伪造的).
1.判定证书的有效期是否过期.
2.判定证书的发布机构是否受信任(操作系统中已内置的受信任的证书发布机构)
3.把证书中其它的字段通过一系列算法(CRC,MD5等),得到一个较短的字符串=>校验和
如果两份数据的内容一样,此时,校验和,就一定是相同的.
如果校验和不同,两份数据的内容则一定不同.(逆否命题)
中间人有没有可能篡改该证书?
中间人篡改了该证书的明文.
由于他没有CA机构的证明,所以无法hash之后用私钥加密形成签名,那么也就没法对篡改后的证书形成匹配的签名.
如果强行篡改,客户端收到该证书后会发现明文和签名解密后的值不一致,则说明证书已被篡改,证书不可信,从而终止向服务器传递信息,防止把信息泄露给中间人.
中间人整个掉包证书?
因为中间人没有CA私钥,所以无法制作假的证书.
所以中间人只能向CA机构申请真的证书,然后用自己申请的信息进行掉包.
这个确实能做到证书的整体掉包,但是别忘记,证书明文中包含了域名等服务端认证信息,如果整体掉包,客户端依旧能够识别出来.
永远记住:中间人没有CA私钥,所以对任何证书都无法进行合法修改,包括自己的.