HTTPS随处可见,那么它到底是个什么鬼?本文我们一起来探讨一下HTTPS为什么是安全的,以及HTTPS连接建立的过程。

一、HTTPS为什么是安全的?

  HTTP使用明文通信,可能会被第三方窃听、篡改和冒充,所以它是不安全的。那么HTTPS为什么是安全的呢,它到底是怎样保证安全的呢?

1、简单通信加密

  如果A需要向B发送数据,怎么保证数据在通信过程中的隐私性呢?答案是使用加密算法,从《了解数字证书、数字签名与常见的加密算法》了解到可以使用对称加密算法来对通信的数据进行加密,这样就可以保证通信过程中数据的隐私性和安全性。做法是,如果通信双方A和B事先已知,则他们可以事先线下商定好一个对称加密算法和密钥,然后进行数据通信,如图1.1。但是,在互联网环境中,往往通信一方是未知的,并且所有数据必须走网络,此时如果直接使用明文传输密钥还是会被截获,通信仍然是不安全的。那么此时如何将密钥发给对方呢?

图1.1 使用相同的对称加密密钥进行数据通信

2、使用非对称加密来传输对称密钥

  聪明的设计者想到了,可以使用非对称加密来解决密钥交换的问题。在非对称加密中,使用A的公钥加密数据发送给A是安全的,因此问题到这里就变成了B如何安全地获得A的公钥。思考一下,A直接将他的公钥发给B有没有安全风险呢?答案是有的,直接发送公钥存在被中间人调包的风险,假设M为中间人,通信调包过程见图1.2(右键放大查看)。

图1.2 中间人通过调包公钥实现通信监听与篡改

  从图中可知,直接发送A的公钥是存在被中间人调包的风险的,那么在下发A的公钥的时候如何保证公钥不被调包呢?

3、使用三方机构来确保服务器公钥下发的安全性

  到这里,单单依赖A和B本身是很难实现A公钥下发的安全性的,此时需要依靠三方CA机构来保证A公钥下发的安全性。此时需要A找一家权威的CA机构,将自己的公钥发给他来申请数字证书,然后CA会使用自己的私钥对A的公钥和A的其他信息进行加密,制作证书。通常情况下,A的身份是web服务器,B身份是浏览器,此时证书做好后A就将数字证书部署到自己服务器中。当浏览器B来请求公钥时,服务器A就将带有A公钥的数字证书发送过去,浏览器B接收到数字证书后,会根据证书中的CA机构信息在本地环境中找到预存的CA公钥(权威CA机构的公钥通常预先内置于操作系统或浏览器中)校验证书的安全性,然后获得服务器A的公钥了(数字证书相关参考《了解数字证书、数字签名与常见的加密算法》)。

  事实上,浏览器B收到服务器A的证书后,先使用本地预存的对应CA的公钥对证书内的数字签名进行验证。验证数字证书后,浏览器B会生成一个随机的字符串,用服务器A的公钥进行加密并发送给服务器A,服务器A用私钥先解密再加密后把结果返回给浏览器B,浏览器B用公钥解密这个返回结果,如果解密结果与之前生成的随机字符串一致,那说明对方确实是私钥的持有者,或者说对方确实是服务器A。

  细心的你可能会发现,虽然数字证书无法伪造,但是此时还是有调包数字证书的可能性,就是中间人也向CA机构申请证书(可以相同也可以不同),将自己的证书替换网站A的证书下发给浏览器B,后续监听与篡改与图2类似。那么说,数字证书岂不是还是没起到作用?

  其实,浏览器在收到数字证书后,会进行一系列的安全校验,其中最重要的就是需要校验当前访问的网址是否与证书中的网址匹配,如果不匹配,则存在证书被替换风险,会发出风险警告。几乎所有的浏览器都支持CA证书与校验,演变到这一步,已经完全可以实现网站A公钥下发的安全性保障了。

  -----------------

  浏览器如何验证数字证书?

  1) 验证证书的真伪

  浏览器拿到证书后会根据颁发机构去本地系统CA证书库找到对应证书,取出发证机关的公钥,并用此公钥解密数字签名值获取网站公钥的摘要值即为DIG1,再用相同的摘要算法对网站公钥进行计算获取值为DIG2,若DIG1=DIG2,则表示此证书为的确为该颁发机构颁发的真实证书,未被篡改。

  2) 验证当前证书持有者的真伪

  第一步验证证书真伪后,需要再验证当前持有者是否为所有者(注意持有者和所有者的区别)。验证方法是,用网站的公钥加密一段随机信息给当前持有者(当前访问网站),如果持有者能顺利解密并返回(可以返回明文,或返回摘要计算后的值,或使用网站的私钥进行加密后的密文),浏览器再根据对应的方法验证返回的数值是否为原信息,一致则表示当前证书持有者(同新方)就是证书所有者。

  3) 验证证书所有者的姓名

  这一步就是验证证书的域名与当前访问域名是否一致。

  -----------------

  数字证书中的公钥是以密文形式存在,并且数字证书中还包含对该公钥的数字签名。如果有中间人试图篡改公钥信息,客户端在接收证书后是通不过数字签名的校验的,因此使用数字证书下发的公钥,是安全的。

  所以综合以上三点:对称加密算法加密数据 + 非对称加密算法交换密钥 + 数字证书验证身份 = 安全。

