CDC

Place to Be & Show Yourself

小白带你深入理解HTTPS

一、问题的提出

1.1 HTTP的问题

首先看看下面这个京东的主页,部分电信用户访问的时候,会看到右下角有一个浮动广告。
《小白带你深入理解HTTPS》
小白用户以为是京东有意放置的,但是细心的用户会发现,这个 iFrame一层嵌一层的恶心广告很明显是电信/中间人通过 DNS 劫持注入进去的,十分恶心,而且没有关闭按钮。

如果还觉得这个是电信在京东页面做广告,我们再看一个图片,很明显我想访问的是www.sbtabc.com,或者我想访问任何一个其他http的网站,和电信没有任何关系,也会首先跳出电信的广告页面,然后才能跳转到目标页面。
《小白带你深入理解HTTPS》

因为HTTP服务器是没有加密和认证的,所以发送信息到这类网站非常容易被中间人劫持。为了杜绝这种情况,最新版本的浏览器Chrome和FireFox已经不允许通过HTTP向网站发送用户名和密码类的敏感信息。

1.2 HTTPS的问题

为了不被劫持,我们自己曾经搭建的一个博客系统,只提供HTTPS访问。该博客一直以来都可以正常访问,可是突然有一天Chrome浏览器提示访问该博客不安全了。
《小白带你深入理解HTTPS》

同时也有同事报告说之前用python库向一个HTTPS的博客网站post文章没有问题,但是有一天突然报下面的错误,百思不得其解。
《小白带你深入理解HTTPS》

本文就先从基本概念开始讲起,然后通过一个加密通信过程的逐步演化来说明为什么HTTP不安全、HTTPS是如何解决安全问题的、以及在公司和学校环境下使用HTTPS需要注意的问题。

二、基本概念

2.1 HTTPS

在HTTP(超文本传输协议)基础上提出的一种安全的http协议,因此可以称为安全的超文本传输协议。http协议直接放置在TCP协议之上,而https提出在http和TCP中间加上一层加密层。从发送端看,这一层负责把http的内容加密后送到下层的TCP,从接收方看,这一层负责将TCP送来的数据解密还原成http的内容。

2.2 SSL(Secure Socket Layer)

SSL是Netscape公司设计的主要用于WEB的安全传输协议。从名字就可以看出它在https协议栈中负责实现上面提到的加密层。因此,一个https协议栈大致是这样的:
《小白带你深入理解HTTPS》

2.3 公钥密码体制(public-key cryptography)

公钥密码体制分为三个部分,公钥、私钥、加密解密算法,它的加密解密过程如下:

  • 加密:通过加密算法和公钥对内容(或者说明文)进行加密,得到密文。加密过程需要用到公钥。
  • 解密:通过解密算法和私钥对密文进行解密,得到明文。解密过程需要用到解密算法和私钥。注意,由公钥加密的内容,只能由私钥进行解密,也就是说,由公钥加密的内容,如果不知道私钥,是无法解密的。

公钥密码体制的公钥和算法都是公开的(这是为什么叫公钥密码体制的原因),私钥是保密的。大家都以使用公钥进行加密,但是只有私钥的持有者才能解密。在实际的使用中,有需要的人会生成一对公钥和私钥,把公钥发布出去给别人使用,自己保留私钥。 这是一种非对称加密算法(asymmetric key algorithms)

2.4 对称加密算法(symmetric key algorithms)

在对称加密算法中,加密使用的密钥和解密使用的密钥是相同的。也就是说,加密和解密都是使用的同一个密钥。因此对称加密算法要保证安全性的话,密钥要做好保密,只能让使用的人知道,不能对外公开。这个和上面的公钥密码体制有所不同,公钥密码体制中加密是用公钥,解密使用私钥,而对称加密算法中,加密和解密都是使用同一个密钥,不区分公钥和私钥。

2.5 RSA简介

RSA密码体制是一种公钥密码体制,公钥公开,私钥保密,它的加密解密算法是公开的。 由公钥加密的内容能并且只能由私钥进行解密,相反由私钥加密的内容能并且只能由公钥进行解密。也就是说,RSA的这一对公钥、私钥都可以用来加密和解密,并且一方加密的内容可以由并且只能由对方进行解密。

2.6 签名和加密

我们说加密,是指对某个内容加密,加密后的内容还可以通过解密进行还原。 比如我们把一封邮件进行加密,加密后的内容在网络上进行传输,接收者在收到后,通过解密可以还原邮件的真实内容。

