这篇文章有点长,分为两部分,前半部分通过一个实例来演示了一个完整的渗透过程,后半部分详细解释了HTTPS的实现原理,两部分内容没有关联性。

这两年国家对反诈的打击力度可以说是史无前例,我想这背后大概有这么几个原因。

首先,国内的互联网发展非常迅速,2021年国内互联网参与人数已经超过了10亿,这给诈骗团伙提供了一片非常大的猎场。

其次,在网络世界没有百分百的安全,更糟糕的是,由于计算机发展迅猛,虽然摩尔定律已不再,但前几十年的高速发展使得很多技术几乎是指数级的更迭,导致相当多的站点还在使用已经不安全的技术。当然,这其中也包括渗透技术,大量的渗透工具出现,使得渗透的入门门槛变更非常低,只要会一些简单的计算机操作,任何一个人只要下载一些工具就可以实现比如qq盗号、生成木马工具、盗取个人信息等操作。随着互联网这张大网不断变大,网络安全环境也变得越来越糟糕。

最后,国人接触互联网的时间太短,大都没有相关的安全意识,容易中招。

这时候有人说了,这个网络安全和诈骗团伙有啥关系?我想,当你接到一个诈骗电话时,对方可以准确叫出你的名字和你的住址这肯定不是巧合。

20世纪90年代,HTTP/0.9发布,标志了HTTP协议诞生,1993年发布了HTTP/1.0版本,1992年JPEG格式被发明,1995年MP3格式被发明。同年,著名的浏览器大战最终以微软的IE胜出收尾,1999年HTTP/1.1发布RFC2616文档,中间经过几次修订,一直沿用到今天,虽然很多浏览器厂商都已经支持HTTP/2,但HTTP/1.1仍然是使用最多的版本。

HTTP协议于互联网就相当于毛细血管于人一样重要。毫不夸张的说HTTP协议撑起了互联网的整片天。但是,HTTP也有它致命的缺点,其中最大的问题就是它是明文传输,比如你喜欢班上的一个女孩子,又不好意思直接对她说,你让同桌帮你带话,但是你的同桌离她太远,他又让另一个人帮忙带话,一来二去整个班都知道你喜欢她了。

如果不想让人家知道内容又想让人家帮你带话,那最好的方法就是说暗语,比如你可以找机会送给她一本书,然后让你的同桌递给她一张纸条,纸条上一行写三个数字,第一个数字表示多少页,第二个数字表示多少行,第三个数字表示第多少个字。她如果知道规则的话,通过数字就能从书中找出所有的字,然后排成一排,内容是:“我喜欢你”,这样你喜欢她这事就只有你们两个人知道了。这就是HTTPS协议,关于HTTPS协议后面会详细拆解,读完这篇文章相信可以彻底搞清楚HTTPS的实现原理。

我们回到HTTP协议,通过一个实际的例子来演示,那些别有用心的人是如何悄悄盗取我们的信息的。

首先,我们要准备一下环境,这里我们使用kali,kali是一个专门用于渗透测试的linux发行版,里面集成了各种渗透测试工具。我们可以使用虚拟机来安装,推荐使用Virtualbox,Kali的界面如图 1-1。

图 1-1 Kali操作系统界面

然后我们使用airxxx工具集来破解一个wifi,这里要注意的是因为要监听所有数据包,我们要使用一个支持混杂模式的网卡,下面是我使用的网卡,如图:

图 1-2 支持混杂模式的无线网卡

准备好环境之后,就可以开始了。首先,我们看一下网卡有没有被识别。

图 1-3 无线网卡

接着开启混杂模式,如下:

图 1-4 开启网卡混杂模式

开启之后可以得到一个wlan0mon的网卡,如下图:

图 1-5 开启混杂模式的网卡

扫描附近的wifi热点,这里我创建了一个测试的热点,是一台小米路由器。

图 1-6 扫描附近热点

然后我们使用airodump工具来获取握手包,如下:

图 1-7 抓取握手包

airodump启动之后可以使用aireplay工具不断发送握手包,将连接到热点的设备踢下线。

aireplay-ng -0 -o -a {上面的BSSID}  -c {设备MAC地址}  wlan0mon

然后我们看到属主目录下的握手包文件:

图 1-8

使用kali自带的字典来尝试破解,如下

aircrack-ng -w /usr/share/wordlists/rockyou.txt /home/-17.cap

最终可以看到成功破解了wifi密码

图 1-8 破解的wifi密码

这时候你可能会说,wifi破解了也没啥用啊,大不了让你蹭下网。如果你这么想那就太天真了,实际是只要破解了wifi,黑客就可以连接这个wifi和你就在同一局域网上,几乎想干嘛就干嘛。通过arp欺骗可以嗅探你发出去的数据包,甚至可以实时看到你的手机屏幕。我们这里为了说明HTTP协议明文的弱点,只尝试嗅探局域网中的数据包。

破解了wifi就可以连上去了,连上wifi之后我们就可以arp欺骗,首先设置路由转发:

echo 1 > /proc/sys/net/ipv4/ip_forward

接着我们发送arp包,就相当于告诉被攻击的手机或者电脑,我就是网关,后面的请求都发送到我这里来。

arpspoof -i eth0 -t 192.168.31.186(目标) 192.168.31.1(网关)

然后使用ettercap工具来嗅探数据包

ettercap -Tq -i eth0

我们在另外一台机器连上刚刚的wifi,然后打开一个网站,比如www.4399.com(由于这个网站这是使用HTTP协议),然后我们输入帐户和密码,如下:

图 1-10 使用HTTP协议的网站

最后,我们回到ettercap终端,如下:

图 1-11 网络嗅探

可以看到,我们已经拿到帐号和密码了,虽然这里的密码并不是明文,但很明显这里是站点为了隐藏明文做了一次hash计算,但我们有了这个hash值同样可以构造请求登陆成功。

在上面的演示的过程中,全程几乎没有写什么代码,全是使用kali现成的工具,可以看出,现在搞破坏的门槛已经非常低了。如果这背后的人熟悉网络原理通过脚本实现整个过程的自动化,就可以源源不断的去收集个人信息,这也是为什么现在个人信息泄漏这么严重的原因了。

