程序锅

  • 首页
  • 分类
  • 标签
  • 归档
  • 关于

  • 搜索
基础知识 Etcd LeetCode 计算机体系结构 Kubernetes Containerd Docker 容器 云原生 Serverless 项目开发维护 ELF 深入理解程序 Tmux Vim Linux Kernel Linux numpy matplotlib 机器学习 MQTT 网络基础 Thrift RPC OS 操作系统 Clang 研途 数据结构和算法 Java 编程语言 Golang Python 个人网站搭建 Nginx 计算机通用技术 Git

数字证书

发表于 2023-06-18 | 分类于 基础知识 | 0 | 阅读次数 2799

问题

对加密技术,只有最基础的了解,比如对称加密、不对称加密是指什么。除此之外,并没有再深入的了解了。同时,对于目前使用比较广泛的数字证书,比如Web 网站需要数字证书、Kubernetes 访问也需要数字证书等,都没有太多的了解。

前置知识

  • 对称加密。采用一个秘钥来对数据进行加密和解密。消息发送方先采用秘钥对明文进行加密然后再进行传送,待接收方收到消息后,再采用秘钥对密文进行界面,以得到明文。

  • 非对称加密。采用两个密钥:公开密钥(publickey:简称公钥)和私有密钥(privatekey:简称私钥),公钥与私钥是成对使用的。如果用公钥对数据进行加密,只有用对应的私钥才能解密;同样,使用私钥对数据进行加密,只有用对应的公钥才能解密。

    非对称加密和对称加密往往会结合使用。非对称加密的效率比对称加密低,而对称加密需要双方事先交换加/解密用的共享秘钥,而交换的过程就存在密码泄露的风险。为此在通信过程中,往往先通过非对称加密协商一个用于对称加密的共享秘钥,后续在传递数据时采用该对称加密秘钥匙来对数据加密,以在保证安全性的同时兼顾加密传输的效率。SSL/TLS就采用了类似的加密传输机制。

  • 哈希函数。可以将一段任意长度的内容,转化为一段固定长度的二进制数据,用数学方式表示就是:H(X)=Y:。其中,

    • H: 哈希函数,其输入参数为X,输出为Y。
    • X: 哈希方法的输入,可以是任意长度的任意数据。
    • Y:哈希方法的输出,是一段固定长度的二进制数据,长度可以是256,384,516…。

    有以下几个特征:

    • 无法找到可以产生相同输出,但不同的输入。从数学理论上来说,我们是可以找到具备相同输出的不同输入的,因为输入可以是任何数据,而输出则是固定长度的,是有限的。但是对于一个好的哈希函数来说,我们就是使用地球上所有的计算机一起进行计算,也无法在可以接受的时间内找出该输入。
    • 无法通过输出反推出输入。针对输入值是一个有限的集合来说,则很容易通过遍历尝试每一个输入值来推断出一个输出对应的输入。可以为输入 X 加上一个随机值 R 来隐藏输入值,即 H(R|X)=Y。由于攻击者不知道 R 的值,因此无法再通过遍历尝试每个输入的方法推断出 Y 对应的输入。这种做法被称为“加盐”,例如我们在存储密码时就会通过“加盐”的方法来避免彩虹表攻击。

数字签名

数字签名算是非对称加密技术的一种应用吧。秘钥的拥有者先采用私钥对一段数据进行加密(签名),然后公布密文,原文和公钥。任何人拿到这些信息之后,可以使用公钥解密密文,然后核对原文和解密出来的内容是否一致。如果一致的话,则说明这是由公钥对应的私钥加密的,并且内容没有改变。这个就是数字签名的基本原理,整个过程如下所示:

拥有者生成秘钥对: (sk,pk):= generates(keysize)
拥有者生成数字签名: signature := encrypt(sk, message)
验证身份: isValid := isEqual(decrypt(pk, signature),message)

在实际使用中,由于传输的原文可能会很大,这个时候数据签名和传输的效率会很低。因此,往往会考虑通过哈希函数提取数据的特征值,然后只对数据的哈希值进行签名。整个过程如下所示:

