在【第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.txtnew_certs_dir = issuedcertificate = root_cert.pemprivate_key = private/root_keypair.pem数据库参数指定证书索引文件,也称为证书数据库。它是一个文本文件,其中每一行都包含有关一个证书的信息。 new_certs_dir 参数指定将写入新颁发证书的目录。 certificate 和 private_key 参数指定了当前CA(在我们的例子中是根CA)的证书和相应的私钥。
接下来,我们将定义一些可选参数。我们的根CA将只颁发中间CA证书;因此,我们可以将默认颁发的证书有效期设置为10年:
xxxxxxxxxxdefault_days = 3650以下参数设置用于对根CA颁发的证书进行签名的消息摘要算法。 default_md 参数有一个特殊的 default 。这意味着在签名证书中使用的相同消息摘要算法将在签名的证书中使用。例如,如果使用SHA-256哈希函数本身对签名证书进行签名,则颁发的证书也将使用SHA-256散列函数进行签名。在我们的例子中,此参数不会产生任何影响,因为ED448证书在签署其他证书时始终使用SHAKE256消息摘要算法。我们将在这里包含此参数,只是为了演示 openssl ca 子命令的功能:
xxxxxxxxxxdefault_md = default下一个参数指示 openssl ca 使用随机序列号而不是顺序序列号颁发证书:
xxxxxxxxxxrand_serial = yes后续参数允许我们颁发具有相同主题的多个证书。它可用于替换过期的证书:
xxxxxxxxxxunique_subject = no接下来的参数控制在签名之前如何显示证书详细信息。OpenSSL文档建议设置这些参数,否则将使用旧的损坏的显示格式:
xxxxxxxxxxname_opt = ca_defaultcert_opt = ca_default以下参数是必需的,指定了定义默认颁发证书的主题策略的配置部分。当我们谈到本节时,我们将更仔细地审查它:
xxxxxxxxxxpolicy = policy_intermediate_cert下一个参数指定默认的X509v3扩展部分:
xxxxxxxxxxx509_extensions = v3_intermediate_cert下一个参数指示OpenSSL从 证书签名请求(Certificate Signing Request,CSR)中复制X509v3扩展,这些扩展不是由CA添加到颁发的证书中的。选择性复制允许CSR提供有用的X509v3扩展,如 subjectAltName ,但禁止覆盖CA设置的重要扩展,如 basicConstraints 或 keyUsage :
xxxxxxxxxxcopy_extensions = copy接下来的参数与CRL相关。他们使用CRL扩展名、CRL编号文件和已发布CRL的默认有效性设置默认配置部分:
xxxxxxxxxxcrl_extensions = crl_extensions_root_cacrlnumber = crlnumber.txtdefault_crl_days = 30当使用此配置文件进行CSR时,以下参数定义了CSR的默认Subject和X509v3扩展名。使用此配置文件创建的唯一CSR应该是根CA证书的CSR。因此,在配置文件中定义根CA证书的Subject和X509v3扩展名很方便,既可以生成CSR,也可以生成根CA证书。在配置文件中包含证书数据也有助于提醒使用哪个CA证书:
xxxxxxxxxx[req]prompt = nodistinguished_name = distinguished_name_root_certx509_extensions = v3_root_cert [distinguished_name_root_cert]countryName = NOstateOrProvinceName = OslolocalityName = OsloorganizationName = TLS ExpertscommonName = Root CA下一个配置部分定义了默认颁发证书的主题策略:
xxxxxxxxxx[policy_intermediate_cert]countryName = matchstateOrProvinceName = matchlocalityName = matchorganizationName = matchorganizationalUnitName = optionalcommonName = suppliedemailAddress = optional根据定义的策略,我们要求颁发的中间CA证书的主题与根CA证书的主体具有相同的地理位置和组织。这是有道理的,因为我们在一个组织内运行一个迷你CA。
接下来的配置部分定义了根CA证书和颁发的中间CA证书的X509v3扩展。可以使用 -extensions 命令行开关选择所需的部分:
x[v3_root_cert]subjectKeyIdentifier = hashauthorityKeyIdentifier = keyid:always, issuerbasicConstraints = critical, CA:TRUEkeyUsage = critical, digitalSignature, cRLSign, keyCertSigncrlDistributionPoints = URI:http://crl.tls-experts.no/root_crl.der[v3_intermediate_cert]subjectKeyIdentifier = hashauthorityKeyIdentifier = keyid:always, issuerbasicConstraints = critical, CA:TRUE, pathlen:0keyUsage = critical, digitalSignature, cRLSign, keyCertSigncrlDistributionPoints = URI:http://crl.tls-experts.no/root_crl.der最后一个配置部分定义了将添加到已发布CRL中的CRL扩展:
xxxxxxxxxx[crl_extensions_root_ca]authorityKeyIdentifier = keyid:always, issuercrlDistributionPoints = 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.pemUsing configuration from root.cnfCheck that the request matches the signatureSignature okCertificate 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.derCertificate is to be certified until Jul 15 18:54:11 2032 GMT (3650 days)Sign the certificate? [y/n]:y1 out of 1 certificate requests certified, commit? [y/n]yWrite out database with 1 new entriesData 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.txtnew_certs_dir = issuedcertificate = intermediate_cert.pemprivate_key = private/intermediate_keypair.pemdefault_days = 365default_md = defaultrand_serial = yesunique_subject = noname_opt = ca_defaultcert_opt = ca_defaultpolicy = policy_server_certx509_extensions = v3_server_certcopy_extensions = copycrl_extensions = crl_extensions_intermediate_cacrlnumber = crlnumber.txtdefault_crl_days = 30请注意,此配置文件中的 default_days 参数低于根CA配置文件中相同的参数。这是因为我们的中间CA将颁发叶子证书,这些证书的生命周期通常比根证书或中间CA证书短。
我们将使用有助于构建中间CA证书主题的参数继续配置文件:
xxxxxxxxxx[req]prompt = nodistinguished_name = distinguished_name_intermediate_cert[distinguished_name_intermediate_cert]countryName = NOstateOrProvinceName = OslolocalityName = OsloorganizationName = TLS ExpertscommonName = Intermediate CA我们的中间CA将颁发服务器和客户端证书。因此,我们需要为这些类别的证书定义主题策略:
xxxxxxxxxx[policy_server_cert]countryName = optionalstateOrProvinceName = optionallocalityName = optionalorganizationName = optionalorganizationalUnitName = optionalcommonName = suppliedemailAddress = optional[policy_client_cert]countryName = optionalstateOrProvinceName = optionallocalityName = optionalorganizationName = optionalorganizationalUnitName = optionalcommonName = suppliedemailAddress = supplied正如您所观察到的,中间CA配置中定义的策略比根CA配置中的策略更宽松。这是因为我们可能希望向组织外部的实体(例如客户或合作伙伴)颁发证书,并且因为在我们的演示中有一些变化是很好的。
中间CA配置中的下一节定义了X509v3扩展,这些扩展将添加到不同类型的已颁发证书中,如服务器证书、客户端证书和 在线证书状态协议(Online Certificate Status Protocol,OCSP)响应者的证书:
xxxxxxxxxx[v3_server_cert]subjectKeyIdentifier = hashauthorityKeyIdentifier = keyid:always, issuerbasicConstraints = critical, CA:FALSEnsCertType = serverkeyUsage = critical, digitalSignature, keyEnciphermentextendedKeyUsage = serverAuthcrlDistributionPoints = URI:http://crl.tls-experts.no/intermediate_crl.derauthorityInfoAccess = OCSP;URI:http://ocsp.tls-experts.no/[v3_client_cert]subjectKeyIdentifier = hashauthorityKeyIdentifier = keyid:always, issuerbasicConstraints = critical, CA:FALSEnsCertType = client, emailkeyUsage = critical, nonRepudiation, digitalSignature, keyEnciphermentextendedKeyUsage = clientAuth, emailProtectioncrlDistributionPoints = URI:http://crl.tls-experts.no/intermediate_crl.derauthorityInfoAccess = OCSP;URI:http://ocsp.tls-experts.no/[v3_ocsp_cert]subjectKeyIdentifier = hashauthorityKeyIdentifier = keyid:always, issuerbasicConstraints = critical, CA:FALSEkeyUsage = critical, digitalSignatureextendedKeyUsage = critical, OCSPSigningcrlDistributionPoints = URI:http://crl.tls-experts.no/intermediate_crl.derauthorityInfoAccess = OCSP;URI:http://ocsp.tls-experts.no/配置文件的最后一节定义了将添加到已发布的CRL中的扩展名:
xxxxxxxxxx[crl_extensions_intermediate_ca]authorityKeyIdentifier = keyid:always, issuercrlDistributionPoints = URI:http://crl.tls-experts.no/intermediate_crl.derauthorityInfoAccess = 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.pemUsing configuration from root.cnfCheck that the request matches the signatureSignature okCertificate Details: …Certificate is to be certified until Jul 15 18:55:11 2032 GMT (3650 days)Sign the certificate? [y/n]:y1 out of 1 certificate requests certified, commit? [y/n]yWrite out database with 1 new entriesData 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 = nodistinguished_name = distinguished_name_server_certreq_extensions = v3_server_cert[distinguished_name_server_cert]countryName = NOstateOrProvinceName = OslolocalityName = OsloorganizationName = TLS ExpertscommonName = 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.pemUsing configuration from intermediate.cnfCheck that the request matches the signatureSignature okCertificate Details: …Certificate is to be certified until Jul 19 15:36:44 2023 GMT (365 days)Sign the certificate? [y/n]:y1 out of 1 certificate requests certified, commit? [y/n]yWrite out database with 1 new entriesData Base Updated看看证书颁发命令有多简单!只有三步。所有其他参数都来自配置,包括默认策略和X509v3扩展。在配置文件中配置了所有内容后,我们可以使用这样一个简单的命令轻松颁发服务器证书。
颁发客户端证书有点不同,但也不是很困难。我们将在下一节中学习如何做到这一点。
生成客户端证书类似于生成服务器证书:
像往常一样,我们将为此证书创建一个单独的目录,并在那里更改我们当前的目录:
xxxxxxxxxx$ cd mini-ca$ mkdir client$ cd client我们将使用保存在 client.cnf 文件中的以下配置来生成客户端证书:
xxxxxxxxxx[req]prompt = nodistinguished_name = distinguished_name_client_certreq_extensions = v3_client_cert[distinguished_name_client_cert]countryName = NOstateOrProvinceName = OslolocalityName = OsloorganizationName = TLS ExpertscommonName = Thor OdinsonemailAddress = thor@tls-experts.no[v3_client_cert]subjectAltName = @subject_alt_names[subject_alt_names]email.1 = postmaster@tls-experts.noemail.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.pemUsing configuration from intermediate.cnfCheck that the request matches the signatureSignature okCertificate Details: …Certificate is to be certified until Jul 19 15:37:44 2023 GMT (365 days)Sign the certificate? [y/n]:y1 out of 1 certificate requests certified, commit? [y/n]yWrite out database with 1 new entriesData 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 = nodistinguished_name = distinguished_name_server_cert[distinguished_name_server_cert]countryName = NOstateOrProvinceName = OslolocalityName = OsloorganizationName = TLS ExpertscommonName = 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.pemUsing configuration from intermediate.cnfCheck that the request matches the signatureSignature okCertificate Details: …Certificate is to be certified until Jul 19 15:38:44 2023 GMT (365 days)Sign the certificate? [y/n]:y1 out of 1 certificate requests certified, commit? [y/n]yWrite out database with 1 new entriesData 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 \ -textCertificate 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: 1No 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 keyCompromiseUsing configuration from intermediate.cnfRevoking 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 \ -textCertificate 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: 2Revoked 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 = hashauthorityKeyIdentifier = keyid:always, issuerbasicConstraints = critical, CA:FALSEkeyUsage = critical, digitalSignatureextendedKeyUsage = critical, OCSPSigningcrlDistributionPoints = URI:http://crl.tls-experts.no/intermediate_crl.derauthorityInfoAccess = OCSP;URI:http://ocsp.tls-experts.no/像往常一样,我们将从准备目录开始:
xxxxxxxxxx$ cd mini-ca$ mkdir ocsp$ cd ocsp然后,我们将对OCSP响应者证书进行配置,并将其保存到 ocsp.cnf 文件中:
xxxxxxxxxx[req]prompt = nodistinguished_name = distinguished_name_ocsp_cert[distinguished_name_ocsp_cert]countryName = NOstateOrProvinceName = OslolocalityName = OsloorganizationName = TLS ExpertscommonName = 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.pemUsing configuration from intermediate.cnfCheck that the request matches the signatureSignature okCertificate Details: …Certificate is to be certified until Jul 19 17:45:44 2023 GMT (365 days)Sign the certificate? [y/n]:y1 out of 1 certificate requests certified, commit? [y/n]yWrite out database with 1 new entriesData 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.pemACCEPT 0.0.0.0:4480 PID=124271ocsp: waiting for OCSP client connections...我们已将OCSP响应者证书及其私钥提供给 openssl ocsp ,用于对OCSP响应进行签名。
但是 openssl ocsp 子命令非常好,它不仅可以充当OCSP服务器,还可以充当OCAP客户端。让我们在客户端模式下使用它,并检查我们最近颁发的 server 证书的有效性。为此,我们需要打开另一个终端窗口,切换到 mini-ca/ocsp 目录,并运行以下命令:
xxxxxxxxxxopenssl ocsp \ -url http://localhost:4480 \ -sha256 \ -CAfile ../root/root_cert.pem \ -issuer ../intermediate/intermediate_cert.pem \ -cert ../server/server_cert.pemResponse 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.pemResponse 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。
这是本书的最后一章。我希望你喜欢这一章和这本书,并学到了一些新的有用的东西。我还希望所获得的知识将帮助您更好地了解加密和网络安全技术,开发更安全的应用程序,并推进您的职业生涯。