转自:https://mp.weixin.qq.com/s/ibwNtDc2zd2tdhMN7iROJw
作者:腾讯优图实验室 来源:腾讯技术工程

1、 证书是什么?

解释这个问题之前,先看几个关键词:CA,CA 机构,数字证书,数字签名,(证书)指纹,(CA)证书,HTTPS 证书,SSL/TLS 证书

理一理上面这些关键词之间的关系:

CA,CA 机构:机构/组织概念。

数字证书,(CA)证书,HTTPS 证书,SSL/TLS 证书:CA 签发的数字证书。

数字签名,(证书)指纹:CA 签发的证书的内容之一,一段加密的密文。

智库百科对数字证书的解释是:

数字证书也称公开密钥证书,是指用于电子信息活动中电子文件行为主体的验证和证明,并可实现电子文件保密性和完整性的电子数据。数字证书是一个经证书认证中心(Certification
Authority,简称 CA)发行的文件。

数字证书包含有行为主体信息和证书认证机构的数字签名。数字签名是指以电子形式存在,可依附在电子文件中用于辨识电子文件的签署者及表示对该电子文件内容负责所使用的电子数字标识。

抓重点:数字证书用于主体身份验证。

首先,数字证书=主体信息+数字签名。

Windows 下,我们可以在 Chrome 浏览器上点击地址栏的“锁”标记后会出现下拉框,接着点击“证书”即可看到通过 HTTPS 访问该服务器时的数字证书。具体操作如下:

在这里插入图片描述

  • 证书“常规”页面,是关于该证书的一个笼统介绍,包括签发该证书的 CA 机构、该证书绑定的域名(颁发给)、证书有效期。
  • 证书“详细信息”页面,以键值对形式展示了这张证书的完整内容。(后文将详细介绍证书内容)
  • 证书的“证书路径”,以层级结构展示了从该证书绑定的域名一直到根证书的路径,这就是证书链。(后文会展开介绍证书链)

主体的必要信息:版本(version)、序列号(serialNumber)、签名算法(signatureAlgorithm)、颁发者(issuer)、有效期(validity)、使用者(subject)、公钥信息(subjectPublicKeyInfo)

主体的扩展信息(extension):如密钥标识符、证书策略等

数字签名(signature),也称指纹

抽象为下图:
在这里插入图片描述

2、 为什么是数字证书呢?

HTTPS 已经对通信数据进行了加密,为什么还要验证身份?说好的“人与人之间最基本的信任呢?”

这还不是因为各路黑客、骇客们总是在制造各种攻击吗?其中一个大名鼎鼎的中间人攻击(Man-In-The-Middle Attack,MITM 攻击),简单的讲,“中间人”在客户端和服务端都不知情的情况下,夹在双方之间窃听甚至篡改通信信息,过程见下图(图引自《HTTPS 中间人攻击实践(原理·实践)》):

在这里插入图片描述在 HTTPS 的握手阶段,一端向对端发送请求,对端返回自己的公钥;而一端未验证对方的身份和公钥,直接协商密钥。“中间人”看到了这个漏洞,夹在中间截获了对端的公钥,替换成了自己的公钥。正是这步“拿错了公钥”或者说“信错了对端”,使得 HTTPS 为加密(密钥协商的非对称加密和通信数据的对称加密)所做的努力全部泡汤。

可见,在 HTTPS 中,“确保对端身份正确”即“确保拿到的公钥正确”,而在网络通信中所谓的“身份”,一般指的是通信一端的域名、IP 地址甚至是Mac 地址。所以,数字证书同时包含了通信一端的身份信息和公钥信息。

但是数字证书会在网络中传输(由被要求验证身份的一端通过网络传给另一端),这就意味着证书也可能会被窃取篡改。这个时候权威的 CA 机构就出马了,他想了个办法:加了一个“防伪标识”— 数字签名。具体做法如下:

1
signature = RSA(PriKey_CA, Hash(message))

这里啰嗦几句:数字签名生成过程是首先对原文作哈希,把一段不定长的文本映射成固定长度的字符空间,接着再用 CA 机构的私钥对这段定长字符做加密。大大提高了整体的运算效率。

3 证书是怎么工作的?

要了解证书是怎么做“身份验证”,即“防冒充”,得从 2 个角度来说明:

申请证书,即需要被验证身份的一端,需要申请一份能够验证自己身份的证书
验证证书,即需要验证对方身份的一端,拿到证书后验证对端的身份

请注意,这里有一个前提:这张证书必须是由权威 CA 机构颁发的,且尚在有效期内;或者是一张信任的私人证书。

申请证书

CA 机构和证书的分类本文不讨论,推荐阅读《细说 CA 和证书》,这里我们讨论正规权威 CA 机构签发的证书,至于是 DV、OV 还是 EV,只是安全强度问题,工作原理是一样的。

总结申请证书的过程:用户向 CA 机构提交自己的信息(如域名)和公钥(用户自己生成的非对称加密公钥,用于 TLS 握手阶段和另一端协商密钥用),CA 机构生成数字证书,如下图:

在这里插入图片描述
验证证书

收到对端发过来的证书,执行证书申请的“逆过程”即可,总结如下图:
在这里插入图片描述

接受证书的一端先对除数签名的其他部分做一次相同的哈希算法(证书中指明了哈希算法),得到这段文本的哈希映射,记作 H1;获取 CA 机构的公钥对数字签名属性做解码,得到了 CA 机构计算出的哈希映射,记作 H2。对比 H1 和 H2 两个字符串是否严格相等,若是,代表该证书的信息未被篡改,证书有效;否则,证书内容被篡改,证书无效。