拥有者生成秘钥对: (sk,pk):= generates(keysize)
拥有者生成数字签名: signature := encrypt(sk, hash(message))
验证身份:isValid := isEqual(decrypt(pk, signature),hash(message))

通过上述的方式,可以验证上述内容是由公钥对应的私钥发送的(相当于通过公钥就可以确定私钥的身份了),也可以验证在传输过程中并没有发生篡改。

怎么理解数字签名呢?简单来说的话,签名的行为可以理解成加密的行为,数字签名可以理解为加密后的内容。

我们拿现实生活举个例子。我们的签名是有辨识性的,通过签名的字迹可以确实是我们签的,而不是别人签的。比如,我们在这份合同上签上了名字,由于这个名字有特征,因此就可以证明这份合同确实是我们签的。

那么在互联网上,那我们如何向别人证明某些内容是我们发送的呢?这个时候我们就可以通过数字签名的方式。以上面合同的例子为例,先通过私钥给一份合同进行加密(签名)。然后把合同原文、公钥、加密的内容发送给对方。对方拿到之后,通过验证就可以判断是否是我们(公钥对应私钥的拥有者)“签名”的合同。

数字证书

在现实生活中身份认证有匿名的,也有实名的。匿名的身份证明只是用于证明你拥有某一项身份或者权益,并不需要声明你到底是谁,例如各种运动俱乐部的会员卡。实名的身份证明则需要你的姓名,住址,出生年月等信息,例如我们的身份证。

当只需要匿名的身份标识时,某个服务采用公钥对应的私钥对任意一段数据进行数字签名,并将原数据,公钥和签名数据给某个人,这个人拿着这些内容就可以表示自己是该服务的用户,别人拿到这些内容也可以表示自己是该服务的用户。这个时候,你只需要拥有公钥就可以表明你的身份了。比如,比特币是一个匿名的交易系统,它只需要证明你是比特币的拥有者,并不需要你的真实身份,此时在比特币中就直接采用了公钥作为比特币的钱包地址。

但是,在大部分情况下是需要证明公钥拥有者的真实身份,例如姓名,地址,电子邮件等,因此会将这些信息随着公钥一起发布,这就是数字证书,也就是说这个时候需要公钥和一些身份信息才能证明。比如,我们在某个服务注册了一个用户,这个用户有相应的权限,服务给我们颁发了相应的证书,这个时候我们只需要拿着这些证书去访问服务,服务就会根据我们的信息给予我们相应的访问权限。

对数字证书的理解,可以站在公钥的角度去理解,通过公钥采用匿名的方式对身份进行标识,或者通过公钥+身份信息的方式来对真实对身份进行标识。总结下的话,数字证书是指包含“公钥+姓名+地址+电子邮件等个人/组织信息”的一段数据,之后我们再通过数字签名的方式来证明证书拥有者的身份和确保证书中的信息在传输过程中不被恶意篡改。

x.509 格式

RFC5280 定义了 x.509 公钥证书的标准格式,如下图所示:

下面我们用 openssl 创建一个私钥和使用这个私钥签名的数字证书,并查看下这个证书的内容。

# 可以看到在证书创建过程中,会要求输入姓名、住址、电子邮件等身份信息。
$ openssl req -newkey rsa:2048 -nodes -keyout key.pem -x509 -days 365 -out certificate.pem

Generating a 2048 bit RSA private key
....+++++
........+++++
writing new private key to 'key.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) []:CN
State or Province Name (full name) []:Zhejiang
Locality Name (eg, city) []:hangzhou
Organization Name (eg, company) []:multiparam
Organizational Unit Name (eg, section) []:mp
Common Name (eg, fully qualified host name) []:name
Email Address []:dawnguo@dawnguo.com

# 查看刚才生成的证书文件中的内容。
openssl x509 -in certificate.pem -text

