Https
一.为什么出现https
说到https,我们自然就会想到http.因为就光从字面意义上来讲,https就仅仅比http多了一个s。http是一种超文本传输协议,是无状态的、基于TCP的可靠传输协议。但http有一个最大的问题,它是以明文的形式进行传输,由于数据在网络中传输的时候,并不是直接的点对点传输,而是要经历好多的节点进行转发,所以数据包就很容易被劫持,那么数据就完全暴露在阳光下,没有什么秘密可言,所以安全性极低。那怎么解决这个问题呢?我们自然很容易想到了,把数据加密传输,这样即使被劫持,也无法知道我的真实数据是什么。所以,这就产生了https。
说到这里,那么http主要会产生哪些安全问题呢?
- 窃听风险(eavesdropping):第三方可以获知通信内容;
- 篡改风险(tampering):第三方可以修改通信内容;
- 冒充风险(pretending):第三方可以冒充他人身份参与通信。
二.https是什么
如果给https加个定义的话,那么https是一种通过计算机网络进行安全通信的传输协议,经由http进行通信,利用SSL/TLS建立全信道,加密数据包。https使用的主要目的是提供对网站服务器的身份认证,同时保护交换数据的隐私与完整性。说白了,https就是http+SSL,(所以https并不是http的复数,呵呵)。那么什么是SSL呢?SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议,负责在传输层对网络连接进行加密。SSL主要作用:
- 认证用户和服务器,确保数据发送到正确的客户机和服务器;
- 加密数据以防止数据中途被窃取;
- 维护数据的完整性,确保数据在传输过程中不被改变。
正是有了SSL的加持,就解决了上面所说的http的三种安全问题。
三.https解决了什么问题
1.解决的三大问题
- 传输过程中所有数据都是加密的,防止了第三方窃听;
- https的校验机制,一旦数据被篡改,通信双方就会立即发现;
- 具有身份证书,防止了身份被冒充。
下面我们就分别看看是怎么解决这些问题的。
2.解决问题的推演过程
1.数据是如何加密的
在使用http请求时,数据是以明文的方式进行传输的,那么在整个传输过程中,会经过很多节点(操作系统、网关、路由、ISP互联网那供应商),那么每个节点都有可能窃听到传输的数据,因为数据是以明文形式传输的。
既然这样,那么将明文数据加密成密文进行传输,就能解决这个问题。那么怎么加密呢?首先,利用MD5这样的摘要算法肯定是不行的,因为这样密文是不可逆的,所以要采用加密算法,例如移位或者混淆等。
但这种算法只能在一定程度上解决这个问题。为什么呢?原因有以下几点:
1.client端不是一个,而是很多,这样所有的client都必须支持我自己所定义的这种算法,显示不合适,不可能让每个浏览器为每个应用都嵌入一个算法;
2.即使客户端浏览器嵌入了这个算法,由于这个算法是在前端,显然无法保证算法不被外界所知,那么这时候一旦算法泄露,那么这样的密文就没有安全性可言了。
那么怎么进一步解决这个问题呢?想想我们在存储密码的时候,很多使用MD5+盐的方式,才增加密码的强度,那么这里,如果给我们的算法传入一个随机盐,只要保证这个随机盐只有客户端和服务端知道,其他任何人都不知道就行了。
这就可以利用对称加密算法,如DES 、3DES、AES等。
所谓对称加密算法,就是加密和解密都是一个密钥,加密解密过程:明文->密钥加密->密文,密文->密钥解密->明文,其中的密钥就可以理解为我们上面所说的随机盐,只要保证盐不丢失或者盐不被窃取,就基本能够保证密文安全性。
那么问题来了,由于这个随机盐是应该放在哪里或者应该怎么保护这个随机盐呢?有两种方式:放在服务端或者内置在浏览器中;下面我们看下这两种方式:
1.随机盐放在服务端:那么客户端就要向服务端请求这个随机盐或者服务端向客户端直接下发这个随机盐,但是无论采用哪种方式,它在经过网络中的各个节点时,都能很容易的被别人窃取,显示这样不合适;
2.内置在客户端:那么所有的浏览器都要为每个应用放置一个内置的盐,并且这个盐还是固定的,那就相当于向所有人公布了这个盐,只要知道这个盐,就可以利用对称加密算法解密了。
既然上面两种存放方式都不行,那应该怎么办呢?既然放到哪里都不合适,我们是不是可以采用另外一种算法,再对这个随机盐进行加密的,来保证只能客户端和服务端能解开这个密文,获取到随机盐呢?这时候我们自然会想到非对称加密算法。
所谓非对称算法,就是需要两个密钥:公钥(publickey) 和私钥(privatekey) ,公钥和私钥是一对,私钥是由公钥生成的。非对称加密算法的加密和解密有以下几个原则(这个特性非常重要):
1.公钥加密,私钥能解;
2.私钥加密,公钥能解;
3.公钥加密,公钥不能解。
由于非对称加密算法(如RSA)的加密解密速度要比对称算法速度慢很多,所以在实际应用中,通常采取数据本身的加密和解密使用对称加密算法(如AES), 用非对称加密算法(如RSA)加密并传输对称算法所需的密钥(盐),这也是现在这里采用的方式。好了,那我们再考虑下,这个对称加密的公钥和私钥又应该放在哪里?
1.私钥:很显然私钥要放在服务端,这个没有什么好说的;
2.公钥: 如果公钥是放在客户端,那么每个浏览器都要单独为每个应用内置一个公钥,这显然是不现实的,所以公钥应该放到服务端,由私钥生成公钥,再由客户端来请求服务端获取公钥,然后存储在客户端。那就是下面的逻辑:
然后再进行数据的传输:
这样就解决数据被窃取或者偷窥的问题。既然数据在网络节点中连看都无法看(偷窥),那么显然,数据也就无法被篡改,因为你不知道数据是什么样的。这时候我们可能会有这样的考虑,上面客户端从服务端获取公钥的时候,显然网络节点是能够窃取到公钥的,那么这时候是不是可以篡改数据呢?那么我们看下:
从上图中的过程(主要是虚线部分)中看到,由于在传输过程中,客户端初始的随机盐被修改了,所以导致客户端是无法解密利用伪造的盐而响应的密文,客户端也就没办法看到伪造的数据,所以这种方式没有什么意义。
但是到目前为止,身份冒充的问题。下面我们继续分析。
2.如何保证身份不被冒充
我们还是接着上面的图来说,如果我把图稍微改一下:
看上图中实线部分,此时网络节点直接冒充服务端,自身伪造出假私钥和假公钥,由服务节点来代替真正的服务端来给客户端提供响应,那么这样客户端接到的数据就是被其他身份(网络节点)冒充的, 而不是由真正的server端响应的。所以,只靠非对称加密,也无法解决http产生的问题,客户端无法判断公钥是否是那个server端下发的。那么应该如何核实身份呢?
其实说白了,就是如何保证公钥不会被网络节点给伪造。那最好有一个专门的可信任的机构,来保证或者验证公钥的可信任度,也就是说不是什么人生成的公钥都是可信任的,只有我这个第三方机构说你的公钥是正确的,那才是正确的,否则,就是伪造的公钥,所以这里就引出了第三方机构。那么,这个第三方机构又是如何保证服务端的公钥没有被伪造呢?想一下,在平时开发中,我们是如何验证数据一致的?比如说登录时是如何验证密码是否一致呢?很显然,我们采用的hash摘要算法,如MD5。这里我们一样可以借鉴这样的做法,对公钥进行hash,然后客户端比对两次hash的摘要是否一致。
所谓摘要算法,就是相同的数据,hash算法结果一致。
那么第三方机构是如何保证服务端的公钥是可信任和一致的呢?
1.要保证网站的在第三方机构的信任列表里,只有网站在第三方机构的信任列表里,他才会用机构自己的私钥给网站服务端的公钥(server.公钥)进行非对称加密(如RSA),加密方法为:RSA(第三方机构的私钥,网站服务端的公钥)进行非对称加密,假设加密的结果为a;
2.客户端要内置第三方机构的公钥,用于解密出网站服务端的公钥(server.公钥),即server.公钥;
3.第三方机构使用hash摘要算法,对网站服务端公钥(server.公钥)进行hash摘要算法,即hash(server.公钥),称为签名;
除了第三方机构外,上面我们提到的hash摘要算法到底是具体哪种算法,也要告诉客户端,这样客户端来验证server.公钥是否被伪造了。
所以,当客户端向服务端请求公钥(server.公钥)时,就不再是简单的返回公钥(server.公钥)了,还要返回RSA(第三方机构的私钥,server.公钥)、hash摘要算法(即签名算法)、签名、第三方机构的名称等,我们把这些信息统一包装起来,就称为证书,这里的第三方机构,就称为CA证书的颁发机构,简称CA。这样客户端向服务端请求公钥的过程就变成下面的样子了:
并且这个过程中,网络节点是不可能伪造服务端的公钥的,如下图所示:
3.https证书下发过程及数据加密
https和http请求的过程基本是一样的,只是多了一个客户端和服务端协商,获取数字证书的过程,也可以理解为建立一个安全的隧道,来保证数据传输的安全性。
四.小结
到这里,整个原理就分析完了,中间的推演过程比较绕一些。中间有错误的地方,希望多多指教。