若证书有效,接受端会再进行对端的身份校验(验证域名),若身份验证通过,接收端会拿证书上的公钥(也是对端自己生产的非对称加密公钥)加密接下来整个 TLS 握手阶段的信息之后,发送给对端。

这个过程中有一个问题:CA 机构的公钥怎么获取?

回答:提前内置

众所周知,操作系统和浏览器在软件安装阶段会在其特定目录下放置一堆的证书。如 Windows 的根证书管理在 certmgr 下:

在这里插入图片描述
这些证书都有个特点:权威 CA 机构发布的根证书(Root Certificate)。根证书有几个特点:

没有上层机构再为其本身作数字签名

证书上的公钥即为 CA 机构发布的公钥

权威 CA 机构的自签证书

而这些根证书会跟很多软件,包括操作系统、浏览器一起被安装到用户设备上。即使没有被提前安装好,这些根证书也可以在 CA 机构的官网上获取得到。

目前全球大型权威 CA 机构有 Symantec、GeoTrust、Comodo 以及 RapidSSL 等,并且这些机构颁发的 SSL 数字证书,在市场的占有率是非常的高。(节选自《SSL 证书颁发机构有哪些》)

本地被内置了这么多的根证书,那要怎么知道我这份证书应该要用哪一个根证书来验证呢?

回答:证书信任链

在信任链上有 3 类证书:根证书,中介证书和用户证书。根证书前文已有说明,用户证书就是对端发过来的证书,或者说是用户向权威 CA 机构绑定了自己身份(主要指域名)和自己公钥的证书。中介证书可以理解由权威 CA 机构委派的代理机构签发的数字证书,推荐阅读《What is an intermediate certificate?》。中介证书或者说是中介机构的存在是为了保证根证书的密钥的安全性。

细心的同学仔细看一看 certmgr 会发现有一个分类是“中间证书颁发机构”,这里存放的就是中介证书。用户证书绝大多数是通过权威的 CA 机构的代理中介机构颁发。

这么来说,根据对端发来的用户证书寻找对应的根证书岂不是更困难了?

自问自答:这是一个在树形数据结构中,从叶子节点搜索根节点的过程,直接一个最原始的深搜(DFS)不就可以了嘛?举例说明,如下图(引自Wikipedia-Chain of trust):
在这里插入图片描述

从用户证书开始。

记“Issuer”字段的值为 i1,搜索本地证书,寻找由“Subject”为 i1 的证书。

若没有找到,结束返回证书无效;否则,跳到步骤 4)。

判断该证书的 Issuer 值是否等于 Subject 值。

若是,则该证书是根证书,结束返回该证书;否则跳到步骤 6)。

以该证书开始,跳转 2)(继续搜索)。

更多关于信任链的知识点,推荐阅读《What is the SSL Certificate Chain?》

4、证书怎么样?

相信不少同学或多或少接触过证书文件,比如.pem、.crt、.cer、.key 等,于是问题就来了:

“为什么有这么多不同后缀名的证书啊?他们有什么联系和区别?”

回答这个问题要从 3 个层面来分析:

证书标准

证书编码格式

文件扩展名

证书标准

数字证书的格式普遍采用的是 X.509 国际标准,维基百科对于 X.509 解释如下:

X.509 是密码学里公钥证书的格式标准。X.509 证书已应用在包括 TLS/SSL
在内的众多网络协议里,同时它也用在很多非在线应用场景里,比如电子签名服务。X.509
证书里含有公钥、身份信息(比如网络主机名,组织的名称或个体名称等)和签名信息(可以是证书签发机构 CA
的签名,也可以是自签名)。对于一份经由可信的证书签发机构签名或者可以通过其它方式验证的证书,证书的拥有者就可以用证书及相应的私钥来创建安全的通信,对文档进行数字签名。

X.509 是 ITU-T 标准化部门基于他们之前的 ASN.1 定义的一套证书标准。

证书的编码格式

X.509 标准的证书文件具有不同的编码格式:PEM 和 DER。

  • PEM

PEM,全称 Privacy Enhanced Mail,以文本格式存储,以 —–BEGIN
XXX—–开头、—–END XXX—–结尾,中间内容是 BASE64 编码数据。其文本内容大概如下:

html —–BEGIN CERTIFICATE—– Base64编码过的证书数据 —–END CERTIFICATE—–

通常,PEM 格式可以存储公钥、私钥、证书签名请求等数据。查看 PEM 格式证书的信息一般采用如下命令:

openssl x509 -in xxx.pem -text -noout
Apache 和 Nginx 服务器偏向于使用这种编码格式.

  • DER

DER,全称 Distinguished Encoding Rules,以二进制存储,因此文件结构无法直接预览,只能通过如下命令查看:

html openssl x509 -in xxx.der -inform der -text -noout

DER 格式也可以存储公钥、私钥、证书签名请求等数据。Java 和 Windows 应用偏向于使用这种编码格式。

当然同一 X.509 证书的不同编码之间可以互相转换:

  • PEM 转为 DER:
1
openssl x509 -in xxx.pem -outform der -out xxx.der
  • DER 转为 PEM:
1
openssl x509 -in xxx.der -inform der -outform pem -out xxx.pem

文件扩展名

不同的扩展名可以分为以下几类:

  • 证书:

存放数字证书,X.509 标准,格式可能是 PEM 或 DER。.crt、.cer

  • 密钥:

用来存放一个 RSA 公钥或私钥,这类文件不是 X.509 标准,但是是 PEM 或 DER 格式。后缀名有.key。

  • 证书+密钥:

可同时存放证书和 RSA 公钥/.pem、.der、.p12

  • 证书请求:

并不是证书,而是证书签名请求。csr