证书内容如下,命令行输出的前半部分是数字证书解码后的正式内容,"—–BEGIN CERTIFICATE—–“之后的部分则是采用PEM(Privacy Enhanced Mail)格式进行Base64编码的原始证书文件内容。可以看到证书里面主要包含以下内容:

  • Issuer:签发该证书的权威机构或组织,也是证书的信任依据。它会使用自己的私钥对证书进行数字签名,该数字签名确保了证书的完整性和真实性。
  • Subject:证书的拥有者,比如个人、组织或设备。描述了证书拥有者的身份信息,例如名称、国家/地区、电子邮件地址等。
  • Subject Public Key Info:证书的拥有者使用的公钥。
  • Signature Algorithm: 签名算法及数字签名。签发证书的权威机构根据签名算法计算整个证书的 hash 值(也就是除这块内容外的其他内容),然后使用自己的私钥对 hash 值进行加密,加密后的内容也就是数字签名,数字签名和签名算法会和证书的内容放在一起作为整个证书。当用户收到这个证书之后,它会根据权威机构的公钥对数字签名进行解密,同时使用签名算法对证书的内容进行 hash,如果这两个值对得上,说明证书是正确和完整的。
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            be:d5:2d:8b:06:bf:cf:6b
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=CN, ST=Zhejiang, L=hangzhou, O=multiparam, OU=mp, CN=name/emailAddress=dawnguo@dawnguo.com
        Validity
            Not Before: Dec 23 14:58:21 2023 GMT
            Not After : Dec 22 14:58:21 2024 GMT
        Subject: C=CN, ST=Zhejiang, L=hangzhou, O=multiparam, OU=mp, CN=name/emailAddress=dawnguo@dawnguo.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    00:c6:7a:64:51:84:47:93:c6:73:8e:07:b7:6b:e4:
                    a0:4c:d8:2c:5c:cc:d8:fc:bc:3c:94:05:ff:cb:1f:
                    54:ce:fb:0f:a5:23:d9:5d:e1:8e:6a:e6:1d:71:d2:
                    9b:59:8e:3f:5b:78:cb:a3:c7:74:bf:0e:91:e1:13:
                    a4:d3:c0:a2:31:ba:50:60:a1:8b:da:3d:f6:cb:cd:
                    91:1c:5a:8b:e1:6a:30:09:7a:57:d5:77:fa:d7:b5:
                    a4:ac:6f:23:60:1e:a9:f0:85:b9:f9:60:c9:24:e6:
                    15:46:64:ab:9e:03:3f:97:c1:7a:68:0c:09:2f:18:
                    73:6f:a4:e6:49:5d:b5:e4:19:2c:50:f4:76:a9:41:
                    1a:38:61:74:d6:bf:5a:6d:b2:2e:54:ea:02:e0:2b:
                    96:e0:20:dd:3e:bb:4a:c2:95:90:31:b6:f0:f9:2c:
                    a9:24:79:74:fd:af:c9:c1:56:41:8a:ae:f0:b2:30:
                    9e:19:b2:5d:16:c1:0b:7d:a9:cc:2e:46:32:fd:1d:
                    a3:fa:e1:69:07:45:7c:eb:b3:a8:c1:b4:98:2d:21:
                    b2:36:eb:46:75:d5:72:82:f3:25:dd:6b:e5:ea:ac:
                    a3:17:c0:32:a2:c4:74:88:29:84:76:a4:7a:f2:21:
                    54:a7:50:ae:d6:23:e6:da:91:74:36:95:ef:41:90:
                    6b:ed
                Exponent: 65537 (0x10001)
    Signature Algorithm: sha256WithRSAEncryption
         10:17:27:ea:7c:73:61:56:31:92:ba:29:2d:6b:ba:16:de:6a:
         b5:49:6b:89:6e:89:ea:8e:7d:4a:72:a4:58:90:65:12:76:6a:
         aa:0e:45:1d:8c:d7:b3:06:61:8c:93:71:e9:a8:01:e2:15:8d:
         a6:bd:ee:de:4f:05:3a:d6:ae:76:2b:dd:7d:36:44:ee:8f:c6:
         93:0b:67:9a:91:27:00:f3:20:b8:38:00:bb:a9:79:4b:aa:ab:
         db:b3:bb:cf:f0:c0:01:d4:e5:5b:be:66:b8:39:92:bb:52:92:
         6a:1e:b7:dd:c9:02:f3:3e:82:d0:c7:e7:3c:24:f7:f7:53:2e:
         88:06:77:70:cf:8d:6d:b3:f2:c0:6c:f8:0d:e9:02:c9:2f:7e:
         84:5c:b6:2a:0f:f0:cf:2d:23:c8:bc:98:92:de:2f:d9:3f:7a:
         7a:17:41:8c:38:72:c9:0f:4a:96:d1:fc:6e:4a:db:41:19:49:
         66:80:46:f8:59:12:98:3b:50:a7:04:7c:7b:c6:73:14:8c:d2:
         b5:94:60:78:70:f4:dc:2b:31:84:8b:d3:09:1a:32:45:14:39:
         df:cb:e1:e1:7c:6b:34:fd:55:60:97:73:6a:75:75:44:ce:fa:
         f7:97:0b:f1:5d:12:ef:41:f4:f0:06:6c:56:39:23:b1:e3:3f:
         41:80:d7:fd