这里主要解释一下签名,签名就是在信息的后面再加上一段内容,可以证明信息没有被修改过,怎么样可以达到这个效果呢?一般是对信息做一个hash计算得到一个hash值,注意,这个过程是不可逆的,也就是说无法通过hash值得出原来的信息内容。在把信息发送出去时,把这个hash值加密后做为一个签名和信息一起发出去。 接收方在收到信息后,会重新计算信息的hash值,并和信息所附带的hash值(解密后)进行对比,如果一致,就说明信息的内容没有被修改过,因为这里hash计算可以保证不同的内容一定会得到不同的hash值,所以只要内容一被修改,根据信息内容计算的hash值就会变化。当然,不怀好意的人也可以修改信息内容的同时也修改hash值,从而让它们可以相匹配,为了防止这种情况,hash值一般都会加密后(也就是签名)再和信息一起发送,以保证这个hash值不被修改。至于如何让别人可以解密这个签名,这个过程涉及到数字证书等概念,我们后面在说到数字证书时再详细说明,这里您先只需先理解签名的这个概念。

三、一个加密通信过程的演化

第一回合

正常流程中,客户端发起请求,服务器给出响应:
《小白带你深入理解HTTPS》

但是因为HTTP通信没有认证机制,黑客冒充自己是“服务器”来向客户发送信息。例如上面的消息可以被黑客截获如下:
《小白带你深入理解HTTPS》

第二回合

如何确定信息是由真正的“服务器”发过来的呢?也就是如何对服务器进行认证呢?有一个解决方法,使用RSA这种公钥密码体制,“服务器”对外发布公钥(算法不需要公布,RSA的算法大家都知道),自己留着私钥。“客户”通过某些途径拿到了“服务器”发布的公钥,因为只有服务器有私钥,所以只要能够确认对方有私钥,那么对方就是“服务器”。因此通信过程可以改进为如下:
《小白带你深入理解HTTPS》

注意这里约定一下,{} 表示RSA加密后的内容,[ | ]表示用什么密钥和算法进行加密,后面的示例中都用这种表示方式,例如上面的 {我是服务器}[私钥|RSA] 就表示用私钥对“我是服务器”进行加密后的结果。

为了向“客户”证明自己是“服务器”, “服务器”把一个字符串用自己的私钥加密,把明文和加密后的密文一起发给“客户”。对于这里的例子来说,就是把字符串 “我是服务器”和这个字符串用私钥加密后的内容 {我是服务器}[私钥|RSA] 发给客户。

“客户”收到信息后,用自己持有的公钥解密密文,和明文进行对比,如果一致,说明信息的确是由服务器发过来的。也就是说“客户”把“ {我是服务器}[私钥|RSA]” 这个内容用公钥进行解密,然后和“我是服务器”对比。因为由“服务器”用私钥加密后的内容,由并且只能由公钥进行解密,私钥只有“服务器”持有,所以如果解密出来的内容是能够对得上的,那说明信息一定是从“服务器”发过来的。

假设“黑客”想冒充“服务器”,由于“黑客”没有“服务器”的私钥,因此它发送过去的内容,例如{我是服务器}[黑客私钥|RSA],“客户”是无法通过服务器的公钥解密的,因此可以认定对方是个冒牌货!

第三回合

到这里为止,“客户”就可以确认“服务器”的身份了,可以放心和“服务器”进行通信,但是这里有一个问题,通信的内容在网络上还是无法保密。为什么无法保密呢?通信过程不是可以用公钥、私钥加密吗?其实用RSA的私钥和公钥是不行的,我们来具体分析下过程,看下面的演示:
《小白带你深入理解HTTPS》

注意上面的的信息 “{你的余额是3千万}[私钥|RSA]”,这个是“服务器”用私钥加密后的内容。但是我们之前说了,公钥是发布出去的,因此所有的人都知道公钥,所以除了“客户”,其它的人也可以用公钥对\”{你的余额是3千万}[私钥|RSA]\”进行解密。所以如果“服务器”用私钥加密发给“客户”,这个信息是无法保密的,因为只要有公钥就可以解密这内容。然而“服务器”也不能用公钥对发送的内容进行加密,因为“客户”没有私钥,发送个“客户”也解密不了。

第四回合

这样问题就又来了,那又如何解决呢?在实际的应用过程,一般是通过引入对称加密来解决这个问题,看下面的演示:
《小白带你深入理解HTTPS》