在上面这个例子中,我们可以发现,wifi的破解是第一步,然后因为HTTP协议的明文特性,导致我们私密的信息在网络中几乎没有隐私可言。其实要解决这个问题也很简单。首先,wifi密码要设置得复杂一点,最好同时包含大小写字母、数字和特殊符号,我们上面的例子中,wifi密码设置得太简单,可以看一下kali自带的密码字典,使用下面的命令:

less /usr/share/wordlists/rockyou.txt

图 1-12 kali字典文件

可以看到,字典里面的密码特征都是比较明显的。除了增加wifi密码的强度,还要注意不要随便连wifi,现在4G和5G速度已经很快了,并且资费也并不是很贵。其次,现在HTTPS普及的速度是非常快的,我们平时使用的淘宝、京东、美图都使用了HTTPS协议,中间劫持的成本会非常的高,所以相对来讲是安全的,关于HTTPS在接下来的部分会详细说明。

注意!!!

这里声明一下,以上所有操作都是在测试环境中运行,随意破解和嗅探是违法的。

HTTPS 协议

前面我们说HTTP协议存在的最大的问题在于它的安全性,所以才有了后来的HTTPS协议,HTTPS多出来的S指的是SSL或者TLS,目前HTTPS协议一般都认为是HTTP+TLS。

这里不对HTTPS一些众所周知的特性进行介绍,比如端口使用443,使用https打头等。

1995年发布的SSL3.0是HTTPS的第一个第一个版本,后来改名为TLS,包括1999年发布的TLS1.0版本,2006年发布的TLS1.1版本,2008年发布的TLS1.2版本,2018年发布的TLS1.3版本(这也是目前最新版本)。

下面是TLS和HTTP协议在网络分层上的关系,如下图

HTTP/TLS网络分层关系

我们可以思考一下,要实现真正的安全通信要解决哪些问题呢?

通常认为具备机密性完整性身份认证不可否认四个特性的网络通信是安全的。

机密性,只有通信双方能读得懂,对其它人是加密的。比如发送端可以将传输内容通过密钥加密,接收端再通过相同的密钥解开就能得到对应的明文消息了。

完整性,完整性指的是在传输的过程中数据没有被篡改。比如,你让你的好朋友向你喜欢的女孩子带话:“今天晚上9点,在操场上见”。但你朋友不想你们见面,于是告诉她:“今晚xxx约你在食堂见面”,你就这样和你喜欢的人错过了。

身份认证,你需要证明你是你,才能让你通过。比如,你去坐火车,就要证明你是你,而证明的方式是身份证。

不可否认,这就要求你要对你发送的内容负责任,比如,之前网络上有一个段子,说是有一个人用了花呗不想还款,然后就把支付宝给卸载了... ...

我们前面说,HTTP最大的问题就明文传输,一旦别有用心的人在中间劫持了我们的请求,就没有秘密可言了,几乎可以不费吹飞之力就可以拿到我们的私密信息。人们就想,是不是可以将发送的内容进行加密,然后将密文发送出去,接收方收到密文之后再将密文还原成明文。这样,即使中间被别人劫持拿到的也是密文,根本不知道传输的真正内容是什么。

常用的加密算法大致可以分为对称加密非对称加密,由于对称加密的性能比非对称加密要高出几个数量级,所以,一般使用对称加密作为数据传输的加密方式(至于为什么对称加密的性能要比非对称加密的性能高,读到最后相信你会有答案的)。

常用的对称加密算法有DES、3DES、RC4、AES、ChaCha20等,但是前三种已经被证实是不安全的,所以目前常用的是AES和ChaCha20。因为很多硬件都对AES进行了优化,实际上现在主流都是使用AES作为对称加密算法。下面我们就来详细看一下AES的原理。

AES对称加密

为了说明AES加密算法,我们先来搞明什么是对称加密。对称加密的核心是XOR(异或)运算。例如,我们指定一个密钥key=4,要传输的明文是8,它们对应的二进制表示分别是0100和1000,然后对它们做XOR运算,得到1100,这就是加密后的密文,如下图:

图2-1 异或运算

当接收端收到密文1100,使用密钥0100对密文进行一次XOR运算就可以还原出明文了,使用1100(密文) XOR 0100(密钥) = 1000,这里你可以思考一下这样为什么能行,能不能根据密文直接推导出密钥或者明文消息呢?

按照上面的方式,假如要传输的明文非常的长,同样也就需要一个很长的密钥key,这显然是不现实的。所以,人们就想能不能用一个固定长度的密钥去加密任意长度的明文呢?答案是可以的,我们只需要将明文分成多个块,每一块的长度和我们的密钥长度是一样的,这样我们可以使用同一个密钥分别对每个块进行加密,如下图:

图2-2 ECB分组加密

上面这种直接对明文进行分块的加密模式叫做ECB(Electronic Codebook),这种模式有一个问题就是没办法隐藏数据特征,如果一个攻击者抓取大量的数据包就可以分析出数据的特征,从而破解密钥。如下图:

图2-3

如图2-3,我们期望得到图中最右边这样没有特征的数据。

另外一种加密模式CBC(Cipher-block Chaining)就可以解决上面的问题,其原理是将每个明文块先与前一个密文块进行XOR运算后,再进行加密,如下图:

图2-4 CBC分组加密模式

但是,这样还是有一个问题,就是整个过程串行化了,没办法利用多核的优势。

为了解决上面两种加密模式的缺陷,计算机科学家们又发明了CTR(Counter)模式,其原理就是通过一个加密计数器来混淆数据,使密文失去特征。如下图:

图2-5 CRT分组加密模式

但是,CTR也有自己的问题,由于不是串行化的,所以自身无法提供数据完整性的校验。为了既能隐藏数据特征,又可以实现数据一致性校验,计算机科学家们又发明了GCM加密模式,GCM加密模式是CTR+GMAC。我们先看一下如何进行数据一致性的校验。

最常用的数据一致性校验就是计算数据的Hash值,将数据和计算出的Hash值发送出去,当接收端收到数据的时候,再以相同的Hash计算方法计算出数据的Hash值,然后和传过来的Hash值进行比较,如果相等说明数据没有被篡改。常用计算Hash值的方法比如MD5、sha1、sha2等等。

