在【第8章X.509证书和PKI】中,我们学习了基于X.509证书的 公钥基础设施(Public Key Infrastructure,PKI)。在本章中,我们将学习如何使用 openssl ca
子命令运行一个迷你 证书颁发机构(Certificate Authority,ca),该机构可以颁发证书供组织内部使用。小型CA在组织中非常有用,可以建立内部PKI,控制内部使用的证书,并节省从商业CA订购证书的成本。迷你CA的使用将通过命令行示例进行说明。
第十二章 运行一个Mini-CA技术要求了解 openssl ca
子命令生成根CA证书生成中间CA证书为web服务器生成证书为web和电子邮件客户端生成证书撤销证书并生成CRL通过OCSP提供证书吊销状态总结
本章将包含可以在命令行上运行的命令。您将需要 openssl
命令行工具和openssl动态库。
在本章中,我们将使用许多配置文件和命令。这些配置文件和命令保存为Shell脚本,可以在这里找到:
https://github.com/PacktPublishing/Demystifying-Cryptography-with-OpenSSL-3/tree/main/Chapter12
openssl ca
子命令openssl ca
子命令对于在组织内运行迷你CA非常有用。例如,这种CA可以为内部服务器颁发证书。与使用外部商业CA相比,使用内部CA可以节省成本。但这并不是唯一的优势。许多内部服务器不应暴露在互联网的访问范围内。这种限制阻碍了来自外部CA的自动服务器检查,而这些CA是颁发廉价或免费证书所必需的。此外,在某些情况下,不希望公开有关内部服务器的存在或名称的知识。从外部CA订购证书时,您必须向CA公开内部服务器的名称。此外,CA可能会将证书信息发布到证书透明度(Certificate Transparency,CT)日志中,从而导致有关公司内部服务器的更多不必要的信息暴露。
拥有内部CA的另一个原因是颁发客户端证书。在公共互联网web服务器上使用内部CA颁发的证书并不十分方便,因为该web服务器的每个用户都必须将内部CA证书安装到其浏览器的受信任存储中。但是,由内部CA颁发的客户端证书没有这个缺点,因为这样的证书通常只用于对少数服务器进行身份验证。
在某些组织中,与使用外部CA相比,将内部CA用于内部目的可以提供一定程度的自由。例如,您可能需要安全团队的批准才能获得外部证书,或者需要会计经理的批准才能获取付费证书。有了内部CA,您可以自由地为您的内部需求颁发证书,而无需任何批准。
openssl ca
子命令可以从命令行和OpenSSL配置文件中获取其工作参数。OpenSSL配置文件可以存储OpenSSL库和实用程序的各种选项。默认的OpenSSL配置文件在OpenSSL发行版中以 apps/openssl.cnf 文件的形式提供。在OpenSSL安装过程中,默认配置文件将安装到ssl目录中,例如 /opt/openssl-3.0.0/ssl/openssl.cnf 或 /etc/ssl/opensl.cnf 。对于 openssl ca
操作,通常会创建一个表示特定CA的自定义配置文件,如根CA或中间CA,而不是使用默认的OpenSSL配置文件。
最好在配置文件中为 openssl ca
子命令指定大多数参数,以避免在颁发不同证书时在命令行上重复这些参数。此外,有些参数只能在配置文件中指定。如果配置文件和命令行中提供了相同的参数,则命令行参数优先。
有关 openssl ca
参数和配置文件的文档可以在以下手册页上找到:
$ man openssl-ca
$ man 5ssl config
$ man x509v3_config
除了配置文件,openssl ca
还使用其他强制或可选文件,如证书索引文件、序列号文件、随机种子文件和CRL编号文件。
openssl ca
子命令可以颁发证书、吊销证书和生成 证书吊销列表(Certificate Revocation Lists,CRL)。在颁发或吊销证书时, openssl ca
会更新证书索引文件,也称为证书数据库。
openssl ca
可以颁发具有顺序或随机序列号的证书。如果使用连续序列号,则下一个序列号将存储并自动更新在序列号文件中。但是,出于安全原因,最好使用随机序列号颁发证书。
CRL可以在有或没有 CRL number 的情况下生成。CRL编号基本上就是CRL版本。它是一个正整数,每次CA发布下一个完整CRL时都会递增1。最好在CRL中包含一个CRL编号,因为它有助于检查CRL发布的连续性,并使生成 增量CRLs (delta CRLs)成为可能。增量CRL是一种仅包含自普通完整CRL特定版本以来的更改的CRL。增量CRL所基于的完整CRL称为 基础CRL(base CRL)。但是, openssl ca
尚不支持增量CRL——如果要生成增量CRL,您需要使用其他工具。如果生成带有CRL编号的CRL,该编号将存储在CRL编号文件中,并由 openssl ca
自动更新。
让我们学习如何使用 openssl ca
子命令。我们将从生成根CA证书开始。
我们将创建一些所需的目录和文件,然后继续生成根CA证书:
首先,我们将创建一个 mini-ca 目录,在其中放置所有与CA相关的文件:
xxxxxxxxxx
$ mkdir mini-ca
$ cd mini-ca
在 mini-ca 目录中,我们将为与根CA相关的文件创建根目录:
xxxxxxxxxx
$ mkdir root
$ cd root
在 root 目录中,我们将为已颁发的证书创建一个目录、一个证书索引文件和一个CRL编号文件:
xxxxxxxxxx
$ mkdir issued
$ echo -n >index.txt
$ echo 01 >crlnumber.txt
现在,我们必须为根CA创建一个配置文件;我们将此文件命名为 root.cnf 。我们将使用一些强制参数启动配置文件:
xxxxxxxxxx
[ca]
default_ca = CA_default
[CA_default]
database = index.txt
new_certs_dir = issued
certificate = root_cert.pem
private_key = private/root_keypair.pem
数据库参数指定证书索引文件,也称为证书数据库。它是一个文本文件,其中每一行都包含有关一个证书的信息。 new_certs_dir
参数指定将写入新颁发证书的目录。 certificate
和 private_key
参数指定了当前CA(在我们的例子中是根CA)的证书和相应的私钥。
接下来,我们将定义一些可选参数。我们的根CA将只颁发中间CA证书;因此,我们可以将默认颁发的证书有效期设置为10年:
xxxxxxxxxx
default_days = 3650
以下参数设置用于对根CA颁发的证书进行签名的消息摘要算法。 default_md
参数有一个特殊的 default
。这意味着在签名证书中使用的相同消息摘要算法将在签名的证书中使用。例如,如果使用SHA-256哈希函数本身对签名证书进行签名,则颁发的证书也将使用SHA-256散列函数进行签名。在我们的例子中,此参数不会产生任何影响,因为ED448证书在签署其他证书时始终使用SHAKE256消息摘要算法。我们将在这里包含此参数,只是为了演示 openssl ca
子命令的功能:
xxxxxxxxxx
default_md = default
下一个参数指示 openssl ca
使用随机序列号而不是顺序序列号颁发证书:
xxxxxxxxxx
rand_serial = yes
后续参数允许我们颁发具有相同主题的多个证书。它可用于替换过期的证书:
xxxxxxxxxx
unique_subject = no
接下来的参数控制在签名之前如何显示证书详细信息。OpenSSL文档建议设置这些参数,否则将使用旧的损坏的显示格式:
xxxxxxxxxx
name_opt = ca_default
cert_opt = ca_default
以下参数是必需的,指定了定义默认颁发证书的主题策略的配置部分。当我们谈到本节时,我们将更仔细地审查它:
xxxxxxxxxx
policy = policy_intermediate_cert
下一个参数指定默认的X509v3扩展部分:
xxxxxxxxxx
x509_extensions = v3_intermediate_cert
下一个参数指示OpenSSL从 证书签名请求(Certificate Signing Request,CSR)中复制X509v3扩展,这些扩展不是由CA添加到颁发的证书中的。选择性复制允许CSR提供有用的X509v3扩展,如 subjectAltName ,但禁止覆盖CA设置的重要扩展,如 basicConstraints 或 keyUsage :
xxxxxxxxxx
copy_extensions = copy
接下来的参数与CRL相关。他们使用CRL扩展名、CRL编号文件和已发布CRL的默认有效性设置默认配置部分:
xxxxxxxxxx
crl_extensions = crl_extensions_root_ca
crlnumber = crlnumber.txt
default_crl_days = 30
当使用此配置文件进行CSR时,以下参数定义了CSR的默认Subject和X509v3扩展名。使用此配置文件创建的唯一CSR应该是根CA证书的CSR。因此,在配置文件中定义根CA证书的Subject和X509v3扩展名很方便,既可以生成CSR,也可以生成根CA证书。在配置文件中包含证书数据也有助于提醒使用哪个CA证书:
xxxxxxxxxx
[req]
prompt = no
distinguished_name = distinguished_name_root_cert
x509_extensions = v3_root_cert
[distinguished_name_root_cert]
countryName = NO
stateOrProvinceName = Oslo
localityName = Oslo
organizationName = TLS Experts
commonName = Root CA
下一个配置部分定义了默认颁发证书的主题策略:
xxxxxxxxxx
[policy_intermediate_cert]
countryName = match
stateOrProvinceName = match
localityName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
根据定义的策略,我们要求颁发的中间CA证书的主题与根CA证书的主体具有相同的地理位置和组织。这是有道理的,因为我们在一个组织内运行一个迷你CA。
接下来的配置部分定义了根CA证书和颁发的中间CA证书的X509v3扩展。可以使用 -extensions
命令行开关选择所需的部分:
x[v3_root_cert]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer
basicConstraints = critical, CA:TRUE
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
crlDistributionPoints = URI:http://crl.tls-experts.no/root_crl.der
[v3_intermediate_cert]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer
basicConstraints = critical, CA:TRUE, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
crlDistributionPoints = URI:http://crl.tls-experts.no/root_crl.der
最后一个配置部分定义了将添加到已发布CRL中的CRL扩展:
xxxxxxxxxx
[crl_extensions_root_ca]
authorityKeyIdentifier = keyid:always, issuer
crlDistributionPoints = URI:http://crl.tls-experts.no/root_crl.der
完整的根CA配置文件可以在GitHub上找到 root.cnf 文件:https://github.com/PacktPublishing/Demystifying-Cryptography-with-OpenSSL-3/blob/main/Chapter12/mini-ca/root/root.cnf 。
我们的根CA配置文件已准备就绪。让我们继续下一步,即生成根CA密钥对:
xxxxxxxxxx
$ mkdir private
$ chmod 0700 private
$ openssl genpkey \
-algorithm ED448 \
-out private/root_keypair.pem
下一步是生成根CA CSR:
xxxxxxxxxx
$ openssl req \
-config root.cnf \
-new \
-key private/root_keypair.pem \
-out root_csr.pem \
-text
请注意,我们没有在命令行上提供根证书的主题。 openssl req
子命令将从 root.cnf 配置文件中,即从 req
和 distinguished_name_root_cert
部分中找出Subject。
CSR准备就绪后,我们可以颁发根CA证书:
xxxxxxxxxx
$ openssl ca \
-config root.cnf \
-extensions v3_root_cert \
-selfsign \
-in root_csr.pem \
-out root_cert.pem
Using configuration from root.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number:
... (long hex number) ...
Validity
Not Before: Jul 18 18:54:11 2022 GMT
Not After : Jul 15 18:54:11 2032 GMT
Subject:
countryName = NO
stateOrProvinceName = Oslo
localityName = Oslo
organizationName = TLS Experts
commonName = Root CA
X509v3 extensions:
X509v3 Subject Key Identifier:
... (long hex number) ...
X509v3 Authority Key Identifier:
... (long hex number) ...
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Key Usage: critical
Digital Signature, Certificate Sign, CRL Sign
X509v3 CRL Distribution Points:
Full Name:
URI:http://crl.tls-experts.no/root_crl.der
Certificate is to be certified until Jul 15 18:54:11 2032 GMT (3650 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
请注意,我们使用了 openssl ca
子命令而不是 openssl x509
来颁发证书。此外,请注意,我们在配置文件中而不是在命令行中提供了大部分参数。我们没有在命令行上提供私钥、持续时间或X509v3扩展名——它们都是从配置文件中获取的。我们使用了 -selfsigned
开关来指示 openssl ca
颁发自签名的根CA证书。在颁发其他证书时,我们不会使用该开关。
颁发证书后, openssl ca
将颁发证书的副本保存在 issued 目录中(由配置中的 new_certs_dir
参数指定),并更新证书索引文件(由配置的数据库参数指定)。
我们已成功生成根CA证书。在下一节中,我们将了解如何生成中间CA证书。
生成中间CA证书类似于生成根CA证书。我们将为中间CA使用另一个目录;让我们称此目录为 intermediate ,并将其放置在 mini-ca 目录中与 root目录相同的级别:
让我们创建 intermediate 目录,并使用所需的文件和子目录对其进行初始化:
xxxxxxxxxx
$ cd mini-ca
$ mkdir intermediate
$ cd intermediate
$ mkdir issued
$ echo -n >index.txt
$ echo 01 >crlnumber.txt
现在,我们必须为中间CA创建一个配置文件;我们将此文件命名为 intermediate.cnf 。中间CA的配置文件将与根CA类似。我们将使用与根CA配置中相同的参数启动配置文件:
xxxxxxxxxx
[ca]
default_ca = CA_default
[CA_default]
database = index.txt
new_certs_dir = issued
certificate = intermediate_cert.pem
private_key = private/intermediate_keypair.pem
default_days = 365
default_md = default
rand_serial = yes
unique_subject = no
name_opt = ca_default
cert_opt = ca_default
policy = policy_server_cert
x509_extensions = v3_server_cert
copy_extensions = copy
crl_extensions = crl_extensions_intermediate_ca
crlnumber = crlnumber.txt
default_crl_days = 30
请注意,此配置文件中的 default_days
参数低于根CA配置文件中相同的参数。这是因为我们的中间CA将颁发叶子证书,这些证书的生命周期通常比根证书或中间CA证书短。
我们将使用有助于构建中间CA证书主题的参数继续配置文件:
xxxxxxxxxx
[req]
prompt = no
distinguished_name = distinguished_name_intermediate_cert
[distinguished_name_intermediate_cert]
countryName = NO
stateOrProvinceName = Oslo
localityName = Oslo
organizationName = TLS Experts
commonName = Intermediate CA
我们的中间CA将颁发服务器和客户端证书。因此,我们需要为这些类别的证书定义主题策略:
xxxxxxxxxx
[policy_server_cert]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[policy_client_cert]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = supplied
正如您所观察到的,中间CA配置中定义的策略比根CA配置中的策略更宽松。这是因为我们可能希望向组织外部的实体(例如客户或合作伙伴)颁发证书,并且因为在我们的演示中有一些变化是很好的。
中间CA配置中的下一节定义了X509v3扩展,这些扩展将添加到不同类型的已颁发证书中,如服务器证书、客户端证书和 在线证书状态协议(Online Certificate Status Protocol,OCSP)响应者的证书:
xxxxxxxxxx
[v3_server_cert]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer
basicConstraints = critical, CA:FALSE
nsCertType = server
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
crlDistributionPoints = URI:http://crl.tls-experts.no/intermediate_crl.der
authorityInfoAccess = OCSP;URI:http://ocsp.tls-experts.no/
[v3_client_cert]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer
basicConstraints = critical, CA:FALSE
nsCertType = client, email
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
crlDistributionPoints = URI:http://crl.tls-experts.no/intermediate_crl.der
authorityInfoAccess = OCSP;URI:http://ocsp.tls-experts.no/
[v3_ocsp_cert]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer
basicConstraints = critical, CA:FALSE
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning
crlDistributionPoints = URI:http://crl.tls-experts.no/intermediate_crl.der
authorityInfoAccess = OCSP;URI:http://ocsp.tls-experts.no/
配置文件的最后一节定义了将添加到已发布的CRL中的扩展名:
xxxxxxxxxx
[crl_extensions_intermediate_ca]
authorityKeyIdentifier = keyid:always, issuer
crlDistributionPoints = URI:http://crl.tls-experts.no/intermediate_crl.der
authorityInfoAccess = OCSP;URI:http://ocsp.tls-experts.no/
完整的中间CA配置文件可以在GitHub上找到intermediate.cnf文件:https://github.com/PacktPublishing/Demystifying-Cryptography-with-OpenSSL-3/blob/main/Chapter12/mini-ca/intermediate/intermediate.cnf 。
我们的中间CA配置文件已经准备就绪。现在,让我们生成 intermediate
CA密钥对和CSR:
xxxxxxxxxx
$ mkdir private
$ chmod 0700 private
$ openssl genpkey \
-algorithm ED448 \
-out private/intermediate_keypair.pem
接下来,生成中间CA CSR:
xxxxxxxxxx
$ openssl req \
-config intermediate.cnf \
-new \
-key private/intermediate_keypair.pem \
-out intermediate_csr.pem \
-text
与根CA证书一样,我们从配置文件而不是命令行提供了证书主题组件。
下一步是颁发中间CA证书,但必须由根CA颁发。因此,我们将从 root 目录颁发:
xxxxxxxxxx
$ cd ../root/
$ openssl ca \
-config root.cnf \
-extensions v3_intermediate_cert \
-in ../intermediate/intermediate_csr.pem \
-out ../intermediate/intermediate_cert.pem
Using configuration from root.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
…
Certificate is to be certified until Jul 15 18:55:11 2032 GMT (3650 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
请注意,这次我们使用了 root.cnf 文件的 v3_intermediate_cert
部分的X509v3扩展,这与上次不同,上次我们使用 v3_root_cert
部分作为根CA证书。
我们现在已经生成了中间CA证书。在下一节中,我们将使用它来颁发叶子证书。
我们将生成的下一个证书是web服务器的证书。对于之前的证书,我们将为此证书创建一个单独的目录和一个配置文件:
但是,由于我们将颁发叶子证书,因此不需要在其目录中创建与CA相关的文件。我们只需要创建目录并在那里更改当前目录:
xxxxxxxxxx
$ cd mini-ca
$ mkdir server
$ cd server
服务器证书配置文件将比之前制作的CA证书配置文件短得多:
xxxxxxxxxx
[req]
prompt = no
distinguished_name = distinguished_name_server_cert
req_extensions = v3_server_cert
[distinguished_name_server_cert]
countryName = NO
stateOrProvinceName = Oslo
localityName = Oslo
organizationName = TLS Experts
commonName = internal.tls-experts.no
[v3_server_cert]
subjectAltName = DNS:mirror1.tls-experts.no, DNS:mirror2.tls-experts.no
正如您所看到的,这次我们定义了一个X509v3扩展名 subjectAltNames
,它将被添加到CSR中。我们为扩展名提供了几个值,并用逗号分隔它们。还有另一种提供多个值的方法——通过在单独的行上为每个值制作一个单独的配置部分。稍后我们将在创建客户端证书时审查该方法。中间CA配置中不存在上述扩展,并且中间CA配置包含 copy_extensions=copy
选项。因此,CSR中的X509v3扩展将与中间CA配置文件中定义的其他扩展一起复制到生成的证书中。当然,在颁发证书时,我们将能够查看证书详细信息并查看所有包含的X509v3扩展。
下一步是为我们的服务器证书生成一个密钥对和一个CSR:
xxxxxxxxxx
$ mkdir private
$ chmod 0700 private
$ openssl genpkey \
-algorithm ED448 \
-out private/server_keypair.pem
$ openssl req \
-config server.cnf \
-new \
-key private/server_keypair.pem \
-out server_csr.pem \
-text
请注意,我们不必在命令行上提供 -reqexts v3_server_cert
选项,因为 v3_server_cert
是默认的扩展部分,由配置文件中的 req_extensions=v3_server_cert
选项指定。
现在,是时候生成我们的服务器证书了。由于它将由中间CA发出,我们将从 intermediate 目录运行 openssl ca
子命令:
xxxxxxxxxx
$ cd ../intermediate/
$ openssl ca \
-config intermediate.cnf \
-in ../server/server_csr.pem \
-out ../server/server_cert.pem
Using configuration from intermediate.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
…
Certificate is to be certified until Jul 19 15:36:44 2023 GMT (365 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
看看证书颁发命令有多简单!只有三步。所有其他参数都来自配置,包括默认策略和X509v3扩展。在配置文件中配置了所有内容后,我们可以使用这样一个简单的命令轻松颁发服务器证书。
颁发客户端证书有点不同,但也不是很困难。我们将在下一节中学习如何做到这一点。
生成客户端证书类似于生成服务器证书:
像往常一样,我们将为此证书创建一个单独的目录,并在那里更改我们当前的目录:
xxxxxxxxxx
$ cd mini-ca
$ mkdir client
$ cd client
我们将使用保存在 client.cnf 文件中的以下配置来生成客户端证书:
xxxxxxxxxx
[req]
prompt = no
distinguished_name = distinguished_name_client_cert
req_extensions = v3_client_cert
[distinguished_name_client_cert]
countryName = NO
stateOrProvinceName = Oslo
localityName = Oslo
organizationName = TLS Experts
commonName = Thor Odinson
emailAddress = thor@tls-experts.no
[v3_client_cert]
subjectAltName = @subject_alt_names
[subject_alt_names]
email.1 = postmaster@tls-experts.no
email.2 = hostmaster@tls-experts.no
与上次一样,我们使用具有多个值的 subjectAltName
扩展,但现在我们使用单独的配置部分提供了多个值。
让我们生成证书密钥对和CSR:
xxxxxxxxxx
$ mkdir private
$ chmod 0700 private
$ openssl genpkey \
-algorithm ED448 \
-out private/client_keypair.pem
$ openssl req \
-config client.cnf \
-new \
-key private/client_keypair.pem \
-out client_csr.pem \
-text
下一步是颁发客户端证书:
xxxxxxxxxx
$ cd ../intermediate/
$ openssl ca \
-config intermediate.cnf \
-policy policy_client_cert \
-extensions v3_client_cert \
-in ../client/client_csr.pem \
-out ../client/client_cert.pem
Using configuration from intermediate.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
…
Certificate is to be certified until Jul 19 15:37:44 2023 GMT (365 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
对于客户端证书,颁发命令比服务器证书稍长,因为我们必须提供 -policy
和 -extensions
开关。默认策略和扩展部分是为服务器证书保留的,因为它们的颁发频率高于客户端证书。但是,如果您的组织中没有这种情况,您可以很好地使用客户端策略和扩展部分作为默认值。
在制作客户端证书时,另一件有用的事情是将证书、其私钥和验证链打包到 公钥加密标准#12(Public Key Cryptography Standards #12,PKCS#12)容器中:
xxxxxxxxxx
$ cd ../client/
$ cat \
../intermediate/intermediate_cert.pem \
../root/root_cert.pem \
>certfile.pem
$ openssl pkcs12 \
-export \
-inkey private/client_keypair.pem \
-in client_cert.pem \
-certfile certfile.pem \
-passout 'pass:SuperPa$$w0rd' \
-out client_cert.p12
正如我们所看到的,使用 openssl ca
颁发证书相当容易。但是,我们如何撤销证书并生成CRL呢?让我们在下一节中了解一下。
在吊销证书之前,我们必须先颁发证书。让我们发布一个示例证书,类似于我们之前的做法:
像往常一样,第一步是为证书文件创建一个目录:
xxxxxxxxxx
$ cd mini-ca
$ mkdir server2
$ cd server2
接下来,进行以下证书配置并将其保存到 server2.cnf 文件中:
xxxxxxxxxx
[req]
prompt = no
distinguished_name = distinguished_name_server_cert
[distinguished_name_server_cert]
countryName = NO
stateOrProvinceName = Oslo
localityName = Oslo
organizationName = TLS Experts
commonName = server2.tls-experts.no
接下来,制作密钥对CSR,并颁发证书:
xxxxxxxxxx
$ mkdir private
$ chmod 0700 private
$ openssl genpkey \
-algorithm ED448 \
-out private/server2_keypair.pem
$ openssl req \
-config server2.cnf \
-new \
-key private/server2_keypair.pem \
-out server2_csr.pem \
-text
$ cd ../intermediate/
$ openssl ca \
-config intermediate.cnf \
-in ../server2/server2_csr.pem \
-out ../server2/server2_cert.pem
Using configuration from intermediate.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
…
Certificate is to be certified until Jul 19 15:38:44 2023 GMT (365 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
我们刚刚生成了一个新证书。我们仍在 intermediate 目录中。让我们在 server2
证书尚未被吊销时生成一个CRL。
以下是我们为中间CA生成CRL的方法:
xxxxxxxxxx
$ openssl ca \
-config intermediate.cnf \
-gencrl \
-out intermediate_crl.pem
让我们以文本形式查看生成的CRL:
xxxxxxxxxx
$ openssl crl \
-in intermediate_crl.pem \
-noout \
-text
Certificate Revocation List (CRL):
Version 2 (0x1)
Signature Algorithm: ED448
Issuer: C = NO, ST = Oslo, L = Oslo, O = TLS Experts, CN = Intermediate CA
Last Update: Jul 19 16:56:47 2022 GMT
Next Update: Aug 18 16:56:47 2022 GMT
CRL extensions:
X509v3 Authority Key Identifier:
... (hex values) …
X509v3 CRL Distribution Points:
Full Name:
URI:http://crl.tls-experts.no/intermediate_crl.der
Authority Information Access:
OCSP - URI:http://ocsp.tls-experts.no/
X509v3 CRL Number:
1
No Revoked Certificates.
Signature Algorithm: ED448
Signature Value:
... (hex values) ...
我们刚刚生成了第一个CRL, X509v3 CRL Number
值为 1
。此编号取自 crlnumber.txt 文件,该文件由中间CA配置文件中的 crlnumber = crlnumber.txt
行配置。该文件包含下一个十六进制的CRL编号。CRL发出后,openssl ca
会将该文件中的数字递增1。
正如我们所看到的,CRL声明没有证书被吊销。让我们撤销 server2
证书并重新生成CRL。
这就是我们撤销证书的方式:
xxxxxxxxxx
$ openssl ca \
-config intermediate.cnf \
-revoke ../server2/server2_cert.pem \
-crl_reason keyCompromise
Using configuration from intermediate.cnf
Revoking Certificate 1651F3139172DEE541B914DFCB371D8E11BA209F.
Data Base Updated
吊销信息保存在证书索引文件 index.txt 中。该文件中的证书状态已从V
(valid,有效)更改为 R
(revoked,已吊销)。
证书被吊销后,我们必须重新生成CRL:
xxxxxxxxxx
$ openssl ca \
-config intermediate.cnf \
-gencrl \
-out intermediate_crl.pem
让我们检查更新的CRL:
xxxxxxxxxx
$ openssl crl \
-in intermediate_crl.pem \
-noout \
-text
Certificate Revocation List (CRL):
Version 2 (0x1)
Signature Algorithm: ED448
Issuer: C = NO, ST = Oslo, L = Oslo, O = TLS Experts, CN = Intermediate CA
Last Update: Jul 19 17:43:49 2022 GMT
Next Update: Aug 18 17:43:49 2022 GMT
CRL extensions:
X509v3 Authority Key Identifier:
... (hex values) …
X509v3 CRL Distribution Points:
Full Name:
URI:http://crl.tls-experts.no/intermediate_crl.der
Authority Information Access:
OCSP - URI:http://ocsp.tls-experts.no/
X509v3 CRL Number:
2
Revoked Certificates:
Serial Number: 1651F3139172DEE541B914DFCB371D8E11BA209F
Revocation Date: Jul 19 17:41:39 2022 GMT
CRL entry extensions:
X509v3 CRL Reason Code:
Key Compromise
Signature Algorithm: ED448
Signature Value:
... (hex values) ...
正如我们所观察到的,现在 X509v3 CRL Number
值为 2
,CRL包含一个已吊销的证书。我们可以得出结论,证书的撤销和CRL的生成按预期工作。
另一件有用的事情是将发布的CRL从 隐私增强邮件(Privacy-Enhanced Mail,PEM)格式转换为 可分辨编码规则(Distinguished Encoding Rules,DER)格式,因为CRL分发点通常以 DER
格式提供CRL:
xxxxxxxxxx
$ openssl crl \
-in intermediate_crl.pem \
-out intermediate_crl.der \
-outform DER
我们现在已经学习了如何吊销证书和生成CRL。众所周知,提供CRL并不是提供证书吊销信息的唯一方法。另一种方法是OCSP。让我们在下一节中了解更多关于OCSP的信息。
为了提供OCSP响应,我们必须对其进行签名。证书的OCSP响应可以由其颁发者证书签名。同一颁发者还可以颁发另一个证书来签署OCSP请求。该证书必须在X509v3 extendedKeyUsage
扩展中包含 OCSPSigning
。
当我们创建中间CA配置文件时,我们包含了以下X509v3扩展部分:
xxxxxxxxxx
[v3_ocsp_cert]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer
basicConstraints = critical, CA:FALSE
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning
crlDistributionPoints = URI:http://crl.tls-experts.no/intermediate_crl.der
authorityInfoAccess = OCSP;URI:http://ocsp.tls-experts.no/
像往常一样,我们将从准备目录开始:
xxxxxxxxxx
$ cd mini-ca
$ mkdir ocsp
$ cd ocsp
然后,我们将对OCSP响应者证书进行配置,并将其保存到 ocsp.cnf 文件中:
xxxxxxxxxx
[req]
prompt = no
distinguished_name = distinguished_name_ocsp_cert
[distinguished_name_ocsp_cert]
countryName = NO
stateOrProvinceName = Oslo
localityName = Oslo
organizationName = TLS Experts
commonName = OCSP Responder
使用保存的配置,我们将创建OCSP响应者证书:
xxxxxxxxxx
$ mkdir private
$ chmod 0700 private
$ openssl genpkey \
-algorithm ED448 \
-out private/ocsp_keypair.pem
$ openssl req \
-config ocsp.cnf \
-new \
-key private/ocsp_keypair.pem \
-out ocsp_csr.pem \
-text
$ cd ../intermediate/
$ openssl ca \
-config intermediate.cnf \
-in ../ocsp/ocsp_csr.pem \
-out ../ocsp/ocsp_cert.pem
Using configuration from intermediate.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
…
Certificate is to be certified until Jul 19 17:45:44 2023 GMT (365 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
生成的证书可供OCSP响应者使用。让我们测试一下。 openssl
实用程序包括 openssl ocsp
子命令,它可以充当简单的OCSP服务器。我们可以使用这样的OCSP服务器进行测试。OCSP服务器直接从证书索引文件 index.txt 中获取证书有效性数据。如果你问我,这对测试来说非常实用。
您可以在其手册页上阅读 openssl ocsp
文档:
xxxxxxxxxx
$ man openssl-ocsp
我们将从OCSP目录启动测试OCSP服务器:
xxxxxxxxxx
$ cd ../ocsp/
$ openssl ocsp \
-port 4480 \
-index ../intermediate/index.txt \
-CA ../intermediate/intermediate_cert.pem \
-rkey private/ocsp_keypair.pem \
-rsigner ocsp_cert.pem
ACCEPT 0.0.0.0:4480 PID=124271
ocsp: waiting for OCSP client connections...
我们已将OCSP响应者证书及其私钥提供给 openssl ocsp
,用于对OCSP响应进行签名。
但是 openssl ocsp
子命令非常好,它不仅可以充当OCSP服务器,还可以充当OCAP客户端。让我们在客户端模式下使用它,并检查我们最近颁发的 server
证书的有效性。为此,我们需要打开另一个终端窗口,切换到 mini-ca/ocsp 目录,并运行以下命令:
xxxxxxxxxx
openssl ocsp \
-url http://localhost:4480 \
-sha256 \
-CAfile ../root/root_cert.pem \
-issuer ../intermediate/intermediate_cert.pem \
-cert ../server/server_cert.pem
Response verify OK
../server/server_cert.pem: good
This Update: Jul 19 19:59:06 2022 GMT
正如我们所观察到的,OCSP服务器已经确认了 server
证书的有效性。
现在,让我们检查最近颁发和吊销的server2证书的状态:
xxxxxxxxxx
$ openssl ocsp \
-url http://localhost:4480 \
-sha256 \
-CAfile ../root/root_cert.pem \
-issuer ../intermediate/intermediate_cert.pem \
-cert ../server2/server2_cert.pem
Response verify OK
../server2/server2_cert.pem: revoked
This Update: Jul 19 20:03:56 2022 GMT
Reason: keyCompromise
Revocation Time: Jul 19 17:41:39 2022 GMT
正如我们所看到的,OCSP响应者报告说,正如我们所料,server2
证书已被吊销。我们可以得出结论,我们的OCSP设置工作正常。
我们现在已经学习了很多关于运行 mini-CA 的知识。我们使用了许多配置文件和命令。这些保存为Shell脚本的配置文件和命令可以在GitHub上找到,以供试用或将来参考:https://github.com/PacktPublishing/Demystifying-Cryptography-with-OpenSSL-3/tree/main/Chapter12 。
这就把我们带到了本章的结尾。现在,我们将总结我们在这里学到的一切。
在本章中,我们学习了如何运行迷你CA。首先,我们了解了为什么迷你CA在组织中很有用。我们还学习了 openssl ca
子命令以及如何为其创建配置文件。然后,我们学习了如何使用 openssl ca
颁发证书。之后,我们学习如何吊销证书和颁发CRL。我们通过学习如何为OCSP响应者颁发证书以及如何使用 openssl ocsp
子命令通过OCSP提供证书吊销状态来完成本章。这些知识可以帮助您设置和运行迷你CA,从而控制组织中的PKI。
这是本书的最后一章。我希望你喜欢这一章和这本书,并学到了一些新的有用的东西。我还希望所获得的知识将帮助您更好地了解加密和网络安全技术,开发更安全的应用程序,并推进您的职业生涯。