在上面的通信过程中,“客户”在确认了“服务器”的身份后,“客户”自己选择一个对称加密算法和一个密钥,把这个对称加密算法和密钥一起用公钥加密后发送给“服务器”。注意,由于对称加密算法和密钥是用公钥加密的,就算这个加密后的内容被“黑客”截获了,由于没有私钥,“黑客”也无从知道对称加密算法和密钥的内容。

由于是用公钥加密的,只有私钥能够解密,这样就可以保证只有服务器可以知道对称加密算法和密钥,而其它人不可能知道(这个对称加密算法和密钥是“客户”自己选择的,所以“客户”自己当然知道如何解密加密)。这样“服务器”和“客户”就可以用对称加密算法和密钥来加密通信的内容了。

总结一下,RSA加密算法在这个通信过程中所起到的作用主要有两个:

  • 因为私钥只有“服务器”拥有,因此“客户”可以通过判断对方是否有私钥来判断对方是否是“服务器”。
  • 客户端通过RSA的掩护,安全的和服务器商量好一个对称加密算法和密钥来保证后面通信过程内容的安全。

另外,对称加密不仅仅解决了信息泄露的问题,在实际使用过程中,性能也比非对称加密要好。

第五回合

到这里,“客户”就可以确认“服务器”的身份,并且双方的通信内容可以进行加密,其他人就算截获了通信内容,也无法解密。的确,好像通信的过程是比较安全了。

但是其实这里面隐藏着大大的问题。每次和“客户”开始通信时,“服务器”需要把公钥发给“客户”。问题正是出在这里,因为任何人都可以自己生成一对公钥和私钥。因此“黑客”只需要自己生成一对公钥和私钥,然后把公钥发送给“客户”,自己保留私钥,这样由于“客户”可以用黑客的公钥解密黑客的私钥加密的内容,“客户”就会相信“黑客”是“服务器”,从而导致了安全问题。如下图所示:
《小白带你深入理解HTTPS》

第六回合

这里问题的根源就在于,大家都可以生成公钥、私钥对,无法确认公钥对到底是谁的。 如果能够确定公钥到底是谁的,就不会有这个问题了。例如,如果收到“黑客”冒充“服务器”发过来的公钥,经过某种检查,如果能够发现这个公钥不是“服务器”的就好了。

为了解决这个问题,数字证书出现了,它可以解决我们上面的问题。一个证书包含下面的具体内容:

  • 证书的发布机构
  • 证书的有效期
  • 公钥
  • 证书所有者(Subject)
  • 签名所使用的加密算法
  • 指纹算法以及指纹

这里先只需要搞清楚一点,数字证书可以保证数字证书里的公钥确实是这个证书的所有者(Subject)的,或者证书可以用来确认对方的身份。也就是说,我们拿到一个数字证书,我们可以判断出这个数字证书到底是谁的。至于是如何判断的,后面会在详细讨论数字证书时详细解释。现在把前面的通信过程使用数字证书修改为如下:
《小白带你深入理解HTTPS》

注意,上面第二次通信,“服务器”把自己的证书发给了“客户”,而不是发送公钥。“客户”可以根据证书校验这个证书到底是不是“服务器”的,也就是能校验这个证书的所有者是不是“服务器”,从而确认这个证书中的公钥的确是“服务器”的。后面的过程和以前是一样,“客户”让“服务器”证明自己的身份,“服务器”用私钥加密一段内容连同明文一起发给“客户”,“客户”把加密内容用数字证书中的公钥解密后和明文对比,如果一致,那么对方就确实是“服务器”,然后双方协商一个对称加密来保证通信过程的安全。到这里,整个过程就完整了。

四、数字证书的原理

4.1 证书无法伪造

上面第六回合就是一个完整服务器验证的过程。但是还有一个疑问,在第六回合第二次通信时,如果黑客自己生成一个数字证书,是否就可以“窃听”呢?也就是上面提到的问题:数字证书是否可以证明服务器的身份呢?这就要从数字证书的原理和验证说起。

上面证书中所带的公钥和服务器的私钥,完成了客户端和服务器之间的私密通信。而证书自身真伪的验证是通过另外一套公钥和私钥来进行的。这里的私钥由证书颁发机构保存,而对应的公钥和证书颁发机构的名称则会以证书机构自己的证书的形式预装到操作系统里,这里简称为机构私钥和机构公钥。

这样一个证书的签名可以简单表示为:“{颁发机构,有效期,所有者,指纹算法}[计算指纹][机构密钥|签名加密算法]”

证书的验证过程和上面保密通信的第二回合有点类似,只要客户端操作系统使用“机构公钥”和Signature algorithm (签名所加密算法)能够解密签名,就可以认为该证书是一个合法的证书。