-----BEGIN CERTIFICATE-----
MIIDjjCCAnYCCQC+1S2LBr/PazANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMC
Q04xETAPBgNVBAgMCFpoZWppYW5nMREwDwYDVQQHDAhoYW5nemhvdTETMBEGA1UE
CgwKbXVsdGlwYXJhbTELMAkGA1UECwwCbXAxDTALBgNVBAMMBG5hbWUxIjAgBgkq
hkiG9w0BCQEWE2Rhd25ndW9AZGF3bmd1by5jb20wHhcNMjMxMjIzMTQ1ODIxWhcN
MjQxMjIyMTQ1ODIxWjCBiDELMAkGA1UEBhMCQ04xETAPBgNVBAgMCFpoZWppYW5n
MREwDwYDVQQHDAhoYW5nemhvdTETMBEGA1UECgwKbXVsdGlwYXJhbTELMAkGA1UE
CwwCbXAxDTALBgNVBAMMBG5hbWUxIjAgBgkqhkiG9w0BCQEWE2Rhd25ndW9AZGF3
bmd1by5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGemRRhEeT
xnOOB7dr5KBM2CxczNj8vDyUBf/LH1TO+w+lI9ld4Y5q5h1x0ptZjj9beMujx3S/
DpHhE6TTwKIxulBgoYvaPfbLzZEcWovhajAJelfVd/rXtaSsbyNgHqnwhbn5YMkk
5hVGZKueAz+XwXpoDAkvGHNvpOZJXbXkGSxQ9HapQRo4YXTWv1ptsi5U6gLgK5bg
IN0+u0rClZAxtvD5LKkkeXT9r8nBVkGKrvCyMJ4Zsl0WwQt9qcwuRjL9HaP64WkH
RXzrs6jBtJgtIbI260Z11XKC8yXda+XqrKMXwDKixHSIKYR2pHryIVSnUK7WI+ba
kXQ2le9BkGvtAgMBAAEwDQYJKoZIhvcNAQELBQADggEBABAXJ+p8c2FWMZK6KS1r
uhbearVJa4luieqOfUpypFiQZRJ2aqoORR2M17MGYYyTcemoAeIVjaa97t5PBTrW
rnYr3X02RO6PxpMLZ5qRJwDzILg4ALupeUuqq9uzu8/wwAHU5Vu+Zrg5krtSkmoe
t93JAvM+gtDH5zwk9/dTLogGd3DPjW2z8sBs+A3pAskvfoRctioP8M8tI8i8mJLe
L9k/enoXQYw4cskPSpbR/G5K20EZSWaARvhZEpg7UKcEfHvGcxSM0rWUYHhw9Nwr
MYSL0wkaMkUUOd/L4eF8azT9VWCXc2p1dUTO+veXC/FdEu9B9PAGbFY5I7HjP0GA
1/0=
-----END CERTIFICATE-----

自签名

自签名其实就是证书颁发机构和证书拥有者是相同的,是同一个人,相当于使用自己的私钥对自己的身份信息进行签名。上述的证书例子就是自签名证书。

