X.509数字证书标准

193 阅读6分钟

PKI

PKI(公钥基础设施 Public Key Infrastructure)是一组由硬件、软件、参与者、管理政策与流程组成的基础架构,其目的在于创造、管理、分配、使用、存储以及撤销数字证书,主要组成元素有:

  • 用户:使用PKI的人或者机构
  • CA:认证机构,颁发证书的人或者机构
  • 仓库:保存证书的数据库

X.509是PKI的标准格式

x.509标准

x.509是密码学里数字证书的一种格式标准,广泛应用在SSL/TLS等网络协议中,同时也用在离线场景中的电子签名。 x.509证书包含持有者的身份信息、公钥和签名信息(CA签名或者自签名),另外x.509还附带证书吊销列表和基于证书信任链的合法性验证算法。

证书签发

在x.509中,组织机构通过CSR(证书签名请求)来从CA获取签名证书,具体过程如下:

  • 组织机构生成本地私钥
  • 通过私钥生成csr文件,csr文件包含组织机构的身份信息以及公钥
  • 将csr文件发向ca,ca对组织机构和证书进行审核后,利用自身的私钥和证书对csr进行签名,生成数字证书并发给申请的组织机构

证书链

由于证书申请存在大量需求,不可能全部由一个CA来签发,所以CA实际上是层级结构,我们称顶级CA为根认证机构,由根认证机构签发授权的为二级认证机构,由二级认证机构签发授权的为三级认证机构,以此类推等等... 最终由最底层的认证机构签发用户的数字证书。我们称根认证机构的证书为根证书,其他的依次为二级CA证书、三级CA证书等等,从根证书到用户数字证书这些证书形成了一条链,这就是证书链。

证书的签发和验证过程中都涉及到证书链,以下从签发和验证两方面展开介绍:

假设存在根认证机构CA、二级认证机构CA2以及期望申请证书的机构USER

签发过程

  1. CA自签发获得证书ca.crt
  2. CA2向CA提交ca2.csr文件,包含公钥和身份信息,CA利用自身的私钥和证书形成数字签名,附在csr文件后面形成了证书文件ca2.crt
  3. USER向CA2提交user.csr文件,包含公钥和身份信息,CA2利用自身的私钥和证书形成数字签名,附在csr文件后面形成了证书文件user.crt

验证过程

某一验证方需要验证USER的证书user.crt

  1. 验证方获取USER证user.crt以及证书的签发方CA2的公钥,利用CA2公钥解密证书的数字签名得计算结果R1,再单独对证书进行摘要计算得计算结果R2,如果R1等于R2,说明此证书是由CA2签发
  2. 然后对CA2证书进行验证,取CA2证书ca2.crt(一般第一步对端会将整个证书链发过来,其中就包含S1证书和S2证书)以及证书的签发方CA的公钥,利用CA公钥解密证书的数字签名得计算结果R3,再单独对证书进行摘要计算得计算结果R4,如果R3等于R4,说明此证书是由CA签发,证书的主体信息也是正确的
  3. 然后对CA证书进行验证,由于CA的证书ca.crt是根证书,一般根证书是内置在操作系统或者浏览器中的,此类证书被自身信任,无需验证。另外如果直接将CA2证书ca2.crt放置在本地可信证书池,则第二步就完成了整个验证过程 至此,即完成了对证书CERT_C1的验证

手动实践

/*
任务:
	1. 自签发根CA证书
	2. 利用根CA证书签发二级CA证书
	3. 利用根CA证书签发用户证书
*/

// 1.1 生成根ca私钥
$ openssl genrsa -out ca.key 4096
Generating RSA private key, 4096 bit long modulus (2 primes)
...

// 1.2 生成根ca csr
$ openssl req -new -key ca.key -out ca.csr
...
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:BJ
Locality Name (eg, city) []:BJ
Organization Name (eg, company) [Internet Widgits Pty Ltd]:TEST
Organizational Unit Name (eg, section) []:TEST
Common Name (e.g. server FQDN or YOUR name) []:TEST
Email Address []:
...

// 1.3 生成根ca证书
$ openssl x509 -req -days 365 -in ca.csr -signkey ca.key -out ca.crt
Signature ok
subject=C = CN, ST = BJ, L = BJ, O = TEST, OU = TEST, CN = TEST
Getting Private key

// 2.1 生成二级ca私钥
$ openssl genrsa -out ca2.key 4096
Generating RSA private key, 4096 bit long modulus (2 primes)
...

// 2.2 生成二级ca csr
$ openssl req -new -key ca2.key -out ca2.csr
...
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:BJ
Locality Name (eg, city) []:BJ
Organization Name (eg, company) [Internet Widgits Pty Ltd]:TEST
Organizational Unit Name (eg, section) []:TEST2
Common Name (e.g. server FQDN or YOUR name) []:TEST2
Email Address []:
...

// 2.3 拓展配置
$ cat << EOF > ca2.ext
basicConstraints=CA:true
crlDistributionPoints=URI:https://test.cn/test.crl
EOF

$ openssl x509 -req -days 365 -CA ca.crt -CAkey ca.key -CAcreateserial -in ca2.csr -out ca2.crt -extfile ca2.ext -sha256
Signature ok
subject=C = CN, ST = BJ, L = BJ, O = TEST, OU = TEST2, CN = TEST2
Getting CA Private Key