二、HTTPS是怎样建立连接的?

  客户端与服务端需要经过握手阶段才能建立HTTPS连接,握手过程如图2.1所示。我们将通过wireshark抓包支付宝主页(https://www.alipay.com/)来逐步了解具体通信过程。

图2.1 https握手连接示意图

    

1、客户端发起Client Hello

  tcp三次握手后,客户端开始发起Client Hello请求,如图2.2所示。  

图2.2 Client Hello请求抓包数据

  1) 随机数。这是整个连接过程中的第一个随机数,我们先记为ClientHello.random,后续生成对称密钥会用到;

  2) Session Id。用于下次建立https连接时,可直接使用,避免重复握手,以提高效率(类似于web的session)。这里由于是第一次访问alipay,所以SID为空;

  3) Cipher Suites-密文族。是浏览器所支持加密算法的清单,供服务器选择。以"TLS_RSA_WITH_AES_256_CBC_SHA"为例,TLS为协议,RSA为密钥交换的算法,AES_256_CBC是对称加密算法(其中256是密钥长度,CBC是分组方式),SHA是哈希的算法。

  4) server_name扩展。一个ip可能配置有多个https域名,此时需要向服务器指定需要请求哪个域名的证书;

  5) Compression Methods。客户端支持的压缩算法,供服务器选择。

2、服务端回复Server Hello

  图2.3 Server Hello抓包数据

  1) Session ID。服务端新生成供客户端下次请求时复用(如果客户端请求带有SID并且服务端已存在则直接复用,不新创建);

  2) Cipher Suite。服务端选择的加密算法。

  大多数HTTPS握手在Server Hello返回时会带上客户端所需要的证书,而此实验发现此时并没有返回证书。往下看,发现在Server Hello Done时返回了证书。

3、服务端响应Sever Hello Done

图2.4 Server Hello Done抓包数据

  这里在Server Hello Done响应时,同时给客户端返回了证书,告诉客户端hello结束。

4、客户端验证证书

  这一步非常关键,客户端需要校验服务端下发的证书的真实性。主要靠证书中自带的数字签名算法进行校验,同时会比较当前访问站点与证书中的域名是否一致,如不一致则需要发出预警。

5、客户端密钥交换Client Key Exchange

图2.5 客户端密钥交换抓包数据

  此步骤密钥交换算法比较复杂,客户端生成第三个随机数PreMaster并加密传输给服务器,并不会直接加密传输生成后的对称密钥,会让服务器利用已知的三个随机数和相同的加密算法生成后续数据通信的对称密钥(不直接传输加密后的对称密钥可能出于更安全的角度考虑)。

6、服务端响应握手结束

图2.6 握手结束抓包数据

  至此,HTTPS握手已经结束,后续客户端与服务端通信都使用协商好的对称密钥进行加密通信。

其他

免费的https证书,参考:https://segmentfault.com/a/1190000012343679

参考资料

  《HTTPS 科普扫盲帖

  《SSL/TLS协议运行机制的概述

  《https连接的前几毫秒发生了什么

  《一个故事教你看懂什么是数字证书,它的原理是什么?它的作用是什么?