我们可以使用 openssl verify 命令来验证某个证书。由于证书中的数字签名往往是由别人的私钥进行加密的,因此需要由别人私钥对应公钥进行解密。然而,对于自签名来说,证书中的数字签名是由自己的私钥进行加密的,因为需要使用自己私钥对应的公钥进行解密。因此,使用 -CAfile 参数指定自己的证书,表示使用该证书中的公钥来验证。

$ openssl verify -CAfile certificate.pem certificate.pem

certificate.pem: OK

上述的验证过程,可以证明自签名证书是由证书中公钥对应的私钥拥有者发布,其实就是自己发布的,且证书中包含的信息没有被篡改过。但是,由于是自己给自己验证,证书中信息的准确性并不能保证。当我们把自签名的证书发给别人使用的时候,证书的使用者它其实并不能确保这些信息就是准确的,会出现证书使用者和证书拥有者的信任问题。

以生活中的例子为例,自签名证书就相当于一个人给自己印了一张名片,名片中写上了自己的姓名,地址,电子邮件等信息。我们把证书发给别人使用,就相当于把这个名片发给别人。但是,别人对于上述的信息是抱有疑虑的,这些信息准确吗?如果这个名片上有相应机构的认证盖章,或者别人从其他可信任的渠道得知这些信息是对的,那么就会打消你的疑虑。

对于互联网来说,有没有相应的机构来认证呢?有,这个就是证书机构。

证书机构

引入证书机构后,我们使用证书机构的私钥来对数字证书进行签名,如下图所示:

  1. 我们将自己的相关信息(数字证书)发给证书机构,证书机构使用自己的私钥(不可公开)对这个数字证书进行签名,并将签名后的内容也放到数字证书中,同时将数字证书中的 Issuer 改为证书机构自己的。

  2. 我们就拿到了证书机构给我们颁发的证书了,我们是这个证书的拥有者。当别人有需要的时候,我们就将这个证书发给他,也就是证书的使用者。

  3. 之后,证书的使用者根据 Issuer 中的相关信息,找到证书机构公开的公钥,使用该公钥验证该证书的正确性和完整性。如果验证通过,则说明该证书确实是由证书机构签名的,由于证书机构是可以信任,则表明这个证书也是可以信任的。

  4. 之后,这个证书就可以用于之后的通信传输使用。

举个例子,

  1. 我们是某个 web 网站的负责人,我们生成相应的密钥对,然后把公钥、web 网站的相关信息发给证书机构(其实可以不需要生成密钥对,我们只需要把网站的信息发给证书机构即可,证书机构可以给我们生成密钥对)。

  2. 证书机构给我们返回,它签名后的数字证书,这个数字证书我们就可以用在 SSL 中。

  3. 之后客户端发起连接请求,网站就会把这个证书返回给客户端。

  4. 客户端接下去就需要验证这个证书就可以了。那么验证证书所需要的公钥怎么来呢?权威证书机构会为自己颁发一个自签名证书,这称为证书机构的根证书(包含了证书机构的公钥)。然后操作系统和浏览器会将这些根证书内置到发布的版本中。这样,在验证用户证书时,使用内置证书中的公钥即可。有时,我们可能想使用一些未被操作系统和浏览器缺省内置的证书机构,则可以把这些证书机构的根证书手动导入到操作系统或者浏览器中。

  5. 验证成功之后,客户端就可以使用网站证书中的公钥与网站进行通信,比如他们会协商之后通信使用的密钥对等。

我们用 openssl 命令来模拟上述证书机构给申请人发布证书,以及申请人使用证书的过程,

# 1. 首先使用模拟一个证书机构,为该证书机构创建私钥和自签名的根证书。
$ openssl req -newkey rsa:2048 -nodes -keyout rootCA.key -x509 -days 365 -out rootCA.crt
Generating a 2048 bit RSA private key
....................................................................+++++
..................................................+++++
writing new private key to 'rootCA.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) []:CN
State or Province Name (full name) []:zhejiang
Locality Name (eg, city) []:hangzhou
Organization Name (eg, company) []:duocan
Organizational Unit Name (eg, section) []:yanfa
Common Name (eg, fully qualified host name) []:root
Email Address []:root@root.com