// 3.1 生成用户ca私钥
$ openssl genrsa -out user.key 4096
Generating RSA private key, 4096 bit long modulus (2 primes)
...

// 3.2 生成用户ca csr
$ openssl req -new -key user.key -out user.csr
...
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:BJ
Locality Name (eg, city) []:BJ
Organization Name (eg, company) [Internet Widgits Pty Ltd]:USER
Organizational Unit Name (eg, section) []:USER
Common Name (e.g. server FQDN or YOUR name) []:USER
Email Address []:
...

// 3.3 生成用户ca证书
$ openssl x509 -req -days 365 -CA ca2.crt -CAkey ca2.key -CAcreateserial -in user.csr -out user.crt -sha256
Signature ok
subject=C = CN, ST = BJ, L = BJ, O = USER, OU = USER, CN = USER
Getting CA Private Key

// 4.1 校验ca2.crt合法性
$ openssl verify -CAfile ca.crt ca2.crt
ca2.crt: OK

// 4.2 校验user.crt合法性: 注意此处要合并所有的ca证书做验证
openssl verify -CAfile <(cat ca.crt ca2.crt) user.crt
user.crt: OK

交叉证书

交叉证书是解决两个独立的根证书体系中,一个根证书下签发的用户证书如何被另外一个根证书信任的问题。

交叉证书的原理是多个CA机构可对同一公钥进行签发证书,从而该公钥下签发的证书到根证书间可以形成多条证书链

在进行根证书更新时,CA生成一对新的秘钥对和根证书,然后用新的私钥为老的公钥签名生成一个中间证书,并用老的私钥为新的公钥签名生成一个中间证书。这样,无论是新的根证书还是老的根证书颁发的证书在更新期间都可以正常使用,以实现CA新老根证书的平滑过渡。

/*
前提:
	1. 存在自签发顶级CA1和CA2
	2. CA1和CA2分别签发用户证书USRE1和USER2
目标:
	3. 实现在不经过CA2证书的情况下信任USER2证书

// 1.1 CA1自签发证书
$ openssl genrsa -out ca1.key 4096
$ openssl req -new -key ca1.key -out ca1.csr
$ openssl x509 -req -days 365 -in ca1.csr -signkey ca1.key -out ca1.crt

// 1.2 CA2自签发证书
$ openssl genrsa -out ca2.key 4096
$ openssl req -new -key ca2.key -out ca2.csr
$ openssl x509 -req -days 365 -in ca2.csr -signkey ca2.key -out ca2.crt

// 2.1 USER1用户证书
$ openssl genrsa -out user1.key 4096
$ openssl req -new -key user1.key -out user1.csr
$ openssl x509 -req -days 365 -CA ca1.crt -CAkey ca1.key -CAcreateserial -in user1.csr -out user1.crt -sha256

// 2.2 USER2用户证书
$ openssl genrsa -out user2.key 4096
$ openssl req -new -key user2.key -out user2.csr
$ openssl x509 -req -days 365 -CA ca2.crt -CAkey ca2.key -CAcreateserial -in user2.csr -out user2.crt -sha256

// 3.1 验证用户证书
$ openssl verify -CAfile <(cat ca1.crt) user1.crt
user1.crt: OK
$ openssl verify -CAfile <(cat ca2.crt) user2.crt
user2.crt: OK
// 可以看到此时不经过CA2是无法验证到USER2证书的
$ openssl verify -CAfile <(cat ca1.crt) user2.crt
C = CN, ST = BJ, L = BJ, O = USER2, OU = USER2, CN = USER2
error 20 at 0 depth lookup: unable to get local issuer certificate
error user2.crt: verification failed

// 3.2 生成交叉证书: 利用CA1给CA2签名
$ cat << EOF > ca2.ext
basicConstraints=CA:true
crlDistributionPoints=URI:https://test.cn/test.crl
EOF
$ openssl x509 -req -days 365 -CA ca1.crt -CAkey ca1.key -CAcreateserial -in ca2.csr -out cross_ca2.crt -sha256 -extfile ./ca2.ext

// 3.3 利用交叉证书和CA1证书即可验证
$ openssl verify -CAfile <(cat ca1.crt cross_ca2.crt) user2.crt
user2.crt: OK
*/

证书更新

一般证书升级即令应用程序先同时支持新旧证书,待全部升级以及替换完成后,不存在对旧证书的依赖时,再删除旧证书配置

证书吊销

证书是有生命周期的,如果证书的私钥泄漏了那这个证书就得吊销,一般吊销方式有CRL和OCSP。

CRL( Certificate Revocation List)是CA机构维护的一个已经被吊销的证书序列号列表,浏览器需要定时更新这个列表,浏览器在验证证书合法性的时候也会在证书吊销列表中查询是否已经被吊销,如果被吊销了那这个证书也是不可信的。可以看出,这个列表随着被吊销证书的增加而增加,列表会越来越大,浏览器还需要定时更新,实时性也比较差。

所以,后来就有了 OCSP (Online Certificate Status Protocol)在线证书状态协议,这个协议就是解决了 CRL 列表越来越大和实时性差的问题而生的。有了这个协议,浏览器就可以不用定期更新CRL了,在验证证书的时候直接去CA服务器实时校验一下证书有没有被吊销就可以,是解决了CRL的问题,但是每次都要去CA服务器上校验也会很慢,在网络环境较差的时候或者跨国访问的时候,体验就非常差了,OCSP虽然解决了CRL的问题但是性能却很差。