下面是GCM加密和计算校验值的过程

图2-6 GCM数据校验原理

因为GCM的每个数据块都有一个counter,通过这个counter我们可以把数据块拼起来计算hash值,得到一个AuthTag。这个AuthTag就是最终校验值,接收端收到之后以同样的方式计算校验值就可以对数据进行校验。

通过上面的分析,我们对对称加密原理应该是有了比较深刻的认识了,但还有一个问题没有解决,由于对加密的密钥和明文每一位都是一一对应的,所以如果明文长度不够的话还要进行填充,现在比较主流的填充方式都是以字节为单位填充,这是因为我们一般是不会直接使用二进制位发送数据,字节填充有以下几种:

| DD DD DD DD DD DD DD DD | DD DD DD DD 00 00 00 00 |

| DD DD DD DD DD DD DD DD | DD DD DD DD 00 00 00 04 |

最后一个字节表示填充了多少字节

| DD DD DD DD DD DD DD DD | DD DD DD DD 81 A6 23 04 |

  1. 补零

  2. ANS|X9.23

  3. ISO 10126

  4. PKCS7

    | DD DD DD DD DD DD DD DD | DD DD DD DD 04 04 04 04|

    填充的每一位都表示填充了多少字节

上面我们详细说明了对称加密的核心逻辑,下面开始我们来分析AES加密原理。

AES(Advanced Encryption Standard)加密算法

AES加密算法由比利时密码学字Joan Daemen 和 Vincent Rijmen设计,所以AES算法又称为Rijndael加密算法。AES常用填充算法使用的是PKCS7,常用的分组工作模式是GCM,这些在上文中已经解释过了,如果觉得陌生可以回过头再去回顾一下。

AES加密步骤可以分为以下4步:

  1. 把明文按照128bit拆分成若干个明文块,每个明文块是4*4的矩阵。

  2. 按照选择的填充方式填充最后一个明文块。

  3. 每个明文块利用AES加密器和密钥加密成密文块。

  4. 拼接所有密文块组成最终的密文。

我们来看一下AES的加密流程,也就是上面的第3步

AES加密可以分为AddRoundKeySubBytesShiftRowsMixColumns几种操作,一般AES都会经过多轮加密得到最终的密文,下面是不同密钥长度对应的加密的轮数:

AES 密钥长度(32Bit) 分组长度(32Bit) 加密轮数
AES-128 4 4 10
AES-192 6 4 12
AES-256 8 4 14

要注意表中的密钥和分组长度的单位是32Bit也就是4字节,所以实际长度要乘以4。比如,AES-128对应的密钥长度就是16字节。

在整个加密过程中,又分为一轮初始轮、一轮最终轮和多个普通轮。初始轮、最终轮和普通轮所进行的加密步骤又是不一样的,如下:

初始轮

  • AddRoundKey  轮密钥加

普通轮

  • AddRoundKey  轮密钥加

  • SubBytes          字节替代

  • ShifRows          行移位

  • MixColumns     列混合

最终轮

  • SubBytes          字节替代

  • ShiftRows         行移位

  • AddRoundKey  轮密钥加

下面分别来分析AddRoundKey、SubBytes、ShiftRows、MixColumns的具体实现。

AddRoundKey

矩阵中的每一个字节都与该回合密钥(round key)做XOR运算,每个子密钥由密钥生成方案产生。如下图:

图2-7 Add Round Key操作

图中的明文a通过和密钥k做XOR运算,得到密文b,要注意这里的k不是原始密钥,是通过密钥扩展算法得到的。密钥扩展算法大致流程如下:

  1. 将明文块里的内容进行字循环,左移1个字节

  2. 使用S盒字节代换

  3. 使用当前轮常量RC[j]进行异或运算,其中j表示当前轮数

图2-8 密钥扩展算法

第一轮的密钥是一个4*4字节的矩阵,将每一列组成一个字(Word),对应图中的W0、W1、W2、W3,然后每个字通过一个g函数加上XOR运算得到一组新的字,对应图中的W4、W5、W6、W7,那么g函数做什么事呢?从上图中可以看到,g函数会将字中的每个字节做一次循环移位,B0、B1、B2、B3进行一次移位之后就变成了B1、B2、B3、B0。做完位移之后用S沙盒做代换,得到B'1、B'2、B'3、B'0,然后通过RC数组进行一次XOR运算,就得到一个新的字W',这个就是通过g函数之后得到的最终的一个字,上面的W4、W5、W6、W7就是通过W0、W1、W2、W3和g函数的结果进行XOR运算得到的最终结果。这里的RC数组前面的元素都保存了每一轮运算的结果,最后三位都是0,如下:

RC = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B,0x36}

SubBytes

SubTypes步骤是透过一个非线性的替换函数,用查找表的方式把每个字节替换成查找到的字节,这里的关键是非线性,实际上是通过随机性来对抗线性的简单代数性质出现的攻击点。

图2-9 Sub Bytes操作

SubBytes最终输出的结果是通过原数据从S沙盒里查找到的结果。

这里有个关键点就是查找表,也就是S盒,其对应的是一个二维向量表:

ShiftRows

ShiftRows操作是将矩阵中的每个横列进行循环式移位,操作步骤如下:

图2-10 Shift Rows操作

  1. 第一行保持不变

  2. 第二行循环左移1个字节

  3. 第三行循环左移2个字节

  4. 第四行循环左移3个字节

MixColumns

将当前矩阵和上一步得到的结果矩阵进行矩阵相乘,得到最终的结果,如图:

图2-11 MixColumns操作

好了,到此为止,我们使用GCM加密模式的AES加密算法可以实现对明文的加密和解密。就算有人截获了我们发送的消息拿到的也只是一串密文,没有解密的密钥也没法看到里面的明文。

