证书可以理解为签发方信息、拥有者信息、公钥以及签名(由签发方私钥签名)的集合(当然还有额外信息)。校验证书是否可信,实际就是检验该证书是否是由合法的签发方签发,验证的方法就是首先通过签发方信息找到对应的签发方证书,利用签发方证书中的公钥去校验签名是否正确。
从上述验证方法可以看出,实际上证书是否可信是由其签发方的证书来进行校验的,而签发方的证书的可信是由上一层签发方的证书来校验的,如此就形成一条证书链,而最顶层的就是常说的根证书。此外有也许会问如果浏览器中找不到签发方证书怎么办?而且签发方确认是可信的,此时在TLS协商的时候,可以下发证书链。
随便搜一下TLS证书,会出现一大堆关键字:X.509, p12, pfx, pkcs, pem, csr, cer, crt, jks, crl等,这么繁杂一下就让人想从入门到放弃了,不过还是耐心梳理一下。
(一)X.509
X.509就是一个广泛应用的数字证书标准,简单来说就是定义了数字证书里面包含哪些字段,如何存储,可以参照一下RFC5280;协议中定义的参数都是采用DER编码(X.690),DER编码可以理解为一种TLV(Tag Length Value)格式编码。
以一个实际的证书内容为例,如下所示:
Certificate:
Data:
Version: 3 (0x2) //表示为X509 v3版本证书
Serial Number: 1 (0x1) //序列号,签发时需保证同一签发方所签发的每个证书都一个唯一的Serial Number
Signature Algorithm: sha256WithRSAEncryption //签名算法,先进行SHA256摘要后,使用签发方私钥进行RSA加密
Issuer: C=CN, ST=JS, L=NJ, O=Dreamer, OU=Dreamer, CN=Dreamer //签发方DN(Distingushed Name),见后续说明
Validity //证书有效期
Not Before: Jul 29 14:02:13 2018 GMT
Not After : Jul 26 14:02:13 2028 GMT
Subject: C=CN, ST=JS, O=Dreamer, OU=JM, CN=*.dreamer.com //证书拥有方DN(Distingushed Name)
Subject Public Key Info: //证书公钥信息
Public Key Algorithm: rsaEncryption
Public-Key: (1024 bit)
Modulus:
00:c5:b8:68:a2:9c:bd:11:0c:83:34:a2:97:a5:8e:
72:75:2a:bc:f4:75:fc:d0:a3:47:7d:e4:6b:4f:ed:
dd:79:7c:0f:ce:6e:e7:d2:7d:10:cd:e8:07:56:34:
58:e3:2b:2e:c9:e3:7f:ae:27:2d:f7:a3:17:6f:dd:
65:d7:f8:4f:d0:be:9c:3b:9b:ea:ed:86:d2:19:67:
81:60:53:64:c9:d1:be:17:7d:5d:7f:cc:58:1d:b6:
e1:51:0d:ba:32:ac:4d:73:a4:fc:8f:6a:79:f9:44:
25:03:b6:1c:3e:0f:e9:b8:36:b1:07:07:59:54:40:
d7:2c:52:ab:68:fe:ed:e2:6f
Exponent: 65537 (0x10001)
X509v3 extensions://v3版本扩展信息
X509v3 Basic Constraints:
CA:FALSE //表示证书拥有方是否是CA机构,可签发证书,如为True,则还可以添加一个pathLengthConstraint来显示签发链的长度
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier: //证书拥有方密钥ID,对于CA: TRUE时需要加入此扩展
67:30:EE:FB:39:A4:92:56:9C:1A:E8:94:10:A4:3B:EA:EC:2E:04:9E
X509v3 Authority Key Identifier: //证书签发方所对应密钥ID,用于签发方的公钥查找(特别是存在多个密钥时)
DirName:/C=CN/ST=JS/L=NJ/O=Dreamer/OU=Dreamer/CN=Dreamer
serial:A0:09:E3:A9:D2:C1:86:7C
X509v3 Subject Alternative Name: //证书拥有方的别名,此处用户多域名证书的签发
DNS:*.example.com, DNS:*.jm.com
Signature Algorithm: sha256WithRSAEncryption //证书签名信息
91:db:9b:0c:9b:6e:68:24:d3:2f:3a:67:b5:c0:6c:f0:c8:4c:
f8:87:86:93:eb:fc:dc:ef:dc:7b:2e:2c:0e:7b:52:23:4d:de:
d9:69:a8:ee:ae:aa:14:04:ca:1a:03:87:fe:11:60:fe:16:8f:
87:9d:9e:d0:3a:be:33:03:f6:25:8a:10:37:f8:90:9d:67:5c:
36:a6:1e:3c:59:d9:8f:eb:22:0e:f7:3c:7d:47:10:9b:0b:03:
f0:8c:70:b0:3c:40:c6:5d:cc:6b:ba:40:ce:89:04:c7:3c:be:
af:bd:1d:94:6b:83:39:29:74:de:12:fc:63:0d:0f:39:31:3b:
48:fd
除了上述的注释说明外,需要补充的几点如下:
1. Subject和Issuer均为DN格式,常见格式:C=国家, ST=省市, L=区县市, O=组织机构, OU=组织单位, CN=通用名称。
2. DN是证书链查找的关键,验证是会根据Issuer的DN去匹配签发方的证书,具体的匹配方法是比较DN的数量以及各DN参数值,相对来说还是比较严格的
3. DN中的CN通用名称一般表现为域名,如需支持子域名,例如abc.server.com, bcd.server.com,可使用泛域名形式*.server.com
4. Subject Alternative Name扩展字段可用于多域名证书,后续将会具体介绍多域名证书的签发。
(二)证书编码格式(DER&PEM)
X.509中说明证书各个字段编码均适用DER格式进行编码,最终实际上整个证书就是一个纯二进制格式文件,那PEM编码又是什么格式呢?
按照网上普遍说法,X.509有DER和PEM两种编码格式,其实这种说法个人认为有点歧义,实际上这两种编码格式并不在一个层面上。前面说过DER一种纯二进制TLV格式的编码协议,那PEM是否也是一种类似TLV的键值型的编码格式呢?其实PEM并没有去处理X.509的内部参数,而是在X.509进行DER编码之后,对二进制数据进行了BASE64编码,然后加上文件头尾即可,如下所示:
-----BEGIN CERTIFICATE-----
BASE64编码内容
-----END CERTIFICATE-----
具体区分DER还是PEM也很简单,打开有乱码的是DER格式文件,打开类似上面格式的就是PEM格式证书文件。
(三)证书相关扩展名
扩展名是比较容易误导人的地方,除了.der或.pem后缀外,还有以下常见后缀:
-- crt:常见于*nix系统,大多是PEM编码,也可能是DER编码
-- cer:常见于Windows系统,大多是DER编码,也可能是PEM编码
-- key:用户存放密钥信息,和证书一样,可能是DER编码,也可能是PEM编码;可参照PKCS#1(RFC8017)查看其具体字段和定义;但密钥明文存储方式有所危险,一般可以使用PKCS#8格式(RFC5958)进行密钥的加密,即设置一个提取密钥
-- csr:证书签发请求,其实与证书内容相似,但不包含签发方信息,签发方根据CSR并添加自身的签发信息,从而生成证书文件,详情可参照(PKCS#10 RFC2314)
-- pfx/p12:实际上就是将证书和私钥一并打包成一个文件,并且设置“提取密码”
-- jks/keystore/truststore: 一般常见于JAVA相关应用,实际上也是和p12类似,将证书和私钥一并打包并设置“提取密码”,至于keystore和truststore只是概念上的区别,keystore一般用户表示用户或服务器证书,而truststore一般表示CA证书。
想要深入研究的童鞋可以看一下PKCS协议族,上述的key、csr、pfx/p12等都是该协议族中定义的相应扩展。后续将会结合本次内容讲解以下证书生成。