欢迎大家加入QQ群一起讨论: 489873144(android格调小窝)
我的github地址:https://github.com/jeasonlzy
全文较长,主要从概览,到原理,到抓包整个流程进行全方位的解读,个人能力有限,我也是通过在网上寻找资料,结合自己的理解整理出来的,如有不当,欢迎指正。
如果你认真看完本文,以下几个问题你将会有答案:
- 什么是Https,为什么要使用Https,SSL/TLS 协议又是什么
- 什么是对称加密、非对称加密,各自的优缺点
- 什么是中间人攻击,Https的加密方案是什么,如何防止中间人攻击
- 什么是CA、证书、证书链,证书如何吊销
- 数字签名又是什么,与证书什么关系
- TLS/SSL 如何握手,以及握手传递的参数
- 什么是单向认证、双向认证,有什么区别
- 什么是自签名证书,如何认证自签名证书,自签名证书安全吗
- Https对性能的损耗有多大,如何优化
- Https如何抓包,抓包的数据如何看懂是什么意思
一、HTTPS的概念
首先为什么使用Https呢,这个问题回答前,我们需要对现在使用的http协议有了解。
http日常使用极为广泛的协议,它很优秀且方便,但还是存在一些问题,如:
- 明文通信,内容可以直接被窃听:HTTP 不会对请求和响应的内容进行加密,报文直接使用明文发送,没有经过任何安全处理。报文在服务器与客户端流转中间,会经过若干个结点,这些结点中随时都可能会有窃听行为。例如用户在百度搜索了一个关键字,比如“微办公”,攻击者想要做些什么并没有任何的限制,包括窃取用户的Session信息。
- 无法验证报文的完整性,可能被篡改:攻击者在窃听的同时还可以注入有害的代码等,乃至于修改用户传送至服务器的数据。因为通信一定会经过中间很多个结点,所以就算是报文经过了加密,也一样会被窃听到,不过是窃听到加密后的内容,而双方是无法知道这个信息是否被篡改的。
- 通信方身份不验证:可能遇到假的客户端或服务器,这个就是我们说的通信中间会经过很多节点,而随便增加一个或减少一个,通信都是可以完成,没有验证机制。
这里提到的攻击者或者中间者主要指一些网络节点,是用户数据在浏览器和服务器中间传输必须要经过的节点。比如 WIFI 热点,路由器,防火墙,反向代理,缓存服务器等。
那么https 能否解决以上问题呢,答案是可以的。
HTTPS = HTTP + 加密 + 认证 + 完整性保护(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。是在HTTP基础上加入网景公司设计的SSL层,HTTPS的安全基础是SSL,因此需要加密就需要SSL。
SSL:(Secure Socket Layer,安全套接字层),位于可靠的面向连接的网络层协议和应用层协议之间的一种协议层。
TLS:(Transport Layer Security,传输层安全协议),用于两个应用程序之间提供保密性和数据完整性。
TLS 是传输层加密协议,它的前身是 SSL3.0 协议,最早由 netscape 公司于 1995 年发布,1999 年经过 IETF 讨论和规范后,改名为 TLS。如果没有特别说明,SSL 和 TLS 说的都是同一个协议。
目前有以下几个版本:SSLv2,SSLv3,TLSv1,TLSv1.1,TLSv1.2,当前基本不再使用低于 TLSv1 的版本;
二、 TLS/SSL协议的基本概念
TLS/SSL在协议中的位置如下,属于传输层之上,应用层之下的一个中间协议。
TLS/SSL的完成加密功能的核心是密码学原理,而加密就是保护数据安全的措施。一般是利用技术手段把有效数据变成乱码(加密)传送,到达目的地后,再利用对应的技术手段还原数据(解密)。加密包含算法和密钥两个元素。算法将要加密的数据与密钥(一串数字)相结合,产生不可理解的密文。由此可见,密钥与算法同样重要。
现在的加密方法中,加密算法都是公开的,网上都有各种算法原理解析的内容。加密算法虽然是公开的,算法用到的密钥却是保密的,以此来保持加密方法的安全性。加密和解密都会用到密钥。有了密钥就可以解密了,如果密钥被攻击者获得,加密也就没有意义了。
上面的图展示了TLS/SSL协议为了解决http协议在安全性方面的不足,对数据加密使用了三类基本算法,具体介绍如下,我们先从简单的开始说:
1. 散列函数Hash,验证信息的完整性
这个大家应该经常使用,比如下载一个文件,如何保证我下载的文件就是没有没篡改的,是不是完整的,那么我们就检验一下文件的MD5值,所以该类算法常见的有* MD5、SHA1、SHA256*,该类函数特点是函数单向不可逆、对输入非常敏感、输出长度固定,针对数据的任何修改都会改变散列函数的结果,用于防止信息篡改并验证数据的完整性;
md5破解在线查询
2. 对称加密,采用协商的密钥对数据进行对称加密
对称加密的意思就是,加密数据用的密钥,跟解密数据用的密钥是一样的。常见的有AES-CBC、DES、3DES、AES-GCM等,掌握密钥才能获取信息,能够防止信息窃听,通信方式是1对1;
-
优点:
- 对称内容加密强度非常高,一般破解不了
- 加解密速度快,性能开销小,一次完全的 TLS 握手,密钥交换时的非对称解密计算量占整个握手过程的 90% 以上。而对称加密的计算量只相当于非对称加密的 0.1%,
-
缺点:
- 要求提供一条安全的通道使通信双方在首次通信时协商一个共同的密钥。直接面对面协商可能难于实施,所以双方需要借助于邮件和电话等其他相对不够安全的手段来进行协商。
- 密钥的数目难于管理。因为对于每一个合作者都需要使用不同的密钥,很难适应开放社 会中大量的信息交流。
- 对称加密算法一般不能提供信息完整性的鉴别。它无法验证发送者和接受者的身份。
- 对称密钥的管理和分发工作是一件具有潜在危险的、繁琐的过程。对称加密是基于共同保守秘密来实现的,采用对称加密技术的贸易双方必须保证采用的是相同的密钥,保证彼此密钥的交换是安全可靠的,同时还要设定防止密匍泄密和更改密钥的程序。
3. 非对称加密,实现身份认证和密钥协商,
即常见的RSA、ECDHE、DH 、DHE等算法,算法特点是,密钥成对出现,一般称为公钥(公开)和私钥(保密),公钥加密的信息只能私钥解开,私钥加密的信息只能公钥解开。因此掌握公钥的不同客户端之间不能互相解密信息,只能和掌握私钥的服务器进行加密通信,服务器可以实现1对多的通信,客户端也可以用来验证掌握私钥的服务器身份。
- RSA:算法实现简单,诞生于 1977 年,历史悠久,经过了长时间的破解测试,安全性高。其数学原理是将一个大数分解成两个质数的乘积,加密和解密用的是两个不同的密钥。即使己知明文、密文和加密密钥(公钥),想要推导出解密密钥(私钥),在计算上是不可能的。按现在的计算机技术水平,要破解目前采用的1024位RSA密钥,需要上千年的计算时间。在2010年以后,均采用了2048位的签名。RSA 是目前唯一一个既能用于密钥交换又能用于证书签名的算法。缺点就是需要比较大的素数(目前常用的是 2048 位)来保证安全强度,很消耗 CPU 运算资源。
- DH:diffie-hellman 密钥交换算法,诞生时间比较早(1977 年),但是 1999 年才公开。缺点是比较消耗 CPU 性能。
- ECDHE:使用椭圆曲线(ECC)的 DH 算法,优点是能用较小的素数(256 位)实现 RSA 相同的安全等级。缺点是算法实现复杂,用于密钥交换的历史不长,没有经过长时间的安全攻击测试。
- ECDH:不支持 PFS,安全性低,同时无法实现 false start。
- DHE:不支持 ECC。非常消耗 CPU 资源。
那么总结非对称加密的优点就是:用户可以公开其公钥,而保留私钥,就算别人知道了公钥也无法解密数据,还可以1对N通信,缺点也很明显,极度的消耗cpu的资源,就像前文说的,一次完全 TLS 握手,密钥交换时的非对称解密计算量占整个握手过程的 90% 以上。而对称加密的计算量只相当于非对称加密的 0.1%,如果应用层数据也使用非对称加解密,性能开销太大,无法承受。
三、中间人攻击和信息抵赖
我们前面讲到了TLS/SSL协议使用了三种加密算法确保了数据的完整性、有效性,那么是不是就够了呢?我们来看如下场景。
身份验证和密钥协商是TLS的基础功能,要求的前提是合法的服务器掌握着对应的私钥。但RSA算法无法确保服务器身份的合法性,因为公钥并不包含服务器的信息。
上面这句话不好理解,我们看下图:
假如我是攻击者,也就是中间人M,现在开始攻击,步骤如下:
- 客户端C和服务器S进行通信,中间节点M截获了二者的通信,也就是路由器节点,代理服务器等等,反正你不可能直接和服务器通信;
- 节点M自己计算产生一对公钥
pub_M
和私钥pri_M
; - C要对数据进行加密,那么一定需要先知道加密的密钥是什么,于是向S请求,让S把加密的公钥给C
- C向S请求公钥的过程中,M可以截获请求,于是把自己的公钥
pub_M
发给了C; - C拿到这个
pub_M
后,是无法知道这个公钥是M给的还是S给的,因为公钥中没有包含服务器的信息。 - 于是C使用公钥
pub_M
把数据加密后发出去; - M再次拦截,因为数据是用
pub_M
加密的,而解密的私钥pri_M
自己拥有,所以M解密C发出去的数据,拿到明文; - M在拿到明文后,使用S返回的公钥
pub_S
再次加密明文,发送给S; - S拿到了被自己的公钥
pub_S
加密后的密文,当然也能用自己的pri_S
解密,但是S同样无法知道这个请求是M发出的,因为请求的信息中没有包含客户端的任何信息。 - S接着对客户端C进行响应,M再次拦截,步骤与请求一样;
这样就完成了一次攻击,客户端C与服务端S通信的所有内容被中间人M全部获取,但是C和S无法感知到M的存在,双方都没有机制去判断对方的身份是否可信。此外M除了对进行窃听外,还可以进行篡改等操作,双方依然是无法感知的。这也就导致了服务器同样也可以对自己的发出的信息进行否认,不承认相关信息是自己发出,这也就是信息抵赖。
四、身份验证CA和证书
那么既然这样都无法解决通信的安全问题,怎么办呢?这时候跳出来了一个人,他就是CA机构(Certification Authority 数字证书认证机构),他是具有权威性、公正性的机构,他说,我来负责对你们的身份进行认证,具体怎么做呢,看下面:
基本的原理为,CA负责审核信息,然后对关键信息利用私钥进行”签名”,公开对应的公钥,客户端可以利用公钥验证签名。CA也可以吊销已经签发的证书,具体的流程如下:
- 服务端生成一对公私钥,服务端自己保留私钥key,利用公钥加上公司信息,服务器信息生成请求文件csr;
- 用生成的csr文件向国际CA机构提交申请,CA审核通过后,会为申请者颁发一个数字证书,一般是cer或者crt文件,并且CA会用自己的私钥对提交的信息进行签名,并将该签名附加在证书上
- CA将生成好的证书颁发给申请者,这样服务端就是一个被CA认可的可信服务器。
- 以后客户端在请求服务器的时候,服务器会直接将证书返回给客户端
- 客户端拿到这个证书后,会验证签名是否合法,那么如何验证这个签名呢,这个签名是被CA用他自己的私钥加密的,所以我们只需要用CA的公钥去解密。那么这个公钥要去哪里弄呢,实际上常用的认证机构的公钥证书都会被内置在手机、电脑、浏览器中,大概有150-200个证书被内置。位置如下:
在这个过程需要理解以下几点:
- 申请证书不需要提供私钥,确保私钥永远只能服务器掌握;
- 证书的合法性仍然依赖于非对称加密算法,证书主要是增加了服务器信息以及签名;
- 内置 CA 对应的证书称为根证书,颁发者和使用者相同,自己为自己签名,即自签名证书;
- 证书=公钥+申请者与颁发者信息+签名;
- 公钥放在数字证书中。只要证书是可信的,公钥就是可信的。
那么一个真实的证书是什么样呢?如下所示,打开chrome浏览器,输入一个https的站点,比如我们公司微办公的首页https://www.weibangong.com,或者百度的首页都可以,这里我们用我们公司的示例,点击浏览器上的这把小绿锁,
然后点击这个查看证书的按钮
我们会看到如下结果
这个里面包含了公司和服务器还有加密公钥,加密算法,数字签名等很多重要信息。
五、证书链
证书链:服务器证书、中间证书与根证书在一起组合成一条合法的证书链,证书链的验证是自下而上的信任传递的过程,原理图如下:
我们公司的证书结构如下:
即CA根证书和服务器证书中间增加一级证书机构,即中间证书,证书的产生和验证原理不变,只是增加一层验证,只要最后能够被任何信任的CA根证书验证合法即可。
- 服务器证书 server.pem 的签发者为中间证书机构 inter,inter 根据证书 inter.pem 验证 server.pem 确实为自己签发的有效证书;
- 中间证书 inter.pem 的签发 CA 为 root,root 根据证书 root.pem 验证 inter.pem 为自己签发的合法证书;
- 客户端内置信任 CA 的 root.pem 证书,因此服务器证书 server.pem 的被信任。
使用证书链具有以下好处:
- 减少根证书结构的管理工作量,可以更高效的进行证书的审核与签发;
- 根证书一般内置在客户端中,私钥一般离线存储,一旦私钥泄露,则吊销过程非常困难,无法及时补救;
- 中间证书结构的私钥泄露,则可以快速在线吊销,并重新为用户签发新的证书;
- 证书链四级以内一般不会对 HTTPS 的性能造成明显影响。
同时证书链还有以下特点:
- 同一本服务器证书可能存在多条合法的证书链。因为证书的生成和验证基础是公钥和私钥对,如果采用相同的公钥和私钥生成不同的中间证书,针对被签发者而言,该签发机构都是合法的 CA,不同的是中间证书的签发机构不同;
- 不同证书链的层级不一定相同,可能二级、三级或四级证书链。中间证书的签发机构可能是根证书机构也可能是另一个中间证书机构,所以证书链层级不一定相同。
六、证书吊销
CA 机构能够签发证书,同样也存在机制宣布以往签发的证书无效。证书使用者不合法,CA 需要废弃该证书;或者私钥丢失,使用者申请让证书无效。主要存在两类机制:CRL 与 OCSP。
CRL
Certificate Revocation List, 证书吊销列表,是一个单独的文件。该文件包含了 CA 已经吊销的证书序列号(唯一)与吊销日期,同时该文件包含生效日期并通知下次更新该文件的时间,当然该文件必然包含 CA 私钥的签名以验证文件的合法性。
对于一个证书的实际字段如下:
在证书中一般会包含一个 URL 地址 CRL Distribution Point,通知使用者去哪里下载对应的 CRL 以校验证书是否吊销。该吊销方式的优点是不需要频繁更新,但是不能及时吊销证书,因为 CRL 更新时间一般是几天,这期间可能已经造成了极大损失。
OCSP
Online Certificate Status Protocol, 证书状态在线查询协议,一个实时查询证书是否吊销的方式。请求者发送证书的信息并请求查询,服务器返回正常、吊销或未知中的任何一个状态。
对于一个证书的实际字段如下:
证书中一般也会包含一个 OCSP 的 URL 地址,要求查询服务器具有良好的性能。部分 CA 或大部分的自签 CA (根证书)都是未提供 CRL 或 OCSP 地址的,对于吊销证书会是一件非常麻烦的事情。
七、TLS/SSL握手过程
好讲了这么多,终于到了这篇文章的最核心的地方,在讲握手之前,我们把前面关于握手有关的东西重新整理下,我们能得到如下结论,这几个结论非常重要,非常重要,非常重要:
- TLS/SSL使用了三种密码学的算法保证数据的有效性、完整性、安全性。
- 鉴于非对称加密算法极度消耗cpu的特点,最后的方案是,仅仅使用非对称加密传输协商密钥,真正的数据使用协商密钥进行对称加密,这样既保证了安全性,也保证了效率。
- 但是这样由于没有信息的验证机制,所以这个任务交给了CA机构,于是TLS/SSL协议就诞生了。
好,有了上面的这个结论,我们再来详细的看握手过程,看看每次握手究竟传递了什么参数,服务端与客户端是如何完成通信的,那么为了能够看到传递的数据,我们需要对请求进行抓包,我们使用的工具是wireshake
,使用他的原因是,TLS/SSL协议位于应用层之下,普通的fiddler
和charles
这两个抓包工具只能抓应用层的数据,抓不到底层的数据,关于这个wireshake
工具的下载地址,我这就不提供了,他是一个跨平台的免费工具,mac和windows都有。
使用简单说一句,打开wireshake
,选择好网卡,在过滤条件中输入ssl
,然后打开浏览器,进入百度主页,就完成了,我们可以在wireshake
的过滤信息中找到符合如下,主要是右边的info一栏,一定要看是这个顺序的,一点都不能错,否则就不好分析了。
所有的准备工作完毕,我们先上一张整个握手过程的大图,如下,这个图我也是来来回回画了很久,很详细,如果图片看不清可以点击这里查看大图。不要被这个图吓着了,如果你不愿意自己看,那么我们接下来一点点帮你分析,这个图就是让你有个整体印象。
1. Client Hello
前面我们抓包看到了,第一步是Client Hello,也就是客户端向服务端传递一些客户端的信息,但是这个是明文传输,那么我们点开Client Hello 看看里面的数据:
- 支持的最高TLS协议版本号version,比如TLSv1.2(0x0303)。
- 一个客户端生成的随机数
Random
,这个随机数一方面需要在客户端保存,另一方面需要传送给服务端,客户端的随机数需要跟服务端产生的随机数结合起来产生后面要讲到的Master Secret。 - 支持的加密套件cipher suite列表,客户端(如不同浏览器或手机)对一些加解密算法的支持程度不一样,但是在TLS协议传输过程中必须使用同一套加解密算法才能保证数据能够正常的加解密。在TLS 握手阶段,客户端首先要告知服务端,自己支持哪些加密算法,所以客户端需要将本地支持的加密套件(Cipher Suite)的列表传送给服务端。详细看图,客户端共计支持19种加密套件:
- 支持的压缩方法compression methods 列表,用于后续的信息压缩传输,当前我们这个没有压缩。
- session ID 如果存在就会携带。
注意:客户端发送的信息之中不包括服务器的域名。也就是说,理论上服务器只能包含一个网站,否则会分不清应该向客户端提供哪一个网站的数字证书。这就是为什么通常一台服务器只能有一张数字证书的原因。对于虚拟主机的用户来说,这当然很不方便。2006年,TLS协议加入了一个Server Name Indication扩展,允许客户端向服务器提供它所请求的域名,如下:
补充:我们第一次看这种数据就先介绍一下这个结构,我们看到了下面显示很多数据的框框,里面分了五层,这五层分别是:
序号 | 层 | 描述 |
---|---|---|
1 | Frame | 物理层 |
2 | Ethernet | 数据链路层 |
3 | Internet Protocol | IP网络层 |
4 | Transmission Control Protocol | TCP传输层 |
5 | Secure Sockets Layer | SSL安全套接层 |
如果你了解http协议,那么你一定知道这就是经典的五层因特网协议栈,准确来说,SSL不属于应用层,在SSL之上还有一层那就是HTTP应用层协议。
知道这个后,我们再看上图里面有两列IP地址,Source和Destination,分别表示客户端IP和服务端IP,很明显,我的客户端公网IP就是192.168.1.109
,而61.135.169.121
,我们可以直接ping一下百度的首页就知道,这个是百度服务器的IP,但是百度是集群服务器,有很多负载节点,所以不同地方ping的结果可能最后一位ip略有差异,这个不影响。
2. Server Hello
从Server Hello到Server Done,有些服务端的实现是每条单独发送,有服务端实现是合并到一起发送。Sever Hello和Server Done都是只有头没有内容的数据,我们的例子中就是每条单独发,我们看Info中的Server Hello 和 Certificate 的IP,都是从服务端到客户端的响应。
服务端在接收到客户端的Client Hello之后,先保存下客户端发送的随机数,然后向客户端返回协商的信息结果(server_hello),也是明文传输,详细信息如下:
1. 确认使用的加密通信协议版本version,比如TLS 1.2版本。
2. 跟客户端一样,服务端也需要产生一个随机数发送给客户端。客户端和服务端都需要使用这两个随机数来产生Master Secret。
3. 确认使用的加密套件Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
4. 选择的压缩算法Compression Method: null (0)
此外,服务端需要将自己的证书发送给客户端。这个证书是对于服务端的一种认证。例如,客户端收到了一个来自于称自己是www.alipay.com
的数据,但是如何证明对方是合法的alipay支付宝呢?这就是证书的作用,支付宝的证书可以证明它是alipay,而不是 财付通。证书是需要申请,并由专门的数字证书认证机构(CA)通过非常严格的审核之后颁发的电子证书。颁发证书的同时会产生一个私钥和公钥。私钥由服务端 自己保存,不可泄漏。公钥则是附带在证书的信息中,可以公开的。证书本身也附带一个证书电子签名,这个签名用来验证证书的完整性和真实性,可以防止证书被串改。另外,证书还有个有效期。
服务端继续返回以下数据:
5. 服务器证书链server_certificates,我们看到了总大小是2890字节。
7. 在服务端向客户端发送的证书中没有提供足够的信息的时候,还可以向客户端发送一个Server Key Exchange。 这是个非常重要的保密数据,以后服务端还需要对客户端进行验证,以保证数据传送给了安全的合法的客户端。
8. 服务端可以向客户端发出Cerficate Request
消息,要求客户端发送证书对客户端的合法性进行验证。比如,金融机构往往只允许认证客户连入自己的网络,就会向正式客户提供USB密钥,里面就包含了一张客户端证书。(这一步可省略,这一步就是要求下次请求的时候,客户端需要带上自己的证书,服务器需要验证客户端的合法性,也就是双向认证,我只是请求百度,只用到了单向认证)
9. 最后服务端会发送一个Server Hello Done
消息给客户端,表示Server Hello消息结束了。
补充
关于
Cipher
最后返回的的这一长串名字是什么含义呢?其实,每种Cipher的名字里包含了四部分信息,分别是:
- 密钥交换算法 KeyExchange(密钥协商),用于决定客户端与服务器之间在握手的过程中如何认证,用到的算法包括RSA,Diffie-Hellman,ECDH,PSK等
- 对称加密算法 Enc (信息加密),用于加密消息流,该名称后通常会带有两个数字,分别表示密钥的长度和初始向量的长度,比如DES 56/56, RC2 56/128, RC4 128/128, AES 128/128, AES 256/256
- 信息摘要 Mac(完整性校验),用于创建报文摘要,确保消息的完整性(没有被篡改),算法包括MD5,SHA等。
- PRF(伪随机数函数),用于生成“master secret”。
完全搞懂上面的内容似乎还需要一本书的介绍,不过大致了解一下,有助于理解Cipher的名字,比如前面服务器发回给客户端的Cipher,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
,从其名字可知,它是:
1. 基于TLS协议的;
2. 使用ECDHE、RSA作为密钥交换算法;
3. 加密算法是AES-GCM(密钥和初始向量的长度都是128),密钥长度只是选择了128,而不是256,背后的担忧主要来自于性能——加密与解密是CPU密集型操作,过强的Cipher会带来性能问题。
4. MAC算法(这里就是哈希算法)是SHA256。
熟悉了Cipher名字背后的含义后,让我们看看像IIS这样的Web服务器如何选择一个密钥算法呢?假如浏览器发来的密钥算法套件为[C1, C2, C3],而Windows Server支持的套件为[C4, C2, C1, C3]时,C1和C2都是同时被双方支持的算法,IIS是优先返回C1,还是C2呢?答案是C2。IIS会遍历服务器的密钥算法套件,取出第一个C4,发现浏览器并不支持;接下来取第二个C2,这个被浏览器支持!于是,IIS选择了C2算法,并将它包含在一个“ServerHello”握手协议中,发回给客户端。
3. Client Key Exchange
这一步是第一次认证,即客户端认证服务端证书,但是不幸的是,很多开发者为了简单方便,在android代码中,将相关的逻辑进行了空实现,导致无论服务端的证书是什么(可能服务端被拦截或代理),客户端都选择相信,这将为以后的安全通信埋下巨大的隐患。
不论什么平台,设备的操作系统中都会内置100多个全球公认的CA证书,说具体点就是设备中存储了这些知名CA的公钥。当客户端接收到服务器的数字证书的时候,会进行如下验证:
1. 证书链的可信性 trusted certificate path,客户端会用设备中内置的CA的公钥尝试解密证书中的数字签名,如果所有内置的CA的公钥都无法解密该数字签名,说明该数字证书不是由一个全球知名的CA签发的,这样客户端就无法信任该服务器的数字证书。
2. 如果有一个CA的公钥能够成功解密该数字签名,说明该数字证书就是由该CA的私钥签发的,因为被CA私钥加密的密文只能被与其成对的CA公钥解密。(这里就能证明服务端是可信的,并没有被代理,即数据的安全性)
3. 计算数字证书的hash摘要,并与解密后得到的证书hash摘要对比,如果一致表示该证书并没有被篡改,否者,证书被中间人有过修改。(这里就保证了内容的完整性)
4. 域名 domain,核查证书域名是否与当前的访问域名匹配;
5. 有效期 expiry date,证书是否在有效时间范围;
6. 证书是否吊销 revocation,有两类方式离线 CRL 与在线 OCSP,不同的客户端行为会不同;
如果验证不过,就会向访问者显示一个警告,由其选择是否还要继续通信。
如果验证通过,客户端就会从证书中取出服务器的公钥。向服务器发送下面信息。
- 在此之前的所有TLS握手信息都是明文传送的。但是本次在收到服务端的证书等信息之后,客户端会使用之前协商好的加密套件的算法,产生一个48个字节的随机数Key,这个Key叫
Pre-master
, 然后用从证书中取出来的服务器的公钥和之前协商好的加密算法加密这个Pre-master
,结合之前的两个随机数生成session secret
,注意这个加密是非对称加密,除了服务端用自己的私钥能解开,谁都解不开。 - 发送一个编码改变通知
change_cipher_spec
,change_cipher_spec
是一个独立的协议,体现在数据包中就是一个字节的数据,用于告知服务端,客户端已经切换到之前协商好的加密套件的状态,准备使用之前协商好的加密套件加密数据并传输了。 - 在
change_cipher_spec
传输完毕之后,客户端发送握手结束通知,encrypted_handshake_message
,他是结合之前所有通信参数的 hash 值与其它相关信息生成一段数据,采用协商密钥session secret
进行加密,然后发送给服务器用于数据与握手验证; - 如果服务端需要对客户端进行验证,也就是在
Server Hello
中返回了Cerficate Request
消息,那么此时,客户端还需要额外向服务端发送客户端的证书,让服务端来验证客户端的合法性(双向认证)。我们本例中没有这个要求,所以并没有发送客户端证书。
4. Server Finish
服务端在接收到客户端传过来的Pre-master
加密数据之后
1. 使用私钥对这段加密数据进行解密,并对数据进行验证,同时也会使用跟客户端同样的方式结合两个随机数生成session secret
,一切准备好之后,会给客户端发送一个change_cipher_spec
,告知客户端已经切换到协商过的加密套件状态,准备使用加密套件和session secret
加密数据了。
2. 服务端也会使用session secret
加密后一段Finish消息发送encrypted_handshake_message
给客户端,以验证之前通过握手建立起来的加解密通道是否成功。
3. 如果服务端需要验证客户端身份,那么首先验证客户端证书,验证方法与步骤3基本一致。
4. 如果验证失败,服务端会发送alter message
给客户端, 用于指明在握手或通信过程中的状态改变或错误信息,一般告警信息触发条件是连接关闭,收到不合法的信息,信息解密失败,用户取消操作等,收到告警信息之后,通信会被断开或者由接收方决定是否断开连接。
最后结果如下图:
5. 验证结果,发送数据
客户端最后会收到服务器发送的encrypted_handshake_message
,用来验证服务器发送的数据和密钥,如果验证通过则握手完成,到此就说明客户端和服务端的两次握手通信都能对Finish信息进行正常加解密且消息正确的被验证,双方握手通道已经安全建立成功,接下来,就可以使用上面产生的session secret
对数据进行加密传输了,如下所示:
到此我们就对整个SSL/TLS的握手流程进行了一次详细的讲解。相信在经过自己的学习和文章的阅读后,这些都不是问题。
不同的加密算法握手的过程略有不同,
基于RSA算法的握手精简如下:
基于用Diffie–Hellman算法交换premaster secret 的流程
八、常用证书格式
我们再使用证书的时候,会遇见很多扩展名的证书,那么每种扩展名是什么意思,能不能相互替代使用,解释如下:
X.509 是一个标准,也是一个数字文档,这个文档根据RFC 5280来编码并签发,一份X.509证书是一些标准字段的集合,这些字段包含有关用户或设备及其相应公钥的信息。
编码 (也用于扩展名)
- .DER - 扩展名DER用于二进制DER编码的证书,不可读。这些证书也可以用CER或者CRT作为扩展名。 Java和Windows服务器偏向于使用这种编码格式,比较合适的说法是“我有一个DER编码的证书”,而不是“我有一个DER证书”。
- .PEM - 扩展名PEM用于ASCII(Base64)编码的各种X.509 v3 证书。以“—–BEGIN…”开头, “—–END…”结尾,内容是BASE64编码,Apache和Linux服务器偏向于使用这种编码格式。
常用的扩展名
- .KEY - 通常用来存放一个公钥或者私钥,并非X.509证书,编码可能是PEM,也可能是DER.
- .CSR - 是Certificate Signing Request的缩写,即证书签名请求,这不是证书,是生成证书时要把这个提交给权威的证书颁发机构。其核心内容是一个公钥(当然还附带了一些别的信息),在生成这个申请的时候,同时也会生成一个私钥,私钥要自己保管好.当权威证书颁发机构颁发的证书过期的时候,你还可以用同样的csr来申请新的证书,key保持不变.
- .CRT - certificate的缩写,其实还是证书的意思,常见于Linux系统,有可能是PEM或者DER编码,大多数应该是PEM编码.
- .CER - certificate的缩写,其实还是证书的意思,常见于Windows系统,有可能是PEM或者DER编码,大多数应该是DER编码.
注意:CRT文件和CER文件只有在使用相同编码的时候才可以安全地相互替代。
- .PFX/PKCS12 - predecessor of PKCS#12,包含了证书和私钥,对Linux服务器来说,一般来说CRT和KEY是分开存放在不同文件中的,但Windows的IIS则将它们存在一个PFX文件中,并通过提取密码来保护。
- .JKS/JCEKS - Java密钥库(KeyStore)的两种比较常见类型,包含了证书和私钥,利用Java的“keytool”的工具,可以将PFX转为JKS,当然了,keytool也能直接生成JKS,JCEKS在安全级别上要比JKS强,使用的Provider是JCEKS(推荐),使用使用TripleDES 保护KeyStore中的私钥;
- .BKS – Bouncy Castle Provider,包含了证书和私钥, android系统支持的类型,它使用的也是TripleDES来保护密钥库中的私钥,它能够防止证书库被不小心修改(Keystore的keyentry改掉1个bit都会产生错误),BKS能够跟JKS互操作。
注意:通过工具 BKS、JKS、PFX 三种格式的证书均可以相互转换
OpenSSL简单地说,OpenSSL是SSL的一个实现,SSL只是一种规范.理论上来说,SSL这种规范是安全的,目前的技术水平很难破解,但SSL的实现就可能有些漏洞,如著名的“心脏出血”。OpenSSL还提供了一大堆强大的工具软件,强大到90%我们都用不到.
证书编码的转换
PEM转为DER openssl x509 -in cert.crt -outform der -out cert.der
DER转为PEM openssl x509 -in cert.crt -inform der -outform pem -out cert.pem
(提示:要转换KEY文件也类似,只不过把x509换成rsa,要转CSR的话,把x509换成req…)
九、部署自签名SSL证书为什么不安全
证书的来源有三种,一种是CA认证的机构颁发,这种当然最安全,第二种是像12306这样的使用其他机构颁发的未被CA认可的证书,第三种是我们开发者自己给自己颁发证书。那么他们都具有以下特点:
- 自签证书最容易被假冒和伪造,而被欺诈网站所利用
- 自签证书最容易受到SSL中间人攻击
- 以上这两点都是由于自签证书不受浏览器信任,而网站告诉用户要信任而造成!所以,作为用户,千万不要继续浏览浏览器有类型如下警告的网站
- 自签证书支持不安全的SSL通信重新协商机制
- 自签证书支持非常不安全的SSL V2.0协议
- 自签证书没有可访问的吊销列表
- 自签证书使用不安全的1024位非对称密钥对,微软已经要求所有受信任的根证书颁发机构必须于2010年12月31日之前升级其不安全的1024位根证书到2048位和停止颁发不安全的1024位用户证书,12 月 31 日之后会把不安全都所有 1024 位根证书从 Windows 受信任的根证书颁发机构列表中删除!
- 自签证书证书有效期太长,短则5年,长则20年、30年的都有,并且还都是使用不安全1024位加密算法。
SRCA,12306证书,中铁数字证书认证中心(Sinorail Certification Authority,简称“SRCA”)成立于2003年,主要提供电子认证服务、电子认证产品及一体化的电子认证解决方案,官网点击这里中铁数字证书认证中心
以下是12306证书的完整内容,我们发现与上面的每一项都很完美的吻合了!!!
为何所有Windows受信任的根证书有效期都是20年或30年?
因为:
一是根证书密钥生成后是离线锁保险柜的,并不像用户证书一样一直挂在网上;
二是根证书采用更高的密钥长度和更安全的专用硬件加密模块。
Charles为什么能抓到Https的数据包?为什么测试的时候会出现微办公的证书是不可信任的?
因为Charles作为中间人,代理了客户端与服务端的通信,并且在客户端安装了中间人的证书,使得中间人的证书变成了可信证书。
代码分析
证书锁定尽管带了较高的安全性,但是这种安全性的提高却牺牲了灵活性。一旦当证书发生变化时,我们的客户端也必须随之升级,除此之外,我们的服务端不得不为了兼容以前的客户端而做出一些妥协或者说直接停用以前的客户端,这对开发者和用户来说并不是那么的友好。但实际上,极少情况下我们才会变动证书。因此,如果产品安全性要求比较高还是启动证书锁定吧。
看起来好像解决了我们的问题,实则带来更大的危害。此时,虽然能建立HTTPS连接,但是无形之中间人攻击打开了一道门。此时,黑客完全可以拦截到我们的HTTPS请求,然后用伪造的证书冒充真正服务端的数字证书,由于客户端不对证书做验证(也就没法判断服务端到底是正常的还是伪造的),这样客户端就会和黑客的服务器建立连接。这就相当于你以为你对的对面是个美女,却没有想到已经被掉包了,想想“狸猫换太子”就明白了。
十、HTTPS性能损耗
前文讨论了HTTPS原理与优势:身份验证、信息加密与完整性校验等,且未对TCP和HTTP协议做任何修改。但通过增加新协议以实现更安全的通信必然需要付出代价,HTTPS协议的性能损耗主要体现如下:
-
增加延时
分析前面的握手过程,一次完整的握手至少需要两端依次来回两次通信,至少增加延时2*RTT(Round-Trip Time,往返时间),利用会话缓存从而复用连接,延时也至少1* RTT。
-
消耗较多的CPU资源
除数据传输之外,HTTPS通信主要包括对对称加解密、非对称加解密(服务器主要采用私钥解密数据);压测 TS8 机型的单核 CPU:对称加密算法AES-CBC-256 吞吐量 600Mbps,非对称 RSA 私钥解密200次/s。不考虑其它软件层面的开销,10G 网卡为对称加密需要消耗 CPU 约17核,24核CPU最多接入 HTTPS 连接 4800;
静态节点当前10G 网卡的 TS8 机型的 HTTP 单机接入能力约为10w/s,如果将所有的HTTP连接变为HTTPS连接,则明显RSA的解密最先成为瓶颈。因此,RSA的解密能力是当前困扰HTTPS接入的主要难题。
实际上对于https:
- 证书费用以及更新维护。大家觉得申请证书很麻烦,证书也很贵,可是证书其实一点都不贵,便宜的一年几十块钱,最多也就几百。而且现在也有了免费的证书机构,比如著名的 mozilla 发起的免费证书项目:let’s encrypt(https://letsencrypt.org/)就支持免费证书安装和自动更新。
- HTTPS 降低用户访问速度。HTTPS 对速度会有一定程度的降低,但是只要经过合理优化和部署,HTTPS 对速度的影响完全可以接受。在很多场景下,HTTPS 速度完全不逊于 HTTP,如果使用 SPDY,HTTPS 的速度甚至还要比 HTTP 快。大家现在使用百度 HTTPS 安全搜索,有感觉到慢吗?
十一、HTTPS接入优化
-
CDN接入
HTTPS 增加的延时主要是传输延时 RTT,RTT 的特点是节点越近延时越小,CDN 天然离用户最近,因此选择使用 CDN 作为 HTTPS 接入的入口,将能够极大减少接入延时。CDN 节点通过和业务服务器维持长连接、会话复用和链路质量优化等可控方法,极大减少 HTTPS 带来的延时。
-
会话缓存
虽然前文提到 HTTPS 即使采用会话缓存也要至少1*RTT的延时,但是至少延时已经减少为原来的一半,明显的延时优化;同时,基于会话缓存建立的 HTTPS 连接不需要服务器使用RSA私钥解密获取 Pre-master 信息,可以省去CPU 的消耗。如果业务访问连接集中,缓存命中率高,则HTTPS的接入能力讲明显提升。当前TRP平台的缓存命中率高峰时期大于30%,10k/s的接入资源实际可以承载13k/的接入,收效非常可观。
-
硬件加速
为接入服务器安装专用的SSL硬件加速卡,作用类似 GPU,释放 CPU,能够具有更高的 HTTPS 接入能力且不影响业务程序的。测试某硬件加速卡单卡可以提供35k的解密能力,相当于175核 CPU,至少相当于7台24核的服务器,考虑到接入服务器其它程序的开销,一张硬件卡可以实现接近10台服务器的接入能力。
-
远程解密
本地接入消耗过多的 CPU 资源,浪费了网卡和硬盘等资源,考虑将最消耗 CPU 资源的RSA解密计算任务转移到其它服务器,如此则可以充分发挥服务器的接入能力,充分利用带宽与网卡资源。远程解密服务器可以选择 CPU 负载较低的机器充当,实现机器资源复用,也可以是专门优化的高计算性能的服务器。当前也是 CDN 用于大规模HTTPS接入的解决方案之一。
-
SPDY/HTTP2
前面的方法分别从减少传输延时和单机负载的方法提高 HTTPS 接入性能,但是方法都基于不改变 HTTP 协议的基础上提出的优化方法,SPDY/HTTP2 利用 TLS/SSL 带来的优势,通过修改协议的方法来提升 HTTPS 的性能,提高下载速度等。
-
如果需要进一步减小证书大小,可以选择 ECC(Elliptic Curve Cryptography,椭圆曲线密码学)证书。
256 位的 ECC Key 等同于 3072 位的 RSA Key,在确保安全性的同时,体积大幅减小。ECC 证书这么好,为什么没有普及呢?最主要的原因是它的支持情况并不好。例如 Windows XP 不支持,导致使用 ECC 证书的网站在 Windows XP 上只有 Firefox 能访问(Firefox 证书那一套完全自己实现,不依赖操作系统)。另外,Android 平台也只有 Android 4+ 才支持 ECC 证书。所以,确定使用 ECC 证书前需要明确用户系统分布情况。
感谢以下作者:
沃通(Wosign)关于数字证书的技术文档
TLS协议官方技术文档规范
SSL Server Test
大型网站的 HTTPS 实践(1):HTTPS 协议和原理
SSL/TLS 握手优化详解
HTTPS 理论详解与实践