本文全部的内容都是根据前言中的内容进行讲述。算法
人物:小蓝、小红、小黑。浏览器
事件:通讯安全
对称加密就是通讯的双方都持有同一个密钥,加密和解密都是使用这一个密钥进行的。举个例子:服务器
小蓝和小红互相写情书,可是他们不但愿他们之间的信件真实内容被其余人知道。那么他们要怎么保证他们的情书不被其余人知道呢?网络
由于信件是经过邮局进行邮寄,因此没有办法保证信件在运输途中不被小黑(小黑暗恋小红)阅读过。可是他们只要保证他们之间的信件别人看不懂就能够了,因此他们能够事先约定一个写信的规则,好比,每隔三个字取一个字或者只取每句话中间那个字等等的规则。并发
经过上面的这些规则,即便信件被小黑阅读了,可是只要小黑不知道这个规则,那么小黑就不知道信件要表达的内容是什么。从而达到了信件的真实内存不被小黑所知道。tcp
加密和解密的速度快,不会形成性能上太大的损失,尤为是在加密大量数据的状况下,更加明显。工具
对称加密最大的弊端就是商定加密规则的时候是不安全的。性能
由于小红和小蓝只能经过信件交流,因此他们的加密规则也是要经过信件进行传输的,可是这个信件是没有加密的,因此这个信件上的加密规则是能够被小黑获取而且解读出来的,只要小黑知道了这个加密规则,那么后面的全部信件的内容,小黑就均可以解读出来了。网站
为何要限制小蓝和小红只能经过信件交流,他们不能先私底下商量好加密规则吗?若是在真实生活中确实是能够的,可是若是在咱们的互联网环境下,咱们的网站是不可能跟全部用户都私底下商量密钥的,咱们只能经过一个请求生成一个对称密钥发送给用户,后续的通讯双方都使用这个对称密钥对内容进行加密和解密,可是一开始生成并发送密钥的这个请求是明文的,只要是明文的,那么就是有风险的。
非对称加密存在两个密钥,一个称为私钥,一个称为公钥。既可使用公钥加密,也可使用私钥加密。可是使用公钥加密,那么就只有私钥才能解密;使用私有加密,就只能使用公钥解密。
继续使用上面的场景,小红和小蓝发现他们的信件老是有被拆开的痕迹,他们意识到他们的信件被第三者阅读过,他们固然不乐意,本身的小秘密怎么能够被第三者亵渎。小蓝发现将密钥明文传输很是不安全,因此它决定将一个保险箱先传递给小红,而后小红将写好的信件放进保险箱中,而后上锁,而打开保险箱的钥匙只有小蓝才有,而且这个钥匙从未被其余人看到过。
其中,保险箱就是公钥,钥匙就是私钥。通过保险箱(公钥)加密的内容,只有钥匙(私钥)才能解开。
公钥是任何人均可以获取的。
通过公钥加密的内容,只有私钥才能够解开。
必须保证私钥不能泄露,不然将无加密可言。这个弊端仍是能够接受的。
非对称加密相对于对称加密而言性能损耗较大,因此通常状况下都会结合非对称加密和对称加密一块儿使用,https的作法就是如此。
可是非对称加密还有一个最大的漏洞:中间人攻击,如图所示,
咱们从中能够看到,最关键的部分就是小黑拦截了小蓝的保险箱,并将它替换为了本身的保险箱,可是小蓝和小红对此是一无所知的,由于小红不知道小蓝发送的保险箱是怎么样的,她只能肯定她能收到一个保险箱。而小蓝也不知道本身发送的保险箱被拦截了,由于他收到的回信中确实是他本身的保险箱,也能使用本身的钥匙打开。
众所周知,http在网络中传输的报文都是明文的,也就至关于咱们是在网络的世界中裸奔。咱们只要经过嗅探器Wireshark、tcpdump、dsniff等工具对网络中的信息进行获取,就能够获取到网络上其余人发送的信息。
https是由http协议 + tls / ssl 协议组合而成的。
https = http + tls / ssl
这是咱们使用http协议时能够接触获得的网络协议层:
这是咱们使用https协议时能够接触获得的网络协议层:
咱们能够看到https就是在TCP与HTTP之间加入了一个TLS/SSL层。
如下是访问掘金主页时,发生的网络请求,我经过Wireshark抓包来解析Https的握手过程。我会直接省略tcp的三次握手过程,只关注tls/ssl的握手过程。
IP协议层:左边红色方框的是个人内网地址,它会在访问外网的时候经过路由器的NAT协议转换为外网的地址,右边红色方框就是掘金的外网地址。
TCP协议层:左边红色方框的是我发送这条请求时使用的端口(也叫源端口),咱们接下来要使用这个端口(最好加上序号)来寻找服务器回复给个人信息。右边的红色方框就是我要访问的目的端口,这里能够看出Https使用的端口是443,而https的默认端口就是443,http协议的默认端口是80。
咱们大体能够理解为,IP是为了找到一台主机,而TCP是为了找到主机上的一个进程。
TLS协议层:比较重要的是蓝色方框中的内容。
服务端接受到客户端发送的Client Hello后,会当即发送一个该类型的信息。
咱们经过红色方框中的地址和端口号,能够肯定该信息会回复上面那条Client Hello的。
咱们依然看到蓝色方框中的内容:
此时客户端和服务端就已经协商好了版本号,密码套件,而且客户端和服务端都拥有了两个随机数。
紧接着Server Hello信息,服务端会马上发送一个Server Certificate信息,该信息包含了一个很重要的东西——CA证书,也就是咱们平时说的数字证书。
能够看到红色方框中的就是CA证书。
该证书一般有两个目的:
该消息是有条件才发送的,还记得刚刚在Server Hello中说的,选择不一样的密码套件会有不一样的动做产生,该信息的发送就是属于不一样的动做。
它发送的条件是,若是证书包含的信息不足以进行密钥交换,那么必须发送该信息。一般协商的加密套件属于下面的类型,就会发送:
咱们能够看到客户端和服务端协商出来的密码套件是属于ECDHE_RSA类型的。因此这里咱们能够看到该信息的发送。而且该信息是紧跟着Server Certificate信息的。
客户端每次链接服务器的时候,服务器都会发送动态DH信息(DH参数和DH公钥,DH公钥并非证书上的那个公钥),这些信息不存在证书中,须要经过Server Key Exchange信息来进行信息传递,而且传递的DH信息须要使用服务器的私钥进行签名。
DH公钥就是Pubkey
,签名就是Signatrue
,DH参数就是由Curve Type
、Named Curve
、Pubkey
组成的。
该信息是用于密钥交换。由于https在真正的通讯阶段,是经过对称加密来对内容进行加密的,那么对称加密的密钥交换的安全性就显得很是重要,若是安全的保证客户端和服务端都能得到这个对称加密的密钥就是该信息须要作的事情了。
具体的细节能够自行查看DH算法的流程,这里也提供一些资料:
服务器发送完上述信息以后,会马上发送该信息,而后等到客户端的响应。
该信息的主要做用两点:
在接受到服务器的Server Hello Done信息以后,客户端应该马上发送该信息。该信息的主要做用是协商出预备主密钥,通常有两种方式:
经过抓包信息能够看出,这里使用的是第二种方式。由于这里只将一个DH公钥发送给了服务端。
具体客户端是如何计算出该DH公钥的能够参考DH算法的实现流程,参考连接已经在上面给出。
最终,客户端和服务器会计算出相同的预备主密钥。而该预备主密钥就做为第三个随机数。
咱们知道前面已经获得了两个随机数了,最后客户端和服务端会根据这三个随机数计算出对称加密所须要的密钥,由于该密钥是在各自的本地进行计算的,并无经过网络传输,因此该密钥是安全的。
固然,咱们只须要保证第三个随机数是安全的那么对称密钥才是安全的,而DH算法就是用于获得这第三个随机数,至于DH算法如何保证第三个随机数的安全性,请自行查阅。
该协议并非握手协议中的一部分。客户端和服务端在计算出密钥以后,接下来通知对端,后续的信息都须要TLS记录层协议加密保护了。
也就是该信息用于告诉对方,我已经计算好须要使用的对称密钥了,咱们接下来的通讯都须要使用该密钥进行加密以后再发送。
须要注意的是,发送该信息的一方并不知道对方是否已经计算出密钥。通常由客户端先行发送该信息。
该信息是第一个由TLS记录层协议进行加密保护的信息,双方须要验证对方发送的Finished信息,保证协商的密钥是可用的,保证协商过程当中,没有被篡改。
验证该verify Data的内容,包括三部分的内容:
其实在客户端与服务端协商处理的密码套件中,是同时包含了多个算法的.
拿咱们文章中协商出的密码套件来讲:
密码套件 | 密钥协商算法 | 身份验证算法 | 加密算法 | Hash 算法 | 协议 |
---|---|---|---|---|---|
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 | ECDHE | RSA | AES-128-GSM | SHA256 | TLS |
https是如何保证保密性的呢,咱们知道对称密码是经过ECDHE算法协商出一个随机数,而后经过随机数1,随机数2,随机数3经过一个计算方法一块儿计算出一个对称密钥,由于该密钥是在本地计算的,不通过网络传输,因此该对称密钥是安全的。
而后每次的通讯均可以使用该对称密钥进行加密和解密了。
可是DH算法如何保证发送的DH公钥是客户端发送的呢?这里也遇到了跟CA证书同样的问题,如何保证CA证书是有效的呢?在CA证书中是经过使用CA的私钥对用户的CRS信息+CA的信息+用户提供的公钥进行一个数字签名,只要浏览器可使用公钥进行解密,那么就等于该证书是有效的。
一样,DH算法也是如此,发送DH的信息时,服务端会对DH参数和DH公钥使用私钥进行数字签名,只要客户端可使用公钥进行解密,那么就说明该信息是有效的。客户端发送的信息也是如此。
这里提供一个参考文章:DH算法如何防护中间人攻击
浏览器是如何对CA证书进行验证的?
首先咱们先要知道CA证书是如何产生的,首先是申请证书的服务方S须要向第三方CA机构提供CSR(Certificate Signing Request 证书签名请求),第三方机构收到该请求以后,会对该请求中的信息进行核对,线上线下都会进行验证,好比,提供的域名是否属于服务方,地址是否正确等等,只有第三方机构认为你提供的信息都是准确的,它就会根据(你提供的信息+CA机构的信息+公钥)生成一个信息,而后会对该信息进行一个信息摘要,而后使用CA私钥对该信息摘要进行一个数字签名。而后再将生成的信息、数字签名一块儿生成一个数字证书发布给服务方。
浏览器校验证书的流程:首先在本地电脑寻找一个发布该证书的CA机构的根证书,根证书都是预先安装在操做系统上的,若是有则会对证书上的内容进行验证,好比域名是否一致,证书是否过时等,而后使用CA机构的公钥对该数字签名进行解密,若是解密成功,则说明该证书是有效的。
客户端如何保证CA证书是完整的,而没有被别人篡改过呢?好比第三方截取到证书以后,对证书的内容进行了修改。
咱们知道在生成证书的时候,会对信息生成信息摘要,客户端只要拿到CA证书以后,对证书中的信息进行一次信息摘要的生成,而后与使用数字签名解密出来的内容进行对比,就能够知道证书中的内容是否被篡改过。
假如中间人获取到了CA证书,并修改了证书中的域名,可是此时它没有CA机构的私钥,因此它没法获得一个新的签名,而后客户端收到该篡改的证书后,经过私钥解密出来一个原证书信息的摘要,而且客户端对收到的证书内容生成信息摘要,发现两个信息不一致,就会终止通讯,防止信息泄露。
假如中间人也有一个CA机构颁发的合法的证书,中间人拦截到服务端发送的证书,并将本身的证书发送给客户端,此时客户端就会使用中间人证书的公钥进行通讯。
其实该状况是不会发生的,由于在验证的过程当中会验证域名,若是访问的域名与证书中的域名不一致就会提示不安全的连接。可是若是中间人可使用你的域名去申请到证书,那就另当别论了,可是这也不会发生,由于证书申请是须要进行信息核实的,并非能够随意申请的。
其实这只是一个性能问题,由于hash值相对于CA证书的信息来讲是比较短的值,对该值进行加密和解密都会比较快。一般在生成证书的时候也不会在意这些时间,可是在浏览器进行解密时,若是时间过长,用户可就等不了那么长的时间了。
其实在CA机构中的公钥都是内置于操做系统的,内置于操做系统中的公钥必定是可信的。若是连他们都不信,那么咱们就没法完成CA证书的验证了。
而且CA证书并不必定就是由CA机构颁发的,也能够由CA机构受权的代理商进行发布,也就是说CA机构对它受权的代理商也是信任的。因此咱们通常拿到的都是一个三级证书,一级证书就是CA机构的根证书,二级证书就是CA机构受权的代理商的证书,三级证书就是咱们本身的证书,这三个证书构成了一个证书链。
咱们看到掘金中的证书,就是一个三级的证书链。
若是每一次https的请求都须要进行TLS的握手,TLS的握手那么复杂,势必会对通讯带来较大的延时,这对注重用户体验的网站来讲,是不可接受的。那么有什么办法能够避免这种状况吗?
实际上是经过一个Session Identifier(会话标识符),该Session ID是 TLS 握手中生成的 Session ID。服务端能够将 Session ID 协商后的信息存起来,浏览器也能够保存 Session ID,并在后续的 Client Hello 握手中带上它,若是服务端能找到与之匹配的信息,就能够完成一次快速握手。