但是,这事仔细想想还没那么简单,这个加密的密钥要怎么给到对方呢?如果直接传给对方,那攻击者就可以通过抓取报文获取到密钥,这样他就可以对密文进行解密了。真是头疼啊,那我们是不是可以对密钥也进行加密呢?我们再生成一个密钥,用来加密密钥,但是这样攻击者还是可以通过密钥解出来我们要传递的密钥,总不能无限套下去吧。这里该轮到我们的非对称加密算法登场了,所谓非对称是指加密和解密的密钥可以不一样,由一对私钥和公钥组成,公钥可以对外开放,通过公钥加密的数据只能使用私钥解密,通过私钥加密的数据也只有公钥可以解密。这样我们就可以在不泄漏私钥的前提下完成对数据的加解密了。

在TLS中,常用的非对称加密有DH、DSA、RSA、ECC等,其中RSA最为著名,以至于我们常常把非对称加密称作RSA加密。

RSA的核心原理是基于“整数分解”的数学难题,使用两个超大的素数的乘积作为生成密钥的原始数据,从而使得通过公钥推导出私钥是非常困难的。具体为什么困难,相信看完下面对RSA的解释就会有答案了。

RSA算法是1977年由Ron Rivest、Adi Shamir和Leonard Adleman一起提出,因此命令为RSA算法。

RSA算法公私钥的生成

前面说到RSA的原理是依托于整数分解的数学难题,下面我们来看一下RSA公私钥生成的步骤:

p = 11, q = 29

n = p * q

n = 319

v = (p-1) * (q-1)

v = 280

(d * k) % v = (k * d) % v = 1

d = 187

(d, n) => (187, 319)

  1. 随机选择两个不相等的质数p和q

  2. 计算p和q的乘积n

  3. 计算n的欧拉函数v=φ(n)

  4. 随机选择一个整数k

    k满足 1 < k < v,  且k与v互质,这里假如k=3

  5. 计算k对于v的模反元素d

  6. 公钥:(k,n), 私钥:(d,n)

    (k, n) => (3, 319)

通过上面的步骤我们就计算出了公钥和私钥,很多人就就有疑问了,这怎么和我平时看到的公钥和私钥不一样呢?这里只是演示了计算过程,得到的只是原始数据,一般我们看到的公私钥都是经过类似openssl这样的加密套件编码之后的内容,比如openssl里ASN.1格式的编码。

下面我们通过上面生成的公私钥来验证一下RSA的加解密流程,假如我们要对123进行加密。上面我们只生成了对应的公钥和私钥,那如何通过公私钥进行加解密呢?RSA对应的加密公式是:c = m^k(mod n),解密公式是m = c^d(mod n),其中m是明文,c是密文。我们使用公钥对123进行加密,代入公式得到:123^3 * mod319 = 140,其中140就是加密后的密文。然后使用密钥进行解密,代入公式得到:140^187*mod319 = 123,可以看到公钥加密的明文可以通过密钥进行解密。然后我们来看通过私钥加密用公钥来解密,代入公式加密:123^187*mod139 = 161,得到密文161。然后代入公式解密:161^3mod319=123,可以看到,私钥加密的明文同样也可以通过公钥进行解密,这就是RSA非对称加密的核心原理。

为了进一步说明RSA加密,下面使用加密套件openssl来实际验证一下RSA的加解密过程。

openssl基于RSA生成公私钥一共分为两步

第一步,生成一个私钥

openssl genrsa -out private-key.pem

内容如下:

图2-12 openssl生成的密钥

第二步,从私钥中提取公钥

openssl rsa -in private-key.pem -pubout -out public-key.pem

内容如下:

图2-13 openssl生成的公钥

RSA是通过ASN.i格式进行编码的,RFC文档里面规定的格式如下:

RSAPrivateKey ::= SEQUENCE { version Version,   modulus INTEGER, -- n   publicExponent INTEGER, -- k   privateExponent INTEGER, -- d   prime1 INTEGER, -- p   prime2 INTEGER, -- q   exponent1 INTEGER, -- d mod (p-1)   exponent2 INTEGER, -- d mod (q-1)   coefficient INTEGER, -- (inverse of q) mod p   otherPrimeInfos OtherPrimeInfos OPTIONAL }

然后我们来解析RSA私钥的内容,如下:

openssl asn1parse -i -in private-key.pem

图2-14

公钥如下:

openssl asn1parse -i -in public-key.pem

图2-15

可以看到n对应的偏移是19,使用strparse可以进一步解析。如下:

openssl asn1parse -i -in public-key.pem -strparse 19

图2-16

通过对公私钥的解析,我们可以看到,对应的n和k是一样的,这也验证了我们前面分析的RSA加密过程。

使用openssl的RSA加密套件加解密

我们创建一个文件data.txt,里面的内容是:“hello wrold”

然后对文件的内容进行加密,得到密文data.private,如下:

openssl rsautl -encrypt -in data.txt -inkey public-key.pem -pubin -out data.private

得到的密文如下:

图2-16 加密密文

由于加密后的密文是一串二进制乱码,所以这里我们使用hexdump查看16进制形式。

然后通过私钥去解密,命令如下:

openssl rsautl -decrypt -in data.private -inkey private-key.pem -out hello.data

这样我们就通过生成的公私钥成功对数据进行了加解密。

通过非对称加密,我们就可以实现基于AES的数据加密密钥的交换,但是这样还是存在一个问题,如果随便一个人都可以生成公私钥,我们怎么区分哪个是真的呢?假如攻击者也生成了一对公私钥,然后引诱你去访问他的站点,这个时候由于他手里有私钥,可以解密所有的密文,还是不安全。

这个时候就需要有一种方法能保证公私钥的权威性。比如,我们用的身份证就是由国家背书的,具有权威性。同样的,互联网也有类似的权威机构来专门提供这类服务,叫PKI(Public Key Infrastructure)公钥基础设施,由CA(Certificate Authority)机构将用户个人身份与公开密钥关联在一起,公钥数字证书由CA信息、公钥用户信息、公钥、权威机构的签字、有效期几个部分组成。PKI面向的用户指的是向CA注册公钥的用户。

证书的签发流程

一般由网站的站长向CA机构发起申请,CA机构通过身份认证之后,会给到申请者一个数字证书,这个证书里包含:证书的名称、组织、国家、用户、有效期、公钥和认证机构的签章。

