引言
为什么把这个作为选题。
大概也是2年前,我的同事,在面试某宇宙大厂遇到的问题与我一起探讨。这个时候我发现,虽然TLS(https)这个东西大部分时候可能不会被直接用到,但很容易被作为考察的目标范围。同时这方面的认知不同的人很容易出现不同的偏差。
问题内容概括来说就是URI/URL部分在https中是否会被加密。面试官认为url在https里是不会被加密的,这与事实是有偏差的(最开始只是知道他这里是有误的,没有思考这个地方之所以容易被误解的原因),后面会提到,为什么这个点容易出现理解偏差。
下文将着重分析说明HTTPS的安全性是如何被保证的。(本文会尽量避免直接引用名词含义解释,在说明过程中会重点描述协议与当前内容有直接相关的特性,部分内容会引用作者之前写的帖子或评论)
HTTPS用什么来保障传输安全
结论还是很简单的:我们说https的安全性是由TLS保障的
先问是不是,再问为什么!
HTTP与TLS
这张图展示了http各版本店基本数据传输结构。(该图引至bagder)
从HTTP 1 开始http就在利用TLS确保其安全性(事实上http 0.9就开始在使用SSL)。无论HTTP如何升级,承载其安全特性的组件TLS的地位始终没有被动摇。(从1995年TLS3 首次部署到现在已经超过20年)
值得一提的是作为最知名的传输层协议TCP,HTTP也计划在HTTP3中将其替换,不过其依然沿用最新版本的TLS保障其安全 (举这个例子并不是说TCP不优秀)
上图时间线简单展示了HTTP及SSL/TLS的关键时间线(http1.1 在1999年时有一次定稿,有的资料上会认为1999年是http1.1正式发布的时间点)。不难发现2者的发展一直保持微妙的同步,当然这与web爆发发展有关系,http最知名的版本http1.1 及 现在TLS的基础版本SSL 3 都出现在1996年前后,其影响也一直持续到了现在。
20年前的基础
上图是http各版本当前在web系统中的使用占比,不难看出 http 1.1 至今仍然被广泛使用,这个数字在2020年甚至还有50% (虽然统计中HTTP 2+ 超过了7成,但是并不代表这7成服务不支持HTTP 1.1,他们中大部分可以自动协商降级支持1.1)
而1996年被重新设计的SSL3.0 也一直延用至今(1999年发布的TLS1.0与SSL3.0 修改不大,以至于后面有的地方认为他们是同一个版本)
PS :HTTP与TSL是完全2个独立的协议,只是HTTPS利用TLS保证其安全性。
TLS其他应用范围
当然不能因为http一直与tls绑定,我们就相信tls在安全方面的能力。 (毕竟大家平时在引入三方资源时都会先确认用“他”的人多不多,大部分会优先信任被广泛使用的资源)
我们常用的SSH利用TLS保证连接的安全性,http的好朋友Websocket也在使用TLS,我们常见的VPN也在使用TLS确保我们的隐私安全。
这些基础事实是大家对TLS的认可,同时也表明TLS在安全传输方面的事实地位。
HTTPS/TLS如何确保数据传输安全
那TLS是如何保证其安全的,为什么其地位20多年都无法被撼动。
密钥交换
数据如何安全传输,当然第一时间就能想到“数据加密”(不过数据的传输安全远不仅如此,除了机密性,还需要有鉴别,数据完整性,和不可抵赖性,这些特性TLS都可以做到,不过不在本文讨论范围)
虽然简单加密是不够的,不过消息加密确实一切的基础。看起来并不难,服务器与客户端只需要有一个只有他们2方才知道的密钥,如何用这个密钥传输数据就可以了。
现在真正的问题来了,这个密钥要怎么才能做的只有客户端与服务器才知道,我们知道在互联网上任何数据包的传输都需要经过许许多多路由器等网络设备,其中任意一台设备都知道你的数据包里是什么内容,我们不可能通过网络直接把这个密钥发送给对方。
有一个方案其实很常见,密钥离线分发。比如常见的U盾,口令卡,银行系统用的分量密钥卡等等都是用的类似离线的手段保证密钥的安全。这种密钥交换的方式的确是安全了不过代价太大,对于广泛应用与互联网的http显然不合适。
公开密钥算法
不过幸好早在上个世纪70年年代就出现了公开的非对称加密算法(公开密钥算法,个人觉得这个名字更能体现这个密钥算法的特点),而且其安全性到现如今依然被证明有效(这也是为什么1995就已经问世的SSL3 可以作为TLS的基础一直延用至今的原因),借助于公开密钥算法使得密钥在客户端于服务器之间的安全传播成为可能。
TLS支持的密钥交换算法有许多(比如RSA密钥交换,Diffie-Hellman密钥交换.......)。我们看下RAS密码交换(因为他被广泛应用,且相对简单),看他是如何保证密钥交换的安全性的。
先介绍非对称加密算法的一个重要特点,加密时需要用到一对密钥(公钥,私钥),公钥加密的数据只能通过私钥解密,私钥加密的数据只能通过公钥解密。
- 通常我们说的对称加密基本上都是简单异或或异或的简单变种操作,这正好是计算机擅长的,所以速度非常快。(一般密钥实际上只是一种二进制数据块)
- 非对称加密算法是用的数学算法,无论是加解密,还是密钥对的生成消耗都比对称加密慢很多。(密钥实际上是一个数字,很大的数字)
密钥如何交换
前面我们已经提到了工作密钥是不可以直接在网络上传播的,既然密钥不能中网络中直接传播,那我们能不能把密钥加密后传输呢?非对称加密算法与这个需求完美契合。
服务端可以先将公钥直接发送给客户端,然后客户端自己生成一个随机密钥(TLS里这里交换的其实是预主密钥),然后使用公开的公钥加密这个密钥发送给服务器,因为私钥只有服务器知道,所以只有服务器才能解密这个密钥。这样一来就出现了一个只有客户端和服务器才知道的预主密钥,然后通过这个预主密钥可以生成主密钥,再最终生成工作密钥。
上图简单概括了预主密钥传输过程(其实就是TLS握手的其中一部分)
中间人攻击
看起来是不是很完美,就算密钥交换过程中的数据被其他人知道也没有关系,因为他们没有私钥,没有办法解密,不过还是有漏洞,你连接的网络设备可不是只能看你的数据,他还可以任意截断修改你的原始报文,这就是中间人攻击。
虽然客户端可以使用公钥加密预主密钥,不过客户端的公钥是从哪里来的呢,其实也还是通过网络由服务器下发给客户端的。那既然也是通过网络,在下发公钥的时候工作密钥可还没有生成,这就是说公钥可以被网络中的第三方截获然后替换,客户端以为收到的是服务器的公钥,而实际上收到的是中间人自己生成的公钥(中间人知道与之对应的私钥),这样一来客户端就会在毫不知情的情况下与中间人完成密钥交换(TLS握手),然后中间人会代替客户端与服务端交互,用户及服务端都不知道有中间人的操作,数据就会完全暴露给攻击者。
证书验证
公钥基础设施
现在问题就变成了客户端如何确认自己收到的公钥不是任何攻击者的证书。PKI(公钥基础设施)完美的解决了这个问题。
其实之前就有提到过当前最安全的手段其实就是密钥离线分发,而整个web系统网站这么多不太可能每个网站每个服务器都来给网站离线下发密钥,这个时候就需要一个中间商,一个大家都认可的中间商CA中心(证书签发机构)来帮我们完成服务端公钥的验证,虽然为每个网站离线分发公钥不太可能,不过我们可以提前为客户端离线分发受信任的根证书,利用这个根证书去验证网站服务端发客户端的公钥,这就是前面提到的PKI。
CA中心会提前将自己的根证书加入到操作系统的根证书列表(系统安装的时候就在那里了),许多浏览器也有自己受信根证书列表,这些证书都是内置的,网络嗅探者无法污染这些根证书。
那操作系统凭什么又如何要信任这些根证书呢? 这个就很直白了,刚刚说了是“权威”机构的根证书,你可以不信任,不过基于PKI的证书校验将无法运作,当然这些权威的证书颁发机构也也确实要能对得起他的权威。
现在客户端已经有了离线的信任根证书,那他是如何认证网站发过来的公钥呢(网站发过来实际上是证书,这个证书里包含公钥)
证书验证过程
client会校验证书的合法性,并根据验证结果决定是否连接服务器。(本节内容yin yo)
如上图在浏览器中任意找一个https的网页,服务器在建立TLS连接前都会先将自己的公钥证书发给客户端,我们查看其证书信息。
从这里面我们能看到证书包含以下内容:
(1) Validity也即有效期,有效期包含生效时间和失效时间,是一个时间区间;
(2) 公钥信息Subject Public Key Info,包括公钥的加密算法和公钥内容;
(3) 指纹信息,指纹用于验证证书的完整性,也是证书校验的关键,他确保证书没有被修改过。 其原理就是在颁发证书时,颁发者根据指纹算法(单向散列函数)(此处证书使用了SHA-1和SHA-256算法 有多个指纹是为了兼容老的客户端)计算整个证书的hash指纹【证书内容hash值使用CA私钥加密就是指纹】并和证书放在一起,client在打开证书时,自己也根据指纹算法计算一下证书的hash值,同时使用自己信任的根证书的公钥解密hash指纹计算出原始hash,如果hash值不一致,则表明证书内容被篡改过;
(4) 证书的签名Certificate Signature Value和Certificate Signature Algorithm,对证书签名所使用的Hash算法和Hash值;
(5) 签发该证书的CA机构Issuer;
(6) 该证书是签发给哪个组织/公司信息Subject;
(7) 证书版本Version、证书序列号Serial Number以及Extensions扩展信息等。
上图即是证书指纹校验的主要过程,不难看出Client校验证书的核心其实是CA公钥解密出原始指纹。那这个CA公钥从哪里来,这就是上文中提到的系统根证书。
这里就有一个关键点证书的颁发,我们现在知道根证书里的公钥是用来解密网站公钥证书的指纹的,为了确保安全系统会有一批自己信任的CA公钥列表(根证书),操作系统会提前内置好这些CA的根证书。这些根证书为什么可以验证网站的证书呢 ,因为网址的证书也是这些CA机构签发的。CA对应的一般是权威机构或组织,然后由这些权威机构颁发证书时使用他们自己的私钥去签名(为证书生成指纹)然后再颁发给网站,这样就确保了只有权威机构颁发给各个网站的证书才会被客户端校验通过。
网站证书的颁发
顺便我们看一下CA颁发给网站的证书具体是怎样的,一般有2部分组成
公钥证书:这个就是网站后面会公开发送给客户端的证书 (CA的私钥只会用来给这个证书签名,不关心证书里的密钥)
私钥文件:里面只有一个私钥(与公钥证书里公钥是一对,用来在TLS握手只解密预主密钥)
如上图sipv4.com.key就是私钥文件,sipv4.com.cer就是公钥证书 (如果看的细,会发现cer里不止含有一个CERTIFICATE,其实他是一个证书链)
上图简单描述了证书如何在TLS里发挥作用。有一点需要注意,CA再为网站颁发证书时会验证申请者是网站的拥有者,这样可以确保只有网站的拥有者才可能拥有合法的证书。这一通操作下来即使中间人用自己生成的公钥证书来欺骗客户端时,客户端也能马上反应过来从而中止链接。
现在我们再来看下攻击者的处境,攻击者如果伪装成网站A,握手时攻击者需要给用户发送公钥证书,攻击者有2个选择。
- 发送真正的证书(因为公钥证书是公开的,任何人都可以方便的获取),这样虽然可以通过客户端的证书校验,不过攻击者因为没有私钥,无法解密客户端发过来的预主密钥,握手会最终失败。
- 发送攻击者自己生成的公钥证书,这时虽然攻击者有对应的私钥,不过因为自己生成的证书没有CA的签名,无法通过客户端的证书验证,握手也会被终止。
这样一来密钥的交换,交换过程的安全就都得到了保障。
结束
url加密
现在回到开头,为什么有些同学会认为https不会加密URL。前面讲到的在密钥交换完成前数据流其实是明文,也就是说网站公钥证书的传输是以明文的形式进行的,上面也提到了证书里是包含Subject,而这个信息里往往有目标网站的域名,所以如果直接查看未解密的https流量,往往是可以看到域名的明文信息的,这个信息很有可能让人误以为这是url信息
为什么不使用公钥加密数据
还有一个问题也会经常会被提到,TLS为什么不使用公钥直接加密数据,这个问题也与开头的问题一样,很容易有认知上的偏差
看了很多被广泛接受的答案都是“性能”问题,我很早之前也是这么认为的,不过现在我知道“性能”问题相对于安全性上是否可行那就根本不是问题,不能使用公钥加密是因为安全上根本不可行,会让TLS形同虚设!
随便打开一个https网站的证书,不同电脑不同时间获取的证书里的公钥其实都是一样的,也就是说这个公钥是公开的而且任何人都知道,那就不可能自己用公钥去加解密。这样服务器返回的数据那不是任何人都能解密了
如上图任何人都知道baidu的公钥,任何人也都能解密baidu返回给客户端的数据。
当然TLS的握手是个十分严谨及复杂的过程,他还有很多认证的功能在里面,如果直接用公钥加密数据了那就抛弃了握手里面的很多功能,这里就不展开了。(因为就上面提到的所有返回数据都能被任何人解密那就是致命问题了,相比之下其他的问题都是小问题)
关于非对称加密算法应该加密什么数据
而不用公钥加密数据本身这是个策略,不仅仅是TLS 这些,绝大部分加密系统都是使用的这个策略,因为非对称加密加密的内容本质其实是数字(可以想象把1kb的数据转换成数字 会是个什么情景,当然他也不会允许你加密这么大的数据,还要特殊处理),并且还是数学运算,计算机处理起来会很慢(很多银行机构为了提高速度还会使用特殊的加密设备加密机/卡这类东西)。可以看到非对称算法天生就不是为加密长度不可控的数据设计的,他往往用来加密长度有限的关键数据,比如数据的hash值。而DES、AES这种对称算法就不一样,他们加密主要靠异或跟置换,大数据直接分组 ,这些操作计算机天生就很在行速度很快,他们对加密这些任意长度的数据流就很合适。
总结:
绝大部分加密系统都不会用非对称算法直接加解密数据(因为就不是为这种场景设计的)
而TLS就更不可能用公钥加密数据(因为除了上面提到的设计上的不合理,这种操作还让服务返回的数据失去了任何保护能力)
TLS地位为什么难以被动摇
是不是有必要,作为其基础的非对称加密算法目前为止依然十分十分可靠,而已也找不到更加合适的替代方案。
与其有直接关系的PKI体系已经形成,已经遍布全球CA中心并不是这么容易建立,因为需要大家互相信任,要推翻这个体系也并不容易。
- HTTPS 怎样保证数据传输的安全性
大家都知道,在客户端与服务器数据传输的过程中,HTTP协议的传输是不安全的,也就是一般情况下HTTP是明文传输的.但HTTPS协议的数据传输是安全的,也就是说HTTPS数据的传输是经过加密的. 在客户 ...
- 一文看懂https如何保证数据传输的安全性的【转载、收藏】
一文看懂https如何保证数据传输的安全性的 一文看懂https如何保证数据传输的安全性的 大家都知道,在客户端与服务器数据传输的过程中,http协议的传输是不安全的,也就是一般情况下http是明 ...
- HTTPS 如何保证数据传输的安全性
为什么需要 HTTPS? 我们知道 HTTP 是一个纯文本传输协议,对传输过程中的数据包不进行加密,是明文传输,那这样的话对于介于在发送端和接收端之间的任何 一个节点都能知道传输的内容,这些节点可能是 ...
- 【转】HTTPS 如何保证数据传输的安全性?
大家都知道,在客户端与服务器数据传输的过程中,HTTP协议的传输是不安全的,也就是一般情况下HTTP是明文传输的.但HTTPS协议的数据传输是安全的,也就是说HTTPS数据的传输是经过加密的. 在客户 ...
- HTTPS如何保证数据传输的安全性 -- 结合加密
什么是HTTPS: HTTP就是我们平时浏览网页时候使用的一种协议 HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全.为了保证这些隐私数据能加密传输,于是网 ...
- http与https的区别以及https如何保证数据传输安全
http是应用层协议,它会将要传输的数据以明文的方式给传输层,这样显然不安全.https则是在应用层与传输层之间又加了一层,该层遵守SSL/TLS协议,用于数据加密. **加密的方式有两种: 对称加密 ...
- 一文看懂https如何保证数据传输的安全性的
通过漫画的形式由浅入深带你读懂htts是如何保证一台主机把数据安全发给另一台主机的 对称加密 一禅:在每次发送真实数据之前,服务器先生成一把密钥,然后先把密钥传输给客户端.之后服务器给客户端发送真实数 ...
- 深入理解Https如何保证通信安全
作为一名ABC搬运工,我相信很多人都知道Https,也都知道它是用来保证通信安全的,但是如果你没有深入了解过Https,可能并不知道它是如何保证通信安全的.我也是借着这次机会,和大家分享下我深入了解的 ...
- Https如何保证安全
Https加密安全. SSL加密. Https和http的区别?Https如何做到安全? HTTPS协议是由SSL+HTTP协议构建的可进行加密传输.身份认证的网络协议. http是普通的超文本文 ...
随机推荐
- Java中 equals和==的区分, new Integer和 非new的区别
浅谈 equals 和 == ,new出的Integer和非new出的Integer 首先我们要知道在 == 比较的是内存地址值(不包括8种基本数据类型) equals比较的是两个值(内容)是否相同. ...
- 论文解读(DAGNN)《Towards Deeper Graph Neural Networks》
论文信息 论文标题:Towards Deeper Graph Neural Networks论文作者:Meng Liu, Hongyang Gao, Shuiwang Ji论文来源:2020, KDD ...
- Linux应急响应入门——入侵排查
点击上方"开源Linux",选择"设为星标" 回复"学习"获取独家整理的学习资料! 账号安全: 1.用户信息文件 /etc/passwd # ...
- Android添加布局和按键
Android添加布局和按键 Android布局方式分为 1.LinearLayout (线性布局) 2.ConstraintLayout (约束布局) 3.FrameLayout (帧布局) 4.T ...
- CXP 协议中upconnection 与downconnection的说明及其区别
概述 CXP定义了一个DEVICE和HOST之间点对点的连接协议.CXP的一个连接包含了一个MASTER物理连接和若干可选的SLAVE连接,每一个连接都定义了一组逻辑通道用于传输图像数据.实时触发.设 ...
- MySQL、SqlServer、Oracle,这三种数据库的优缺点,你知道吗?
盘点MySQL.SqlServer.Oracle 三种数据库优缺点 MySQL SqlServer Oracle 一.MySQL 优 点 体积小.速度快.总体拥有成本低,开源:支持多种操作系统:是开源 ...
- 树莓派使用Docker部署EdgeX(jakarta版本)
使用Docker部署EdgeX 老师安排我搞边缘计算,搞了很久都没能明白边缘计算是什么,甚至对其兴趣不大,前一阵弄好了lorawan网关,该做网关内部的边缘计算了,发现自己已经慢慢地学了进去,总是想要 ...
- 面试突击55:delete、drop、truncate有什么区别?
在 MySQL 中,删除的方法总共有 3 种:delete.truncate.drop,而三者的用法和使用场景又完全不同,接下来我们具体来看. 1.delete detele 可用于删除表的部分或所有 ...
- JAVA学习之第一个HelloWorld程序
第一个HelloWorld程序 第一步,创建java类型的文件 第二步,在创建文件的目录中打开cmd窗口 第三步,使用javac 命令将java文件编译为.class类型的字节码文件 第四步,使用ja ...
- 记录bug的贴子
这个贴子用来记录一些,平时关注新闻,暴露出来的bug,引以为戒. 2019/01/21 - 拼多多出现大量100元无门槛券 关键词: 风险控制:羊毛党: https://www.zhihu.com/q ...