# 2. 之后创建网站的私钥和 CSR(证书签名请求),该 CSR 中包含了网站使用的私钥对应的公钥,以及网站相关信息。
$ openssl req -new -nodes -keyout dawnguo.key -out dawnguo.csr
Generating a 2048 bit RSA private key
.......................................................................................................................+++++
..........+++++
writing new private key to 'dawnguo.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) []:CN
State or Province Name (full name) []:zhejiang
Locality Name (eg, city) []:hangzhou
Organization Name (eg, company) []:dawnguo
Organizational Unit Name (eg, section) []:yanfa
Common Name (eg, fully qualified host name) []:dawnguo-wangzhan
Email Address []:******

# 3. 接着模拟证书机构使用自己的私钥、根证书和提交的网站 CSR 为网站创建数字证书。
$ openssl x509 -req -in dawnguo.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out dawnguo.crt
Signature ok
subject=/C=CN/ST=zhejiang/L=hangzhou/O=dawnguo/OU=yanfa/CN=dawnguo-wangzhan/emailAddress=dawnguo@dawnguo.cn
Getting CA Private Key

# 4. 接着网站把证书发给了用户,用户验证这个证书是否合法。这里 rootCA.crt 只是我们模拟生成的根证书,它并不存在操作系统中,因此我们需要通过 -CAfile 参数指定 root.crt,表示使用该证书来验证网站证书。当然我们也可以把 rooCA.crt 证书导入操作系统,这样不使用 -CAfile 参数也可以。
$ openssl verify -CAfile rootCA.crt dawnguo.crt
dawnguo.crt: OK

# 5. 接着网站发送了一段使用自己私钥加密的内容,给用户
$ echo "A very important business contract to Bob" > contract-content
$ openssl dgst -sha256 -sign dawnguo.key -out contract-content-sign.sha256 contract-content

# 6. 由于验证了网站的证书,我们就可以使用网站证书中的公钥对网站发送的内容进行验证,以证明该内容确实该网站发出的。
$ openssl x509 -pubkey -noout -in dawnguo.crt  > dawnguo-pub.key

$ openssl dgst -sha256 -verify dawnguo-pub.key -signature contract-content-sign.sha256 contract-content
Verified OK

接下去我们看下证书机构给我们签名的证书,可以看到 Issuer 的内容是根证书的相关信息。

$ openssl x509 -in dawnguo.crt -text
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            99:69:27:c5:b2:d8:1f:6b
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=CN, ST=zhejiang, L=hangzhou, O=duocan, OU=yanfa, CN=root/emailAddress=root@root.com

证书链

上述模拟直接使用根证书机构的私钥进行签发,但是实际上一般不会使用根证书机构的私钥签发用户证书,主要原因是根证书机构的私钥非常重要,如果直接使用根证书机构的私钥进行签名的话,一旦私钥泄露了,会影响该私钥签发的所有证书。为此,证书机构引入了中间证书(intermediate certificate),证书机构会采用根证书的私钥来签发中间证书,然后使用中间证书来签发其他用户证书。当然中间证书可以有多个层级,这样就形成了一个证书链。

下面以三层证书链的生成和验证来进行说明,

  • 证书生成和使用过程

    1. 证书机构先生成自签名根证书;
    2. 证书机构再采用根证书对应的私钥签名中间证书;
    3. 证书机构再采用中间证书对应的私钥签名网站证书;
    4. 最后网站使用网站证书对应的私钥签名网站数据。
  • 证书使用时的验证过程

    • 用户拿到网站证书,发现网站证书上的签名机构(Issuer)是中间证书,会先使用中间证书中的公钥验证网站证书;
    • 验证的时候发现中间证书也需要验证,这个时候会使用根证书中的公钥验证中间证书的签名;
    • 由于自签名根证书已经内置在操作系统中,属于系统信任的根证书,到达根证书时就验证完毕;
    • 网站证书和中间证书都验证通过了,说明网站证书是可信的。接着用户就可以拿着网站证书中的公钥来和完整进行通信了。