签名与验签流程

图2-17 数字证书签名与验签流程

证书的签名与验签能够成立的前提是,证书需要在权威机构去申请,站长提交个人信息到证书机构,证书机构使用它的私钥生成一个公钥,然后将站点信息(站点名、有效期,CA机构签章等)通过一个hash算法计算出hash值,然后使用私钥进行加密,最后将加密后的hash值和站点信息以及公钥打包成一个数字证书给到站长,这就是签名过程。

浏览器拿到网站的证书之后,将数字证书里面的信息提取出来,通过协商的hash函数将站点信息计算hash值,然后使用公钥将前面使用私钥加密的hash值解密,判断两个hash值是否相等。至于浏览器是怎么拿到数据证书的,在HTTPS握手的时候会详细讲。

证书信任链

图2-18 数字证书信任链

证书信任链有点类似DNS服务器,会一层一层往上找,最顶层的称为根证书也叫root证书,root证书由于没有上级证书机构了,所以可以实现自校验。这里你可以思考一下,为什么证书机构要分多级呢?

PKI公钥基础设施

图2-19 PKI公钥验证基础设施

数据证书需要通过三方机构来进行验证,而这个三方机构就是PKI公钥基础设施,由于CRL是基于链表查询,效率不高所以后来又搞了一个OCSP,最新版本的TLS基本上都是通过OCSP来进行验签的。

证书类型

  • 域名验证(domain validated, DV)证书

  • 组织验证(organization validated, OV)证书

  • 扩展验证(extended validation, EV)证书

其中DV、OV、EV证书的验签严格程度是越来越高,价格也是越来越贵的,但是他们的加密规则其实是一样的,只是验签的流程不一样。

到这里为止一切看起来都很完美,使用对称加密来保证数据的机密性,使用非对称加密来交换密钥,使用PKI证书体系来进行身份验证。但是,这里面其实还有一个问题。假如,一个攻击者不断在网络上抓包,将历史所有的访问记录都抓下来保存起来了,经过夜以继日的计算有一天他破解了密钥,那么他保存的那些密文也就没有秘密了。

那么,是不是有一种方法可以动态的交换密钥呢?根据我们前面讲的,我们可以每次请求都生成一个密钥通过非对称加密算法传给对方,但这样至少要两次TLL,在性能上不具备优势。人们就想,有没有一种方法,客户端和服务端都根据一定的规则各自生成密钥,并且生成的密钥都是一样的呢?当然,答案是肯定的,这就是DH密钥交换协议。

DH密钥交换协议

1976年由Bailey Whitfield Diffie 和 Martin Edward Hellman首次发表,简称DH。它可以让通信双方完全没有任何预先信息的条件下创建一个密钥,如下图:

图2-20 密钥交换

上图中,DH密钥交换协议可以总结为以下几步:

  1. 客户端发起握手,将自己支持的加密套件发送给服务端

  2. 服务端收到握手包,选一个加密套件,生成一对公私钥,并将公钥返回给客户端,同时还会告诉客户端自己使用的是哪个加密套件。

  3. 客户收到服务端的公钥和使用的加密套件之后,也生成一对公私钥,并将公钥传给服务端

  4. 客户端和服务端根据自己的私钥和对方传过来的公钥生成加密密钥

可以看到,整个过程并没将加密密钥发送给对方,而是双方根据公私钥自己生成的,我们知道对称加密的密钥需要一样才能正常加解密,那双方各自生成的加密密钥是如何保证是一样的呢?下面我们来看一个例子:

现在假如有6个数,a、b、g、p、A、B其中a和b是保密的,g、p、A、B是公开的。

  1. 首先客户端使用a、g和p算出A,公式是A = g^a mod p

  2. 将g、p和第一步算出的A发送给服务端,这里的g、p、A就相当于上图中的公钥

  3. 服务端使用g、p和b算法出B,公式是B=A^b mod p

  4. 服务端将算出的B发送给客户端,这里的B就相当于服务端生成的公钥

  5. 然后算出加密密钥K,对于服务端公式是:K=A^b mod p,对于客户端公式是:K=B^a mod p。

上面最后一步的K就是最终的加密密钥了,看着好像不一样啊,我们对上面的公式稍微变下形,如下:

K = A^b mod p = (g^a mod p)^b mod p = g^ab mod p = (g^b mode p) = B^a mod p

可以看到,我们证明了A^b mod p 和 B^a mod p是相等的,这就是DH密钥交换的核心思想。

通过上面的过程可以看到DH密钥交换协议涉及大量的乘法运算,在效率上并不理想,所以目前主流都是使用ECDH协议,也就是ECC+DH协议。ECC又是啥?

ECC(Elliptic Curve Cryptography)椭圆曲线密码学

椭圆曲线表达式:y^2 = x^2 + ax + b, 4a^3 + 27b^2 != 0,通过公式我们可以推断出这条曲线始终是关于x轴对称的,如下图:

图2-21

椭圆曲线的加运算特性

加运算的几何意义是:R为P和Q连续曲线交点在X轴上的镜像,P+Q = R,如图:

图2-22

加运算满足交换率和结合率,比如a + b = b + a,(a+b)+c = a+(b+c)。

加运算的代数计算方法

下面通过一个实际的例子来说明:

设曲线:y^2 = x^3-7x+10

设P=(1,2), Q=(3,4), 计算出R(-3,-2)

  • P在曲线上,因为2^2=4=1^3-7*1+10

  • Q在曲线上,因为4^2=16=3^3-3*7+10=27-21+10

  • R在曲线上,因为-2……2=4=-3……3-7*(-3)+10=-27+21+10

下面是证明的详细过程

ECC核心原理

Q=K.P

  • 已知K与P,正向运算快速

  • 已知Q与P,计算K的逆向运算是非常困难的