但是由于证书的内容都是明文的,如何证明证书内容没有被修改过呢。这个时候Thumbprint algorithm (指纹算法)就派上用场了。 其原理就是在发布证书时,发布者根据指纹算法(一个hash算法)计算整个证书的hash值(指纹)并和证书放在一起,使用者在打开证书时,自己也根据指纹算法计算一下证书的hash值(指纹),如果和刚开始的值对得上,就说明证书没有被修改过,因为证书的内容被修改后,根据证书的内容计算的出的hash值(指纹)是会变化的。

证书内容经过指纹算法得到了指纹,指纹算法和指纹本身在经过机构私钥的非对称加密,整个证书的认证和防伪就就已经完美无缺了。

4.2 HTTPS劫持的过程

这个时候再来理解一下,为什么一直能访问的HTTPS网站变得不安全了呢?在Chrome浏览器中,打开Developer Tool(开发者工具),如下图所示,可以查看目标网站的证书:
《小白带你深入理解HTTPS》

我们先来看看不安全的目标网站的证书:
《小白带你深入理解HTTPS》

奇怪,我们的博客是在Let\’s Encrypt这个机构申请的免费证书,怎么颁发机构变成了TREND.IWS.2了?原来是公司的网关产品IWS在作怪,是IWS劫持了我们的HTTPS流量。劫持的具体过程如下图所示:
《小白带你深入理解HTTPS》

因为TREND.IWS.2这个颁发机构是不被操作系统信任的证书机构,所以浏览器会跳出警告信息,说明网站不安全,因此上面的劫持并不算是成功。

当然公司的域用户管理员可以将TREND.IWS.2的证书加入到操作系统的信任体系之中,不在域中的用户也可以手工导入证书的方式或者忽略警告继续访问该网站,这样劫持就成功了。劫持成功之后,信息在客户端和服务器之间的流程如下图所示:
《小白带你深入理解HTTPS》

对于Python代码想HTTPS网站Post文章出现的问题,解决方案也是类似的,如果能够确认网站的安全性,则直接在请求访问之前忽略证书验证就可以了。

不过这个时候访问该网站真的变得不安全了。因为上图中所有客户端和真实服务器之间交互的信息都在网关上进行了解密。如果不解密,则服务器就无法认识客户端发来的信息,因为客户端和服务器使用的对称密钥是不同的。因此在访问HTTPS网站的时候一定要小心,如果浏览器弹出了警告提示,务必确认证书的有效性。域用户就更需要小心了,因为管理员可以在你神不知鬼不觉的情况下导入一个并不可靠的证书。

4.3 证书机构的权威性

通过以上描述,我们知道,证书颁发机构的权威性在整个加密通信流程中起到非常重要的作用。微软等公司会根据一些权威安全机构的评估选取一些信誉很好并且通过一定的安全认证的证书发布机构,把这些证书发布机构的证书(包含公钥和机构名称)默认安装到操作系统中。如果颁发机构对证书申请人不进行仔细审核,或者故意放水,则“黑客”就可以利用申请到的证书来骗取操作系统和用户的信任,来获取用户的隐私信息。

这个就是2017年初最著名的Google和Symantec互撕的由来。因为Symantec颁发了3万张有问题的证书,所以Google选择不信任Symantec颁发的证书。互撕详情,请参考这里http://tech.163.com/17/0329/07/CGM9E1PD00097U7T.html

设想另外一种情况,证书颁发机构是没问题的,但是证书颁发之后,证书持有人自己开始作恶了。证书颁发机构就会吊销这个证书。浏览器会定期查看证书颁发者公布的“证书吊销列表”,如果证书被吊销,那么浏览器也会给出警告。每个证书的CRL Distribution Point字段显示了查看这个列表的url。尽管如此,windows对于这个列表是“不敏感”的,也就是说windows的api会缓存这个列表,直到设置的缓存过期才会再从CRL Distribution Point中下载新的列表。目前,只能通过在证书颁发服务端尽量小的设置这个有效期(最小1天),来尽量使windows的客户端“敏感”些。

五、总结

本文深入浅出讨论了HTTPS加密通信的原理,详细解释了为什么数字证书不可能被伪造的情况下,HTTPS劫持仍然能够成功的原因。希望读者们一起提高警惕,避免重要信息泄露。

点赞
  1. 匿名说道:

    这篇文章浅显易懂,厉害

发表评论

电子邮件地址不会被公开。