HTTPS到底是个什么鬼?的更多相关文章

  1. JWT到底是个什么鬼?

    前面一篇我们了解了微服务安全认证架构是如何演进而来的,但是发现v2.5架构仍然较重,有没有轻量级一点的方法呢?其实业界早已有了实践,它就是基于JWT的安全认证架构.JWT到底是个什么鬼呢?本篇为你解答 ...

  2. 为什么全世界都对HTTPS抛出了橄榄枝,HTTPS到底有什么好?HTTPS如何配置?

    整个互联网世界,正从"裸奔"向HTTPS时代转型. 淘宝.天猫在2015年完成规模巨大的数据"迁徙",将百万计的页面从HTTP切换到HTTPS:苹果要求所有iO ...

  3. HTTPS 到底加密了什么?

    关于 HTTP 和 HTTPS 这个老生常谈的话题,我们之前已经写过很多文章了,比如这篇<从HTTP到HTTPS再到HSTS>,详细讲解了 HTTP 和 HTTPS 的进化之路,对的没错, ...

  4. 一分钟理解 HTTPS 到底解决了什么问题

    本文原作者“虞大胆的叽叽喳喳”,原文链接:jianshu.com/p/8861da5734ba,感谢原作者. 1.引言 很多人一提到 HTTPS,第一反应就是安全,对于普通用户来说这就足够了: 但对于 ...

  5. 被顶级学术期刊枪毙的p.Value到底是个什么鬼

    总结一下,在我看来,p.Value仅仅是在,假设检验,这理论框架下,对于证据力度的一个测量.而且,我们不大可能推翻假设检验这个框架,似乎也不必要,因为,这个框架非常合理,有广泛的应用场景,有强大的生命 ...

  6. Python中的logger和handler到底是个什么鬼

    最近的任务经常涉及到日志的记录,特意去又学了一遍logging的记录方法.跟java一样,python的日志记录也是比较繁琐的一件事,在写一条记录之前,要写好多东西.典型的日志记录的步骤是这样的: 创 ...

  7. Flask中的g到底是个什么鬼?

    g到底是个什么鬼? 在一次请求请求的周期,可以在g中设置值,在本次的请求周期中都可以读取或复制. 相当于是一次请求周期的全局变量. from flask import Flask,g app = Fl ...

  8. Google、Facebook等均开始支持的HTTP3到底是个什么鬼?

    GitHub 19k Star 的Java工程师成神之路,不来了解一下吗! 最近一段时间以来,关于HTTP/3的新闻有很多,越来越多的国际大公司已经开始使用HTTP/3了. 所以,HTTP/3已经是箭 ...

  9. 窥探Vue.js 2.0 - Virtual DOM到底是个什么鬼?

    引言 你可能听说在Vue.js 2.0已经发布,并且在其中新添加如了一些新功能.其中一个功能就是"Virtual DOM". Virtual DOM是什么 在之前,React和Em ...

随机推荐

  1. Curator的监听

    如果要使用类似Wather的监听功能Curator必须依赖一个jar包,Maven依赖, <dependency> <groupId>org.apache.curator< ...

  2. reentrantlocklock实现有界队列

    今天找synchronize和reentrantlock区别的时候,发现有个使用reentrantlock中的condition实现有界队列,感觉挺有趣的,自己顺手敲了一遍 class Queue{ ...

  3. easyui combobox下拉框文字超出宽度有横向滚轮

    //下拉框显示横向滚轮 $(".combo").mouseenter(function(){ $(this).prev().combobox("showPanel&quo ...

  4. [字符串][NOIP2012]Vigenère密码

    Vigenère密码 题目描述 16世纪法国外交家Blaise de Vigenère设计了一种多表密码加密算法——Vigenère密码.Vigenère密码的加密解密算法简单易用,且破译难度比较高, ...

  5. 【MySQL】-2 函数、分组、子查询、联合查询

    函数 Mysql的函数特性没有SQL可移植性强. 大多数情况下支持的函数: 处理文本串的函数: RTrim():处理列值右边的空格 LTrim():处理列值左边的空格   Trim():处理列值的左右 ...

  6. Django手册

    Django教程 Python一直是我最喜欢的语言,在Django和Tornado之间我选择了前者,没有特别的原因,网上人云亦云的,肯定不会有一方离另一方差很远,我就直接去看了看Github上两个项目 ...

  7. (PMP)第7章-----项目成本管理

    7.1 规划成本管理 输入 工具与技术 输出 1.项目章程 2.项目管理计划 (进度管理计划, 风险管理计划) 3.事业环境因素 4.组织过程资产 1.专家判断 2.数据分析 3.会议 1.成本管理计 ...

  8. s4 Docker 网络1

    网络基础 Docker Network 单机网络 Bridge Network Host Network None Network 多机网络:overlay Network 网络的分层 公有IP和私有 ...

  9. pb数据导出

    pb数据导出(一) 1.在窗口新建用户事件  ue_export    2.事件调用函数 gf_dw_to_excel(THIS.dw_dict) 3.写函数 :boolean lb_setborde ...

  10. Python之旅Day3 文件操作 函数(递归|匿名|嵌套|高阶)函数式编程 内置方法

    知识回顾 常见五大数据类型分类小结:数字.字符串.列表.元组.字典 按存值个数区分:容器类型(列表.字典.元组) 标量原子(数字.字符串) 按是否可变区分:可变(列表.字典) 不可变(数字.字符串.元 ...