魏尔斯特拉斯椭圆函数(Weierstrass's elliptic functions)

y^2 = x^3+ax+b

图2-23

ECDH密钥交换步骤

  1. 客户端选定大整数Ka作为私钥

  2. 基于选定曲线及曲线上的共享P点,客户端计算出Qa=Ka.P

  3. 客户端将Qa、选定曲线、共享P点传递点服务端

  4. 服务端选定大数Kb作为私钥,将计算了Qb=Kb.P,并将Qb传递给客户端

  5. 客户端生成密钥Qb.Ka=(X,Y),其中X为对称加密的密钥

  6. 服务端生成密钥Qa.Kb=(X,Y), 其中X为对称加密的密钥

Qb.Ka = Ka.(Kb.P)=Ka.Kb.P=Kb.(Ka.P)=Qa.Kb

X25519曲线

X25519曲线是椭圆曲线的变种,叫蒙哥马利曲线(Montgomery Curve)

By^2 = X^3 + Ax^2 + x,例如A=7,B=3,如下图:

图2-24

X25519

y^2 = X ^ 3 + 486662x^2 + x

p等于2^255-19,基于G=9

ordder N

2^255+0x14def9dea2f79cd65812631a5cf5d3ed

实际上,目前TLS1.2和TLS1.3都在使用了X25519曲线。

openssl 1.1.1对TLS1.3支持的加密套件

Ciphersuites 安全套件

• TLS13-AES-256-GCM-SHA384

• TLS13-CHACHA20-POLY1305-SHA256

• TLS13-AES-128-GCM-SHA256

• TLS13-AES-128-CCM-8-SHA256

• TLS13-AES-128-CCM-SHA256

测试是否支持TLS1.3

正常情况下,我们通过浏览器很难看出站点是否支持TLS1.3,但我们可以使用一些工具,下面这个网站提供了这样的功能。

https://www.ssllabs.com/ssltest/index.html

性能优化

session缓存

图2-25 session缓存

session缓存是将会话过程中用到的信息保存起来,比如加密密钥等等。

session ticket

图2-26 SessionTicket

通过session ticket可以将握手过程中的密钥信息保存起来,在下次请求的时候可以实现跳过握手,直接进行数据的传输。但是,这样其实是违背了密钥的随机性,使用时要注意,可以通过设置过期时期等手段来解决。

TLS1.3的0RTT握手

图2-27 TLS1.3的0RTT

0RTT握手只有TLS1.3才支持,但是0RTT是依赖session ticket的。

0RTT的重放攻击

图2-28 重放攻击

0RTT由于依赖session ticket,当攻击者拿到数据包了之后,他可以基于这个数据包不断调整然后发起请求,由于密钥信息始终是可以用的,他就可以无限重试,来达到破解的目的。

FREAK攻击

图2-29 FREAK攻击

FREAK攻击的原理是,攻击者截获用户的请求之后,将ClientHello里只传安全性比较低的加密套件,这样服务端就不得不使用他传过来的安全套件,当连接建立之后,攻击者就可以通过破解的密钥来解析出通信的明文信息了。

HTTPS协议握手过程

通常我们说HTTPS的握手过程,一般都是指TLS协议的握手过程,TLS协议有些复杂,TLS协议分几个阶段,或者叫几个子协议,这些子协议职责功能各不一样。一般常见的有警报协议记录协议握手协议等等。下面这张图是TLS1.2握手的大体流程。

图2-30 TLS1.2握手过程

前面我们详细讲解了对称加密和非对称加密以及DH密钥交换协议,有了这些基础之后再来看这幅图,相信是比较容易理解的。

下面是TLS1.2详细的连接过程,如图:

图2-31 TLS1.2详细握手过程

客户端会首先发一个ClientHello,里面包含了自己支持的加密套件、TLS版本号、以及随机数,这个随机数是为了最终生成密钥的时候结果更随机,使得攻击者更难猜出来。下面是一个ClientHello的抓包内容,你可以感受一下:

图2-32 ClientHello抓包

其中,Random就是随机数,Cipher Suites表示支持的加密套件,上面的例子中一共支持17种加密套件。加密套件的格式基本都是固定的,密钥交换算法+签名算法+对称加密算法+摘要算法

当服务端收到ClientHello之后,会从Cipher Suites里选择一个加密套件来生成非对称加密的公私钥,然后将ServerHello、Certificate、Server Key Exchange、Server Hello Done一块发送给客户端。我们一个一个看。

Server Hello

图2-33 服务端Server Hello抓包

可以看到服务端也返回了一个随机数,并选择了一个加密套件。

Certificate

图2-34 服务端Certificate抓包

Certificate返回的是网站的证书,这个证书就是网站主去CA机构申请的证书。

Server Key Exchange

图2-35 服务端Server Key Exchange抓包

其中,Pubkey就是我们前面讲非对称加密和DH密钥交换协议里讲的那个公钥,是用于后续客户端生成对称加密密钥用的原始数据。

Hello Done

图2-36 服务端Hello Done抓包

Hello Done其实就是告诉客户端我这边完事了,你那边该干嘛干嘛。

当客户端收到服务端的Server Hello之后,客户端也生成一个Client Key Exchange,里面也包含了一个Pubkey,回想一下DH密钥交换协议的原理,这里为止,双方生成对称加密密钥的原数据就齐了,接下来双方就可以根据各自手里的数据生成对称加密密钥了了。客户端收到ServerHello之后还做了一件事就是回给了服务端一个Change Cipher Spec,告诉服务端后面的传输都用各自生成的对称加密密钥加密之后传输了。

至此,HTTPS的握手就完成了,后面就可以通过HTTPS协议传输HTTP的数据了。

有些文章里讲的可能不太一样,上面的握手过程是目前主流的流程,如果你看到的版本不一样,那大概率是因为很多文章还是使用的传统的流程,下面是TLS传统密钥交换的过程。如下图:

图2-37 TLS1.2传统握手

可以看到传统的握手过程,和目前主流的握手过程有两个最大的区别,一个就是密钥交换,另一个是Change Cipher Spec。在主流的密钥交换过程中,服务端和客户端都会返回对方一个Change Cipher Spec,但在传统的交换过程中,只由客户端发送一个Change Cipher Spec。然后是Change Cipher Spec,目前主流的流程都是放到了数据发送阶段,相当于发送Change Cipher Spec之后立马就可以发送数据了,不用等服务端的Chnage Cipher Spec,有点类似于TCP的TCP Fast Open,传统的流程是双方都要发送Change Cipher Spec之后才可以正式进入到数据发送阶段。

上面的流程中,其实还有一个细节没有提到,就是客户端拿到服务端的证书之后如何去验证,这个上文中其实已经讲过了,如果没有印象可以回头再去看一下。实际上现在只能是用户也就是从浏览器打开网页的人去验证网站的身份,而网站没法去验证用户的身份,这种验证方式也叫单向认证。

实际上,在现实生活中也有双向验证,比如银行给你的U盾,你必须将U盾插入到电脑上才可以对银行帐户进行操作,其原理也很简单,你的U盾里面其实就是保存了一份数字证书,这个证书里面包含了你的个人信息,和银行用它的私钥生成的一个公钥,当你访问银行网站的时候就需要将数据证书发送到银行的服务端,由服务端进行验证是否合法。

TLS1.3握手过程

由于TLS1.2出现得比较早,其要保证向前兼容,很多老的加密套件已经变得不安全了。TLS1.3在1.2的基础上强化了安全,比如我们前面讲的FREAK攻击,就是因为TLS1.2需要向前兼容保留了很多老的加密套件。TLS1.3对加密套件进行了大刀阔斧的瘦身,最终对称加密只保留了AES和ChaCha20,分组模式只保留了AEAD的GCM、CCM和Poly1305,摘要算法只能使用SHA256和SHA384,密钥交换只能使用ECDHE和DHE,椭圆曲线只剩下P-256、x25519等5种曲线。

瘦身之后的加密套件如下表:

加密套件 代码
TLS_AES_128_GCM_SHA256 {0x13,0x01}
TLS_AES_256_GCM_SHA384 {0x13,0x02}
TLS_CHANCHA20_POLY1305_SHA256 {0x13,0x03}
TLS_AES_128_CCM_SHA256 {0x13,0x04}
TLS_AES_128_CCM_8_SHA256 {0x13,0x05}

在握手的过程中也作为了优化,比如客户端在发起连接的时候直接把公私钥算好,发给服务端,服务端收到之后直接就可以生成加密密钥了,如下图:

图2-38 TLS1.3握手

下面是TLS1.3详细的握手过程

图2-39 TLS1.3 详细握手过程

可以看到,和TLS1.2最大的区别就是原来客户端发送的ClientHello只携带了自己支持的加密套件,而1.3是除了把加密套件发过去,每个套件还生成了一套公私钥,直接发给服务端,服务端收到之后直接就可以生成密钥了,从而少了一个RTT。

量子通信

量子通信的核心原理是量子密钥分发(quantum key distribution)简称OKD,量子通信借助了量子力学中的一个原理,就是:任何对量子系统的测量都会对系统造成干扰。如果有第三方试图窃听,通信双方都可以察觉到。说得有点邪乎,具体怎么实现的呢,如下图:

图3-1 波粒二象性原理

图中,黄色的光波是可以通过的,蓝色光波不能通过,这就是中学物理学过的“波粒二象性原理”,也是量子通信的核心原理,通信双方在交换密钥的时候可以使用不同的光栅,通过计算数据正确的概率来判断是否被篡改过,比如正常情况下,正确率是70%,如果中间有人窃听或者篡改,那正确率就会小于70%,从而通信双方都能感知到。

BB84协议

1984年Charles Bennett与Gilles Brassard发表了BB84协议,是量子通信真正可以落地的一个协议,前几年中国发射的墨子号量子通信卫星就是基于BB84协议。

图3-2

BB84协议的核心原理是这样的,如图3-2,假设有两种不同方向的光栅,90度角的光栅,垂直方向表示0,水平方向表示1,45度角光栅,向上方向的表示0,向下的表示1,这些光栅都有一个基,或者叫base,这样通信的每一端都可以有很多的光栅,这些光栅的形状只有自己知道。发送端通过这些光栅将数据发送出去,接收端也有自己的光栅也是不同的形状,并且和发送端不一样,光栅的形状也只有接收端自己知道。当收到发送端发来的数据时,总是有一些数据可以通过自己的光栅。这样就可以得到一个通过的概率值。比如50%,假如中间有一个攻击者,他监听了数据,并将数据重新发送出去,这个时候通过的概率就是50% * 50% = 25%,这样客户端和服务端就能感知到通信被监听了。

我们来举个例子,假如Alice和Bob要建立通信,如下图:

图3-3

可以看到,Alice和Bob的光栅是不一样的,假如Alice通过自己的光栅发送数据10110011001110,到了Bob这边通过的情况就是1--100-100-1-0。

QKD密钥纠错与隐私增强

在实际通信过程中,Alice可以告诉Bob你哪些方向是对的,这样Bob就可以只取这部分数据,由于Alice也知道Bob哪些方向上对的,他们就可以取这部分数据作为密钥生成的原数据了。整个密钥协商也就完成了。如下图:

图3-4

要注意的是,上面举的例子并不是整个传输过程都是使用光栅这种方式,只是在密钥协商阶段使用上面这种方式,这是因为有了加密密钥之后整个传输过程相对来讲是安全的,一般被攻击都是出现在密钥协商阶段。所以,量子通信主要解决的密钥协商。

结束语

互联网经过几十年的发展,已经是一张巨大的网了。到目前为止应该还没有哪个机构可以准确测量这张网的大小,这张网里面有上千万程序员还在不断编织,可以预见,未来这张网还会越来越大。

当然这张网上除了养活了千千万万的程序员之外还存在有一群破坏者,这张大网成了他们的猎场,而参与互联网的人就是这里面的猎物。我们常说邪不压正,但同时还有一句话叫道高一尺,魔高一丈。互联网的建设者和破坏者是这张网里面的两个对立面,相互之间的博弈也是持续了几十年。

HTTP协议作为互联网的毛细血管,它的安全几乎关系到整个互联网的安全,为了解决安全问题,无数的计算机科学家、数学家、密码学家参与到安全规则的制定中来,他们是整个互联网的英雄,有了他们我们才能放心的参与到互联网当中来。

HTTPS协议是高精尖安全技术的集大成者,几乎所有代码实现,加密算法都是开源的,是理解安全不可多得的营养品,希望通过这篇文章可以给你一些启发,给我自己一些动力。

本文参考了HTTPS的RFC文档,极客时间陶辉老师的专栏而成,其中关于对称和非对称加密的部分大量的插图都使用了陶辉老师课件上的插图。这里要感谢陶辉老师高质量的专栏内容。

神秘邻居把我的信息卖给了诈骗团伙相关推荐

  1. 超1.1亿条个人信息泄露 每条0.4元卖给诈骗团伙

    [黑客联盟2016年10月17日讯]公民的姓名.年龄等个人信息竟成为不法分子贩卖的"商品",一条信息可卖0.4元到1元不等.广东省公安厅22日召开发布会透露,近日,全省公安机关开展 ...

  2. 大数据揭秘:个人信息泄露成为网络诈骗主因

    互联网在给人们生活带来便利的同时,线上的特殊性也让"骗子"如鱼得水,将线下骗术与技术手段相结合,不仅迷惑性.隐蔽性更强,而且骗术演变速度奇快,让普通网民难以识别.防不胜防. 羊年春 ...

  3. 斯坦福的智能马桶能凭肛纹识人,大便和尿液都把你的信息“卖”了……

    来源:大数据文摘 本文约2400字,建议阅读8分钟 没想到吧,你的菊花还能这么用! 去年10月,日本最大的建材设备集团LIXIL推出智能马桶,通过系统自动分辨大便形状和大小,能让人更好地进行身体管理, ...

  4. 隐私黑产:2亿余条个人信息卖了2000余万元

    数据猿官网 | www.datayuan.cn 今日头条丨一点资讯丨腾讯丨搜狐丨网易丨凤凰丨阿里UC大鱼丨新浪微博丨新浪看点丨百度百家丨博客中国丨趣头条丨腾讯云·云+社区 前脚买了房,立刻就接到贷款电 ...

  5. 个人信息泄露致电信诈骗猖獗 专家:治理亟须完善立法

    最近发生了几起电信诈骗导致被害人死亡的案件,引起公愤,虽然犯罪嫌疑人很快被抓获,但与这几起案件相关的个人信息泄露的问题仍值得我们持续关注.公众普遍质疑这样的问题,即犯罪嫌疑人怎么这么快就能够得到受害人 ...

  6. 个人信息遭泄露 电信诈骗网络信息管理存隐忧

    最近一段时间,多起电信诈骗案成为社会关注的焦点.由于多名即将升入大学的大学生因为电信诈骗被骗光学费而离世,引发巨大的社会舆论.这一方面反映出当前个人用户信息泄露问题已经非常严重,另一方面更凸显出掌握用 ...

  7. 一秒识破诈骗信息 360手机卫士诈骗鉴定重磅上线

    电信诈骗.网络欺诈,每位网民严防死守时刻注意避免上当,却在不知不觉间屡屡中招.究其原因,对网络诈骗.电信诈骗套路不了解,虚假号码.钓鱼链接.虚假信息肉眼真伪难辨.日前,360手机卫士上线"诈 ...

  8. 现代信用卡管理阅读笔记(一)

    这两天在看的一本书是<现代信用卡管理>,本文是这本书的读书笔记,主要是记录下信用卡审批管理.账户管理.坏账管理.催收管理以及反欺诈管理中的一些知识.由于最近也在看公司的一些培训课,是关于小 ...

  9. 我被“裸聊APP”诈骗了[病毒分析]

    概述:疫情之下,各行各业为了生存发展都在谋求转型,诈骗界也不例外.就色情类诈骗而言,最近"找小姐"诈骗.仙人跳诈骗几乎为零,P2P裸贷诈骗随着整治也告一段落,但"裸聊&q ...

  10. 手中的快递包别乱扔了!100万份个人信息被卖40亿

    Python实战社群 Java实战社群 长按识别下方二维码,按需求添加 扫码关注添加客服 进Python社群▲ 扫码关注添加客服 进Java社群▲ 文章来源丨安全圈 你听过信息泄露吗? 最近微博上的一 ...

最新文章

  1. 解题报告(一)B、(CF453D) Little Pony and Elements of Harmony(FWT经典套路 + 任意模数 k 进制FWT + 快速幂)(2)
  2. 量子计算机混战:新贵离子 vs 老派超导体
  3. js判断输入是否为正整数、浮点数等数字的函数代码
  4. 获取m,n之间的随机整数
  5. 瑞利分布概率密度函数推导_IBL推导及实现
  6. Ubuntu 安装MySQL报共享库找不到
  7. 非科班转码,上岸小公司我也很满意了
  8. Learning deep representations by mutual information estimation and maximization
  9. wordpress 企业 主题 html5,Maxx 漂亮简洁的企业 WordPress主题
  10. 人间哪知星空遥:荣耀30系列的巡天计划
  11. 【求职】小米 2018 秋招测试开发工程师笔试题
  12. UR机器人编译错误收集
  13. Portapack应用开发教程(十五) APRS接收
  14. 【论文阅读|深读】GAS:Role-Oriented Graph Auto-encoder Guided by Structural Information
  15. idea前进和撤销快捷键
  16. C# HMACSHA1 加密
  17. 钙钛矿在太阳能电池领域的研究进展
  18. 全国青少年软件编程等级考试Python一级专题练习
  19. Visualizations:一个数据结构和算法的可视化展示网站
  20. Navicat for MySQL给用户赋予角色

热门文章

  1. 直播无线领夹式麦克风
  2. DynamipsGUI 2.8(CCNP模拟器)
  3. 强大的视频格式转换工具——iSkysoft iMedia Converter Deluxe Mac
  4. 在Linux上安装和配置CSF防火墙
  5. win7 64位 安装Infragistics NetAdvantage,报Error 1606 Could Not Access Network Location %SystemDrive%/ine
  6. MSDN 离线版 支持VS2015 VS2017 VS2019 (镜像本地安装,非目录替换法)
  7. 小韦XPSP3 V10.0_Ghost精简版
  8. USB加密狗复制克隆破解软件
  9. 老毛子Padavan网段LAN修改
  10. 网络PPTP协议代理加速器的应用