下面用 openssl 来模拟上述三层的证书链,

# 1. 首先使用模拟一个证书机构,为该证书机构创建私钥和自签名的根证书。
$ openssl req -newkey rsa:2048 -nodes -keyout rootCA.key -x509 -days 365 -out rootCA.crt
Generating a 2048 bit RSA private key
.................................................................................................................................................................................................................................................................................................................+++++
..........+++++
writing new private key to 'rootCA.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) []:CN
State or Province Name (full name) []:root
Locality Name (eg, city) []:root
Organization Name (eg, company) []:root
Organizational Unit Name (eg, section) []:root
Common Name (eg, fully qualified host name) []:root
Email Address []:root@root.com

# 2. 生成中间证书的私钥和 CSR。
$ openssl req -new -nodes -keyout intermediate.key -out intermediate.csr

Generating a 2048 bit RSA private key
.........................+++++
.......................................................+++++
writing new private key to 'intermediate-1.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) []:CN
State or Province Name (full name) []:inter
Locality Name (eg, city) []:inter
Organization Name (eg, company) []:inter
Organizational Unit Name (eg, section) []:inter
Common Name (eg, fully qualified host name) []:inter
Email Address []:inter@inter.com

# 3.1 和用户证书不同的是,中间证书需要在证书的 basicConstraints 中设置 CA:true 标签,以标明该证书属于证书机构的证书,可以用于签发和验证用户证书。而 openssl x509 命令不能设置 basicConstraints 命令,因此我们需要采用 openssl ca 命令,该命令实现了一个简单的证书机构。
# openssl ca 命令需要采用一个配置文件来配置生成证书的相关参数。我们创建一个 intermediateCA.conf 文件,其内容如下:
[ ca ]
default_ca = intermediate_ca
[ intermediate_ca ]
dir = .
private_key = $dir/rootCA.key
certificate = $dir/rootCA.crt
new_certs_dir = $dir/
serial = $dir/crt.srl
database = $dir/db/index
default_md = sha256
policy = policy_any
email_in_dn = no
[ policy_any ]
domainComponent = optional
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = optional
emailAddress = optional
[ ca_ext ]
keyUsage                = critical,keyCertSign,cRLSign
basicConstraints        = critical,CA:true
subjectKeyIdentifier    = hash
authorityKeyIdentifier  = keyid:always

# 3.2 由于 openssl ca 命令实现了一个简单的证书机构,会使用一个文本数据库来记录生成的证书,我们需要生成该数据库索引文件。
$ mkdir db
$ touch db/index

# 4. 生成中间证书
$ openssl ca -config intermediateCA.conf -days 365 -create_serial -in intermediate.csr -out intermediate.crt -extensions ca_ext -notext

# 5. 使用中间证书生成网站证书
$ openssl req -new -nodes -keyout dawnguo.key -out dawnguo.csr
$ openssl x509 -req -in dawnguo.csr -CA intermediate.crt -CAkey intermediate.key -CAcreateserial -out dawnguo.crt

# 6. 网站证书发给用户,用户验证该网站证书
$ openssl verify -CAfile rootCA.crt -untrusted intermediate.crt dawnguo.crt
dawnguo.crt: OK

相关链接

数字证书原理:https://www.zhaohuabing.com/post/2020-03-19-pki/

wiki-X.509:https://en.wikipedia.org/wiki/X.509

SSL证书原理讲解:https://www.cnblogs.com/dinglin1/p/9279831.html

解析SSL单向认证和双向认证:https://zhuanlan.zhihu.com/p/330393659

卷死我
dawnguo 微信支付

微信支付

dawnguo 支付宝

支付宝

  • 本文作者: dawnguo
  • 本文链接: /archives/236
  • 版权声明: 本博客所有文章除特别声明外,均采用CC BY-NC-SA 3.0 许可协议。转载请注明出处!
# 基础知识
Kubernetes 客户端-Informer 机制
Kubernetes CNI 基础知识
  • 文章目录
  • 站点概览
dawnguo

dawnguo

215 日志
24 分类
37 标签
RSS
Creative Commons
© 2018 — 2025 程序锅
0%