学习网络编程No.10【深入学习HTTPS】
引言:
北京时间:2023/11/14/18:45,因为种种原因,上个月的文章昨天才更新,目前处于刷题前夕,算法课在看了。这次和以前不一样,因为以前对知识框架没有很好的理念,并不清楚相关知识要学到什么时候才算完,大部分时间都花在了总结博客中,而这次我们已经将主线课程全部学完,当然网络相关知识还有多篇博客没有及时总结,但是无关紧要。目前我们就可以进行模式切换,将算法学习变成主线任务,写博客变为支线任务,毕竟我们所能写的博客在我目前知识范围内是有限的,慢慢写,总有一天能够全部完成。而在今天学习算法课的过程中,目前给我较为深刻的感觉就是经历,老话说得好,年少不知富婆好,错把少女当成宝,啊呸呸呸,不对不对,应该是老话说得好,很多事情只有自己经历过了,你才真正能够有所感悟。当然由于目前我对这方面的深度也还不够,只能慢慢学慢慢悟,总有一天我会将我对做题最为深刻的感想总结出来。当前先让我们跟随着该篇博客来学习有关应用层协议之HTTPS的相关知识吧!
回顾HTTP协议相关知识
烦恼于该篇博客的标题,由于HTTP知识太多,导致上篇本来应该重点讲解HTTPS内容的博客中并没有重点谈到HTTPS相关知识,而全部都是HTTP协议相关的知识,所以该篇博客我们只能以深入学习HTTPS为标题。同理,在开始新内容的学习之前,我们先对上篇博客讲解的知识进行回顾,在上篇博客中,我们重点完成的是一个对HTTP协议从理论到实践的过程,也就是我们重点将HTTP请求/响应格式从一幅图变成具体代码的同时,我们也明确了对HTTP请求做处理以及构建HTTP响应等一系列代码实践过程。当然除了上述代码实践过程,在上篇博客中,我们也对HTTP协议中的其它知识进行了着重介绍,明确了HTTP协议因为请求方法不同导致的各种情况以及状态行中状态码不同导致的各种情况,同时对这两方面知识中的内容进行了详略处理,重定理解某些较为重要知识的同时,对其它知识也有一定的认识。最后在博客的尾部,重点介绍一个叫会话保持的概念,从而结合HTTP协议让我们不仅对会话保持有了明确的理解,对HTTP协议也有了一个更深的认识。
正式进入应用层协议之HTTPS的学习
上述对我们在HTTP协议中学到的内容进行了简单的复习之后,此时我们正式进入HTTPS协议的学习,同理明确HTTPS协议也是一个应用层协议,也是一个提供给浏览器使用,用于客户端和服务端之间进行网络数据传输的协议。那么问题就来了,HTTP协议和HTTPS协议有什么区别呢?所以下面就让我们带着这个问题正式进入HTTPS的学习。
理解什么是HTTPS协议
首先回顾上篇博客有关请求方法的概念,在学习HTTP协议中的请求方法时,我们重点对GET和POST方法进行了讲解,明白了对于GET方法来说,使用POST方法提交用户参数私密性更高的概念。并且当时我还特地强调是私密性而不是安全性,这是为什么呢?原来对于HTTP协议来说,无论是HTTP请求/响应,只要它想要通过网络通信的手段发送到对端主机上,它就一定离不开网络协议栈的基本原理,它就一定需要进行全网路由。而如果HTTP请求/响应需要被转发,那么因为HTTP请求/响应是明文数据,此时就会导致数据泄露篡改问题。所以为了解决这一问题,最好的方法就是对HTTP请求/响应数据进行加密,从别人可以直接读取的明文,变成别人不能直接读取的密文。而为了实现这一方法,HTTPS协议顺理成章的诞生了。
所以此时我们就明确HTTPS协议就是在HTTP协议的基础上,对HTTP请求数据和HTTP响应数据做加密处理。明白了这个概念之后,对于HTTPS我们就有了一个很明确的认识,知道它不是一个全新的应用层协议,而是一个对HTTP协议缺陷进行改进的协议。那么同理问题就来了,HTTPS协议采用的是什么方式来改进这个缺陷的呢?亦或者说是HTTPS协议是采用什么方式对HTTP请求/响应数据做加密的呢?答案其实很简单,就是在HTTP协议的基础上再添加一层软件层,当然也就是在应用层中添加一层软件层,无论浏览器或者服务器在接收数据还是发送数据,根据HTTPS协议就需要去调用该层软件层,然后将数据交给该软件层,让它帮我们完成对应数据的加密/解密操作。并且明确一般常见的软件层,也就是HTTPS协议中常用的加密/解密算法就是SSL/TLS。总而言之:HTTPS协议就等于HTTP协议加上对应的软件层。
常见的加密解密方式
通过上述的知识,此时我们就明白HTTPS协议的核心就是除HTTP协议之外的那层软件层,而软件层的核心又是各种加密解密算法,而加密解密算法的核心又是各种数理知识(离散/大素数/概率/编码/代数等…)。对于数理知识,也就是各种算法的核心理论我们不做讲解,毕竟我们实力有限,当然如果我想,具体原理我们肯定是能搞清楚的,毕竟现在是AI时代。所以抛开这层不谈,退而求其次的我们就来学习一下几种常见的加密方式,也就是明确HTTPS中的软件层一般使用的加密方式是什么,具体原理又是什么。只不过在正式介绍加密方式之前,我们需要先明确几个简单的概念,明文经过加密就变成密文,密文经过解密就得到明文,而一个数据从明文变成密文或是从密文变成明文,它都需要通过秘钥来完成。同理明确,秘钥就是某种特定的秘密参数,如生活中最常见的密码就属于秘钥中的一种,你使用密码对某一数据做加密,那么下次解密时,你也只能用同一密码。并且明确当一个数据被加密,就算是在无对应秘钥的情况下,它依然可以被暴力破解,只是对时间和算力方面有很高的要求,所以对于信息安全,它是一个相对的概念,而不是一个绝对的概念,而只要解密成本远大于破解之后的收益,那么我们就认为信息是安全的。明确了上述概念之后,此时我们再谈加密/解密方式成本就会降低许多,所以下面就让我们正式进入常见加密/解密算法的学习吧!
对称加密和非对称加密
明白,在不同的场景或领域下,采用的加密方式是有差异的,加密方式不是一成不变的。而在HTTPS协议中,因为其是为了保证数据在网络传输时的安全性,所以最常见的加密方式就是对称加密和非对称加密。下面我们就对什么是对称加密,什么是非对称加密进行一个简单的了解。
1.对称加密
对称加密也被称为单秘钥加密,顾名思义就是只使用一个秘钥进行加密操作和解密操作,所以对称加密最大的特征就是:加密和解密所用的秘钥是相同的。而对称加密一般使用的算法是DES/AES/TDEA等…,对称加密的特点在于其算法公开,较为简单,计算量小,加密/解密效率高。
2.非对称加密
而非对称加密同理也被称为双秘钥加密,同理此时加密操作和解密操作则由不同的秘钥完成,其中一个叫公钥,另一个叫私钥,若使用公钥加密,那么只有使用与公钥匹配的私钥才能解密,反之同理。所以非对称加密最大的特征就是:加密和解密所用的秘钥是不同的。一般使用的算法则是:RSA/DSA等…,特点在于其算法强度高,计算量大,加密/解密效率较对称加密低。明白了上述非对称加密的基本基本概念之后,此时我们再明确两个知识点及一个问题。明确,之所以说公钥加的密只有私钥能解,是因为非对称加密算法在生成公钥和私钥时,公钥和私钥之间是匹配的、相关的,也就是其中一个秘钥是根据另一个秘钥生成的。注意:非对称加密算法中生成的两个秘钥,谁是公钥,谁是私钥是由人决定的,所以并不存在公钥是根据私钥生成或者私钥是根据公钥生成这个说法的,只能说非对称加密算法中生成的两个秘钥,其中一个秘钥是根据另一个秘钥生成的。并且明白虽然其中一个秘钥是根据另一个秘钥生成的,但是并不存在通过其中一个秘钥推出另一个秘钥的概念,当然也就是不存在通过公钥推出私钥的概念,当然具体为什么不行,这就涉及到了非对称加密最核心的部分,采用了那种数学算法来实现公钥和私钥之间的配对机制。如:上述提到的RSA算法使用的数学算法就是大素数分解,DSA使用的数学算法就是离散对数。当然本质理解也就是在实现一个不可逆场景下,根据某数据生成另一匹配数据的同时,保证该数据处理之后的数据,只有根据该数据生成的匹配数据能识别。这也就是RSA/DSA算法的核心工作原理。 OK,明确了上述两个知识点,我们再解决最后一个问题,对于非对称加密的理解可以说就算是大功告成了。为什么非对称加密中的两个秘钥,一个叫私钥,另一个则叫公钥呢?想要搞懂这个问题,首先我们则要明白对于私钥来说,它就是一个全网唯一的秘钥,只有我自己知道,而对于公钥来说,则是全网公开,所有人都可以获取的秘钥,当然从另一个角度理解,公钥也就是不担心别人获取的秘钥。当然之所以不担心别人获取的本质原因,和上述所说一样,公钥加密后的数据只有私钥能解开。所以此时通过公钥和私钥的概念,我们就能明白为什么一个要叫私钥,一个要叫公钥了,原因就是当两者需要进行数据传输亦或者说需要进行通信,那么首先其中一端就需要将自己的公钥给对端亦或者说对端就必须知道另一端的公钥,只有这样两端之间才有可能搭建出一个理论上安全的通信环境。
HTTPS协议的工作探究
经过上述一系列的描述,我们认识了HTTPS,发现它只是在HTTP协议的基础上封装了一层软件层,而封装这层软件层的目的仅仅只是为了对HTTP请求/响应数据做加密,而加密方式一般使用的是对称加密和非对称加密,而对于对称加密和非对称加密来说,它们各有优缺点,对称加密的效率高但算法强度弱,非对称加密算法强度高但加密效率低。所以此时问题就来了,HTTPS协议中的软件层到底用的是对称加密呢?还是非对称加密呢?具体原理又是什么?此时我们就通过对不同加密方式做分析,以不同方案的视角来看看使用不同加密方式会出现那些问题,最终通过不断改进演示出HTTPS真正的工作原理。
方案一:只使用对称加密
只使用对称加密,也就是让服务端和客户端之间共用同一个秘钥,服务端用该秘钥加密数据,客户端用该秘钥解密数据,反之同理。分析:从理论上来看这个方法好像确实能保持两方的通信安全。好比古代皇帝和边疆大臣之间,两人拥有同一个秘钥,边疆大臣确实就可以在远方使用该秘钥对数据加密,然后通过驿站将这份加密完成的数据传到皇帝的手上,皇帝再用他的秘钥进行解密,两人成功安全的完成数据传输。但仔细一想,好像哪里不对劲。哦,原来是古代边疆大臣在出发之前,都需要面圣,在面圣的过程中和皇帝达成使用同一秘钥的约定,然后皇帝就赐给大臣一个秘钥。那放眼现在呢?我们如果也想使用客户端和服务端进行通信,在仅使用对称加密的情况下,我们是不是也需要和服务端有一个约定呀!那么应该如何进行这个约定呢?也像古代一样去面圣,去目标服务器所处公司申请。显然这是不合理的,那有的同学就会说我们可以直接使用网络通信来实现这个约定呀!所以这就是只使用对称加密的弊端,无法确保唯一秘钥的安全性。从另一个角度出发,就算你能保证唯一秘钥的安全性,那么全网的每一个服务器就都需要完成对所有客户端秘钥的管理工作,这显然也极其不合理。所以该方案不合适。
方案二:只使用非对称加密
上述我们只使用对称加密来保证数据传输的安全性显然是不可能的。所以方案二我们来看看使用非对称加密是否能实现。而对于只使用非对称加密来说,此时可以分为两种情况来讨论,一个是服务端和客户端之间只有一端使用非对称加密算法,另一个是服务端和客户端两者都使用非对称加密算法。对于第一种情况,若此时是服务端使用了非对称加密算法生成了一个公钥和一个私钥,那么它就可以以明文的方式首先将自己的公钥传递给客户端,此时客户端就可以使用该公钥,对HTTP请求数据做加密,从而保证了从客户端到服务端之间的数据安全。但同理因为只有一端使用了非对称加密,所以此时无法保证服务端在响应数据时的数据安全问题。所以我们发现在只使用非对称加密算法的情况下,只有第二种情况能够符合我们目前的要求,实现两端通信的安全性。如下图所示:
如上图所示,想要实现两端通信的安全性,就必须让两端都使用非对称加密算法,都生成属于各自的公钥和私钥,然后通过交换公钥,利用对端公钥对数据做加密,本端私钥做解密,完成请求和响应双端通信都安全的目的。虽然上述我们通过两端都使用非对称加密算法实现了两端通信的合理性,但是因为非对称加密算法自身存在的缺点,此时数据在传输过程中因为加密和解密过程,就会导致数据传输效率降低。所以同理为了避免这一问题,就有了下述方案三对称加密和非对称加密的配合使用。
方案三:对称加密和非对称加密配合使用
安全问题此时我们已经有了合理的解决方案,但因为效率问题,所以我们还需要进行改进。本质也就是将对称加密算法的优点和非对称加密算法的优点结合在一起,构建出一个既高效又安全的网络通信方案。从目标出发,此时我们就很容易得出结论,明确实际的数据传输我们肯定不能使用非对称加密算法,那么自然就要使用对称加密算法,而非对称加密算法又无法保证双端通信的安全,那么自然就是让非对称加密算法去保证双端通信的安全。具体原理也就是:让服务端根据非对称加密算法生成一个公钥和私钥,然后将公钥提供给客户端使用,当客户端获取到公钥之后,客户端就调用对称加密算法,生成一个唯一秘钥,然后使用服务端的公钥对该唯一秘钥做加密处理发送给服务端,最后服务端使用私钥对该加密数据做解密,获取到客户端的唯一对称秘钥。当服务端获取到客户端使用对称加密算法生成的秘钥之后,此时两端就可以安全的使用这个唯一秘钥进行通信,从而实现保证安全的同时,也提高了数据传输的效率。注意
: 几个点明确一下,第一,若你使用的是HTTPS协议,那么在发送HTTP请求之前,软件层(SSL/TLS)首先会发送一个SSL/TLS请求,当服务器收到这个请求之后,才会将该服务器的公钥响应给客户端,所以也就是在这时,客户端才拿到服务端的公钥。第二,因为HTTPS协议在应用层,应用层在网络协议栈,所以大家的应用层都是相同的,大家的软件层也都是相同的,所以对于服务端和客户端谁调用的是对称加密算法,谁调用的是费对称加密算法是由人决定的,当然人是按照上述原理决定的。第三,一个对称加密算法生成的秘钥只能维持一个通信会话,也就是两端的安全秘钥只在客户端和服务端建立连接的情况下有效,一但断开连接或者说是四次挥手,那么这个秘钥就会失效。明确方案一中服务端管理秘钥问题的解决。所以本质方案三解决的就是方案一中秘钥传输不安全的问题。解决方法:非对称加密。
HTTPS协议核心BUG解决
行文来到这里,没错我们需要有一个承上启下的话题,这个话题叫做CA证书。那么什么叫做CA证书?伴随着这个问题,此时我们就需要先解决上述我们所说理论上安全的通信过程中一个隐含问题。在上述我们利用非对称加密算法的公钥来实现保护对称加密算法的唯一秘钥,保证了客户端在获取到公钥之后的网络安全通信。那么此时这个过程一定是安全的吗?答案是否定的。在深入探索该问题前,我们先明确如下几个概念。
什么是数据摘要(数据指纹)
本质很简单,数据摘要就是对一个文本数据使用特定Hash算法生成的一个固定大小的字符串,而因为Hash算法的设计原因,此时这个固定大小的字符串具有很强的唯一性。数据摘要的特点:文本内部数据只要发生细微改变,那么与之前的数据摘要相比,此时的数据摘要都有可能发生巨大的改变。并且因为此时这种专门用于生成摘要的Hash算法中,使用了大量的模幂运算和符合运算,所以导致数据不能被还原,也就是不能依据数据摘要还原出文本数据。同理,对一个文本数据做摘要并不属于加密过程。并且明白,数据摘要最大的用处就是它能以最低的成本,最高的效率快速的判断出两个文本数据是否相同。而根据这一用处,数据摘要则被广泛应用于校验文件完整性的场景。当然除了该场景之外,数据摘要也经常被用于保护数据安全和数据备份。其中对于保护数据安全来说,最经典的就是保护服务器后台数据库中的用户信息,本质也就是数据库中的用户数据并不能明文存储,必须要经过Hash变成数据摘要存储。而对于数据备份来说,最经典的就是网盘技术,本质也就是在网盘上会存在非常多的相同数据,当你在上传数据时,网盘就会对你的数据做数据摘要,然后根据这份摘要与已拥有数据的摘要作对比,如果已经存在,网盘为了避免重复存储,就会将已存在的数据直接拷贝给你,避免上传数据时的消耗和节省存储空间。
什么是数字签名
明确了上述数据摘要之后,对于理解数字签名就非常简单,数字签名的本质也就是对数据摘要做加密。这句话从表面来看好像很好理解,但其涉及的知识还是较为繁琐的。如:是对什么数据的摘要做做加密,如何加密,谁来加密,为什么要加密?理所当然,想要搞懂这些问题,此时我们就需要再次回到主线上,所以下面我们同理继续讲解网络安全通行相关的知识。
什么是CA证书
明确了上述有关数据摘要和数字签名的概念,此时我们正式回到该篇博客的主线,回答为什么上述方案三不一定能保证在网络中安全通信的问题,从而引出CA证书的相关概念。其实很简单,上述方案三中我们说只要当客户端获取到服务端公钥,客户端就会采用对称加密算法生成唯一秘钥,然后通过服务端公钥对唯一秘钥进行加密,并且发送给服务端,从而让两端安全的拿到唯一秘钥,进而完成通信。但是如果当服务端在发送公钥时,亦或者说当公钥在网络中传输时,公钥就被黑客通过中间人的形式截取,然后黑客自己也用非对称加密算法生成一个公钥和一个私钥,将服务器公钥保存的同时,将自己刚生成的公钥以原服务器数据包的形式返回给客户端,此时客户端因为无法识别到数据来源,所以默认认为是服务端发送的公钥,然后同理上述步骤,此时客户端就会使用黑客的公钥对自己的唯一秘钥做加密,然后发送出去,在发送过程中,黑客同理截取,从中提取出被自己公钥加密之后的唯一秘钥,然后用自己的私钥解密,获取唯一秘钥,最后再将唯一秘钥使用服务器的公钥加密,返回给服务器。所以通过上述过程,黑客或者中间人就可以监听甚至修改客户端和服务端之间的数据。
明白了上述问题之后,我们就发现,就算是采用对称加密和非对称加密配合使用的方式,也无法完全保证网络通信中数据的安全性。所以为了解决这一问题,CA证书的概念也就是诞生了。那么到底什么是CA证书呢?先不着急,我们从问题出发,明确之所以会出现上述问题,主要是因为两个方面,其一是想要访问服务器,某些数据就必须以非安全的形式在网络上传输,而这个问题最好的解决方案就在上面,依然是不安全的,所以对于这个方面来讲,是无解的。其二是因为客户端在接收数据时,无法确定数据的合法性,最终导致上述问题。而针对后面这个点,我们就提出了相应的解决策略。明白只要让客户端可以识别到数据来源,我们就能保证通信安全。所以此时的策略就是让全网服务器都有办法标明自己合法性和来源。而为了实现这一目标,传说中的CA机构就诞生了,一个专门为服务器颁发CA证书的权威结构。所以明白当一个服务器拥有了CA证书,它就可以被客户端识别以及校验合法性,从而防止公钥被篡改。具体如何实现以及CA证书中包含那些信息,下述详谈。
正式进入对证书的理解
通过上述的描述,我们明确只有当服务端拥有了CA证书,客户端才能校验公钥的合法性,从而保证网络通信的安全。那么具体的原理是什么呢?在搞清这个问题之前,我们先来看看服务器应该如何拥有自己的CA证书,当然也就是如何向CA机构申请证书。
明白,若一个服务器想要拥有自己的证书,那么它就需要向CA机构提交申请证书所需的资料。而一般这些资料都是被包含在一个叫CSR:证书签名请求文件中。而想要获取CSR文件,我们就需要使用SSL工具,然后将对应的域名、申请者和公钥等信息填写进去,然后它就会返回一个CSR文件,其中CSR文件中就包含了我们刚才填写的域名、申请者和公钥等信息…,最后将CSR文件提供给CA机构,当CA机构获取到某CSR文件之后,它会将签发机构,也就是自己的基本信息也写入到该CSR文件中,然后根据对应的哈希算法对该CSR文件做摘要,最后用自己的私钥对该摘要进行加密,从而生成一个独属于该CSR文件的数字签名。而当一个CSR文件拥有了该CA机构的数字签名,那么对应的服务器就获取到了CA证书,总而言之,CA证书等于CSR文件+数字签名。具体如下左图所示:
所以当行文来到这里,此时我们就默认全网所有的服务器都有着自己的CA证书,那么同理与之配对产生的问题就来了,客户端应该如何识别这个CA证书呢?同理如上述右图所示,根据上述所说,在发送HTTP请求之前,软件层(SSL/TLS)首先会发送一个SSL/TLS请求,只要当服务器收到了这个请求,服务器此时就会将自己的CA证书发送给浏览器。而当浏览器收到了服务端的CA证书,此时它就需要对这个证书进行验证工作,第一步就是将该CA证书拆分成数字签名和CSR文件,然后同理使用对应的Hash函数对CSR文件做数据摘要,使用CA机构提供的公钥对数字签名做解密,然后获取到两个哈希值,对两个哈希值做比较,如果相同则说明数据正常,反之数据被篡改。而如果当数据正常,那么我就可以安全的从CSR文件中提取出服务端公钥了。注意: 同理两个明确一个问题。明确,上述之所以可以直接使用CA机构的公钥,本质是因为CA机构是一个权威机构,无论是我们电脑中的浏览器生产商还是操作系统生厂商,它们在生产时就已经将权威CA机构的公钥内置进去了。并且明白,之前我们说非对称加密不仅可以使用公钥加密,私钥解密,也可以使用私钥加密,公钥解密,上述对CSR文件做签名生成CA证书和对CA证书进行验证的过程,就是一个经典的使用私钥加密,公钥解密的使用方法。所以明确并不是只存在公钥加密,私钥解密的过程。同理,之所以以这样的加密方式实现,要体现出的就是CA机构的权威性,因为CA机构是使用私钥来签名,也就导致全网只认CA机构的公钥,全网只有CA机构能签名,从而保证了数字签名的唯一性。最后一个问题,为什么通过上述方式,我就不担心数据被篡改了呢?首先明白,和之前的原理一样,使用的是非对称加密和对称加密算法配合使用,我首先传递的都是公钥,但此时因为我有证书,我的公钥是在证书中保存,所以当一个黑客想要篡改我的公钥,那么也就是篡改我的CSR文件,但是因为在黑客篡改我的CSR文件之前,我对该CSR文件的数据摘要就做了签名,所以如果黑客篡改了我的CSR文件,那么当我解密数字签名,并且对CSR文件做摘要之后,就会发现CSR的摘要和解密之后的数字摘要不同,那么此时我就确定,这个数据在网络传输过程中被篡改过,我直接丢失。同理,如果黑客将CA证书中的数字签名做篡改,那么因为我的浏览器和操作系统中内置了CA机构的公钥,当浏览器或者操作系统使用该公钥对该数字签名做解密时,就会发现解密失败,同理我也可以明确CA证书被篡改,同理丢弃。当然如果黑客将我们的整个CA证书都篡改掉,那么同理因为浏览器和操作系统内置公钥无法对数字签名做解密,所以同理可以识别出数据被修改。所以黑客如果想要篡改我们的数据,唯一的方法就是黑客自己也申请一个CA证书,也就是将黑客的公钥给内置到浏览器和操作系统内部,然后当黑客直接替换我们的证书时,黑客自己的数字签名可以被浏览器和操作系统解密。而面对这个问题,因为我们的CSR文件中还存在着域名,所以当你将证书给替换之后,浏览器依然可以通过域名检测出不同,本质也就是CA机构在审核过程,就会对域名进行审核,一个域名只能申请一次。所以黑客的域名和目标服务器一定是不一样的。当浏览器检测到这点之后,自然就不会再去使用黑客证书中的公钥了传输数据了。
拓展:
在生成CSR文件之前,我们需要在本地利用非对称加密算法生成对应的公钥和私钥,然后将公钥交给CSR文件,而在本地生成公钥和私钥的这个过程,我们使用Linux系统就能完成(指令:ssh -keygen -t rsa
)。