证书具体认证过程
证书认证包含两种情况,一种是客户端认证CA证书的流程,另一种是CA证书自证流程。
客户端认证CA证书的流程这里直接放一张小林做的图,非常直观的展示了CA如何配合信息加密完成整个HTTPS加密传输。个人为了方便记忆,抽象的步骤如下:
1.服务器注册公钥到CA。
2. CA私钥加密对于服务器公钥数字签名颁发数字证书。
3. 客户端收到数字证书,使用CA公钥(浏览器内置)解密。然后使用数字签名验证是否存在篡改。
4.通过数字证书取到服务器公钥,使用服务器公钥进行非对称加密。
然后是服务器自证过程,前面提到CA 证书是多层嵌套的自认证体现,为了保证CA证书的安全,根证书是CA认证的起点也是最核心的一环,以B站的证书为例,整个认证的体系如下:
操作系统或者浏览器认证顺序:内置证书 -> GlobalSign Root CA -> GlobalSign RSA OV SSL CA 2018 -> *.blibli.com
为什么非对称加密之后,还需要使用摘要算法计算出一个哈希值?
其实非对称加密足以保证安全了,加上CA证书基本可以万无一失,而使用摘要算法计算哈希值,实际上是考虑导效率问题,因为内容长度的匹配比较耗费性能,而哈希可以是固定长度的唯一值,哈希值匹配的效率要高出很多。
此外非对称加密可以加密的消息体长度有上限(public key length in bits / 8 -
11),否则会报错,所以必须先hash保证定长结果。
CA证书的格式以及标准
CA证书当然并不是直接给服务器私钥上套个签名就完事了,CA的证书格式有着极其严格的规范和要求,下面是CA证书主要包含的信息:
• 对象的名称(人、服务器、组织等);
• 过期时间;
• 证书发布者(由谁为证书担保);
• 来自证书发布者的数字签名。
虽然CA证书在刚面世的时候没有严格的全球规范标准,但是随着后续的发展目前TLS1.2被公认的证书格式是X509,
X.509 v3证书
X.509证书字段包含下面的内容:
我们可以通过具备HTTPS安全连接的网站,通过F12的方式查看证书,比如B站的证书信息如下:
证书的弱点
世界上没有绝对安全的事情,CA证书也不例外。CA证书的弱点在于自身的可靠性,比如给不受信任网站颁发受信任的证书,或者给CA证书本身被伪造,那么所有的防护都是一层纸, 所有信任链也就不存在了。
这些事情都是过去真实发生过的,感兴趣可以上网查找相关资料。比如很多年前MCS集团用CNNIC签发的中级证书,发行了多个冒充成Google的假证书。于是在2015年4月份,chrome、firefox都宣布不再信任CNNIC的证书,这件事情的影响十分恶劣,后续证书已经被CNNIC整顿并且被替换为合法的网站 https://xfcnnic.net.cn/。
那么CA机构是如何解决这签错网站和本身受到污染这两个问题的?
“签错”网站:利用CRL(证书吊销列表,Certificate revocation list)和 OCSP(在线证书状态协议,Online Certificate Status Protocol),及时废止有问题的证书。 CA本身被污染:所有CA全部停止工作,浏览器把被攻克CA拉入黑名单。CA本身被入侵的可能性很低。
传输过程中CA证书被篡改或者被替换,如何进行加密传输认证?
被替换和被篡改CA证书是经常被提到的两个问题,我们来一一解答:
篡改证书
假设证书在传输过程被黑客篡改,黑客是没有CA的公钥的,,因为CA公钥一般再客户端的浏览器内置,自然无法破解签名,如果把数字签名改掉,浏览器收到请求通过验签手段对比解密之后的签名,发现原文不一致,也就自然发现了问题。
证书替换
证书替换还要分为两种情况,一种是自己伪造的证书,另一种是真的骗过CA搞了一份真的证书。
伪造证书这个事情,黑客能干,其实用户自己也能随时干。但是毫无疑问在浏览器以及操作系统,自证的证书的是不受到认可,所以通常情况下客户端收到这些伪造证书都会立马判断出证书被人篡改过的事实。
那如果黑客煞费苦心,真的用合法的另一个网站拿到一份CA认可的证书,直接把证书替换了怎么办?
这时候客户端收到的证书确实是真的证书,也确实会拿到错误的公钥,但是不要忘了数字证书还有被颁发者的其他信息,比如域名是造不了假的,比对一下就出现问题了。
这里可能又会问,CA自己“黑吃黑”,本身被污染了怎么办?不能怎么办,这时候浏览器会把CA拉黑,CA所有的服务也会停止。在国内这么干是找死,而在国外…你得有本拉登的逃命实力。
CA证书被黑客入侵本身就是互联网地震,这种时候坐着吃瓜就好了、
证书内容
在RFC的TLS1.2的原文当中,有这么一句话:
The certificate type MUST be X.509v3, unless explicitly negotiated
这个X.509 v3 证书是啥?X509V3 是用于TLS1.2 加密的公认标准,它提供了一种标准的方式, 将证书信息规范至一些可解析字段中。虽然有的证书机构会有个别字段不一样,但是整体上还是使用X509V3格式。
这里引用一段维基百科的介绍:
X.509 - 维基百科,自由的百科全书 (wikipedia.org)
X.509是密码学里公钥证书的格式标准。X.509证书已应用在包括TLS/SSL在内的众多网络协议里,同时它也用在很多非在线应用场景里,比如电子签名服务。X.509证书里含有公钥、身份信息(比如网络主机名,组织的名称或个体名称等)和签名信息(可以是证书签发机构CA的签名,也可以是自签名)
HTTPS的主要改进
关于HTTPS的改进我们再次简单回顾之前的内容:
编解码的过程时在 SSL层完成的,HTTP层不需要做出过多的改变,就可以完美兼容HTTPS。 传输由原来的直接通过HTTP传输给TCP,到建立安全连接之后,从HTTP先传输到SSL层进行编码,然后传输到TCP层。 使用双重加密:对称加密算法、非对称加密算法以及通过数字证书保证,防止中间人攻击。 摘要算法:使用SHA-256等长密钥的加密方式,对于数据的完整性保护,一旦被篡改,数据无法通过校验。
HTTPS 简单来说就是在不改动TCP/IP模型的情况下,在应用层和安全层中间加入了一层安全层。
下面时针对HTTP和HTTPS的传输过程对比图:
下面我们深入到HTTPS 1.2 的细节,了解TLS1.2的建立过程。
RSA和ECDHE算法区别
现代互联网都是使用ECDHE进行密钥交换算法,这里补充和RSA交换算法的两个关键差别点。
第一个,因为用到了密钥交换算法,所以传输过程中ECDHE会多出Server Key Exchange这个步骤。
第二个,因为使用了 ECDHE,客户端可以不用等到服务器发回“Finished”确认握手完毕,立即就发出 HTTP 报文,省去了一个消息往返的时间浪费。这个叫“TLS False Start”,意思就是“抢跑”,和“TCP Fast Open”有点像,都是不等连接完全建立就提前发应用数据,提高传输的效率。
TCP Fast Open 是加速打开两个端点之间连续 TCP 连接的扩展。它通过使用 TFO cookie(一个 TCP 选项)工作,TFO cookies是存储在客户端上的,并在与服务器初始连接时设置的加密 cookie。换句话说,TFO 是 TCP 中的一种可选机制,它可以让过去创建完整 TCP 连接的端点取消握手步骤的往返,并立即发送数据。主要提高了接续通信的速度,主要是针对首字节时间高延迟网络特别有益。
HTTPS 1.2 建立连接
HTTPS的核心是TLS协议,下面就结合TLS协议了解一下协议的组成了。
TLS1.2 协议组成
我们从 TLS1.2 协议组成说起:他的协议号是 RFC5246。网址为: https://www.ietf.org/rfc/rfc5246.txt
Four protocols that use the record protocol are described in this document: the handshake protocol, the alert protocol, the change cipher spec protocol, and the application data protocol.
从官方介绍来看,TLS1.2 主要由四个协议组成,也就是说一共有四份子协议:
记录协议(Record Protocol) 警报协议(Alert Protocol) 握手协议(Handshake Protocol) 变更密码规范协议(Change Cipher Spec Protocol)
记录协议(Record Protocol)
记录协议规定了 TLS传输的基本单位是记录(record),record 可能包含长度,描述和内容,有点类似TCP的Segament的概念,通用是可以进行分块传输的。同样record具备分块、压缩、编码、解压缩、重组等等和TCP分块类似功能。
和TCP不同的是,TLS 可以把多个记录一次性放到TCP里面进行传输,并且不需要返回ACK。
此外,这个协议还规定了安全通信的能力:
可靠连接。使用 MAC(Message Authentication Code,消息验证码,TLS 目前使用的 HMAC 也属于 MAC 的一种)为数据提供完整性校验。同样,在握手阶段也可以不使用该功能。 私有连接:比如对称加密使用的AES和CHACHA20(协议中列举的几个后续被证明不安全),对称加密的密钥是不固定的,但是需要注意Record 协议也可以提供不加密的封装,比如在握手阶段的 Hello 报文。 意味着整个连接过程是“可定制化”的,很多参数都是可选的,这些内容将会在下文介绍。
警报协议(Alert Protocol)
警报协议通常在传输出现问题的时候起到警示作用,警报协议用于终止一些存在危险隐患的请求,有点类似HTTP状态码,我们可以举几个例子方便理解:
bad_record_mac:错误的MAC地址 decode_error:解码异常 protocol_version:表示旧版本不受支持
握手协议(Handshake Protocol)
用于协商会话的安全属性,通常被封装在一个或者多个 TLSPlaintext 的结构中,简单来说主要是指定当前会话状态。
struct { ContentType type; ProtocolVersion version; uint16 length; opaque fragment[TLSPlaintext.length]; } TLSPlaintext;
握手协议是整个TLS里面最复杂也是最为核心的部分,当然也是真正天天都在用的协议,在这里定义了TLS握手协议,随机数以及密码套件等等信息,规定了整个TLS握手的细节。
握手协议的主要内容可以分为下面三点:
身份认证:指的是利用CA端进行身份认证,身份认证的过程会用到非对称加密算法,比如RSA算法,注意HTTPS支持客户端和服务端双向认证,默认是服务单单向认证,客户端认证是可选的。 安全参数协商:安全参数认证指的是保证被认证数据的机密性,需要用到比如哈希算法、密钥、加密算法等算法,对于数据加密处理。 可靠协商:可靠协商指的是防止数据传输过程中被篡改。
握手协议定义了这些命令:ClientHello、SeverHello、Certificate、ServerKeyExchange、CertificateRequest、ServerHelloDone、ClientKeyExchange、CertificateVerify、ChangeCipherSpec、Finished。
变更密码规范协议(Change Cipher Spec Protocol)
主要用在握手阶段的协议,通知对方在出现这个标识之后,所有的内容都将会使用密文进行传输。接下来来看看整个握手的流程,RFC用极简风格演示了整个TLS握手协议,丑是丑了点,但意外的特别好懂。
Application Data 协议
除开上面四个主要协议之外,还有Application Data 协议。
Application Data 协议用在通信阶段,封装了应用层的数据,通过 Record 协议封装之后,再通过 TCP 协议转发出去。
此协议用于握手连接完成之后的数据传输规范,实际上可以看作是SSL和TCP的协议的对接。
TLS1.2 协议握手流程
#HTTPS通信步骤
这里有必要强调是TLS1.2协议握手流程,因为TLS1.3协议对于很多细节和内容进行了简化,这些内容将在后续内容继续介绍。
这里我们填一下在[[《图解HTTP》 - HTTPS]]的读书笔记中埋下的坑,在这本书中仅仅对于HTTPS传输做了大致的介绍,并没有深入到各个步骤的细节内容,下面就根据每一步来解释更加详细的传输步骤。
首先我们应该明白,HTTPS需要四次握手,一共需要在客户端和服务端之间来回两次,才能确定一个HTTPS的连接是安全的。
这部分内容建议结合WireShark 介绍TLS1.2加密的实验,目前网络上大部分的资料介绍的都是TLS1.2的加密过程。
之前从数字加密的历史以及HTTP到HTTPS的历史以及SSL/TLS的历史梳理了大概。现在我们从RFC协议的规范层面,来看看HTTPS连接是如何定义的。
首先给出RFC中的流程定义,官方给了两个版本,第一个版本包含完整的请求,而第二个版本则是交互步骤中必须经过的过程。
master_secret = PRF(pre_master_secret, “master secret”, ClientHello.random + ServerHello.random) [0…47];
表示可选发送的可选消息或取决于情况而必须 消息。
简化之后的版本如下:
接着我们再画一个整个HTTPS的交互流程图,这是本次内容的重点。
补充:截图完发现 4-START 第四次握手这里是开始,不是结束 =-=。
整个流程还是有点点复杂的,但是拆分成四次握手,记住一些核心步骤并不难理解。
TCP三次握手
TCP三次握手的流程图这里还是用的之前已经画过的:
第一步:客户端主动打开TCB端口,服务器被动打开TCB端口。客户端作为发起方携带一个SYN标志,并且携带一个ISN序号Seq=x,但是需要注意的是第一步的过程这个ISN序号是隐藏传递的(因为没有传递数据),因为如果请求不存在数据的交换则不会被显示。客户端发送SYN命令之后进入设置SYN=1,并且设置自己的状态为SYN-SENT(同步-已发送状态)。 第二步:服务器收到客户端TCP报文之后,也将SYN=1,并且回送一个新的ISN序号ack=x+1,并且将ACK=1表示自己收到了,然后在返回参数回送自己新的序列号表示自己的确认请求Seq=y,将状态设置为SYN-RCVD(同步收到)状态,(表示希望收到的序号为xxxx1522),最后也是指定MSS。 第三步:客户端收到服务器的确认报文之后,还需要向服务端返回确认报文,确认报文的ACK=1,并且回传服务器传递的ISN序号+1(ack = y+1),以及自己的ISN序号+1(Seq = x+1),此时TCP连接进入已连接状态。注意ACK是可以携带数据的,但是如果不携带数据则不消耗序列号。 最后一步:当服务器收到客户端的确认,也进入已连接状态。
经过TCP三次握手连接建立,直到断开连接之前都可以传递数据,TCP 构建之后,则开始进行SSL握手。