密码学中的基础公钥基础设施 PKI

LinuxBeginner
立即练习

介绍

在这个实验(Lab)中,你将探索公钥基础设施(PKI)的基础知识,这是支撑互联网上大部分安全(包括 HTTPS)的系统。PKI 是一套创建、管理、分发、使用、存储和撤销数字证书以及管理公钥加密所需的角色、策略、硬件、软件和流程。

你将通过动手实践 openssl 命令行工具来执行 PKI 的核心功能。你将扮演自己的证书颁发机构(CA),为 Web 服务器颁发证书,验证证书的信任链,最后撤销该证书。所有操作都将在 ~/project 目录下执行。

这是一个实验(Guided Lab),提供逐步指导来帮助你学习和实践。请仔细按照说明完成每个步骤,获得实际操作经验。根据历史数据,这是一个 初级 级别的实验,完成率为 96%。获得了学习者 100% 的好评率。

理解 PKI 基础知识

在这一步中,我们将介绍 PKI 的基本概念。此步骤中无需执行任何命令;目标是在我们开始动手实践之前,建立坚实的理论基础。

公钥基础设施 (Public Key Infrastructure, PKI)

PKI 是一个旨在增强电子通信安全性的框架。它通过证书颁发机构 (Certificate Authority, CA) 的方式,利用公钥密码学将公钥与相应的用户身份绑定起来。这种绑定是通过注册和颁发过程建立的。

证书颁发机构 (Certificate Authority, CA)

证书颁发机构是一个颁发数字证书的可信实体。CA 充当一个受信任的第三方,同时被证书的主体(所有者)和依赖该证书的各方所信任。CA 的主要作用是对绑定到特定用户的公钥进行数字签名并发布。

数字证书 (Digital Certificate)

数字证书是一个电子文档(通常遵循 X.509 标准),其中包含:

  • 所有者的公钥。
  • 所有者的身份信息(如名称或主机名)。
  • 颁发者(CA)的信息和数字签名。
  • 有效期(开始和结束日期)。
  • 一个唯一的序列号。

CA 对证书的签名证明了证书中包含的公钥确实属于证书中命名的实体。

信任链 (Trust Chain)

信任链(或证书链)是一系列证书的序列,从一个终端实体证书(例如,针对 example.com 的证书)开始,一直到根 CA 证书结束。

  1. 根 CA 证书 (Root CA Certificate):这是来自最终权威机构——根 CA 的自签名证书。这些证书预先安装在你的浏览器或操作系统的“信任存储区”(trust store)中。
  2. 中间 CA 证书 (Intermediate CA Certificate(s)):大型 CA 通常使用中间 CA 来向最终用户颁发证书,以保护根密钥。中间证书由根 CA 签名。
  3. 终端实体证书 (End-Entity Certificate):这是颁发给特定服务器或用户的证书。它由中间 CA 签名(在更简单的设置中也可能直接由根 CA 签名)。

当你的浏览器收到服务器的证书时,它会通过检查颁发者的证书来验证签名。它会沿着这条链向上追溯,直到找到一个已存在于其信任存储区中的根 CA。如果链有效且所有签名都通过验证,则认为该服务器是受信任的。

在下一步中,你将创建自己的根 CA。

创建证书颁发机构 (CA)

在这一步中,你将扮演证书颁发机构(CA),并创建其基础组件:一个私钥和一个自签名根证书。所有命令都将在终端中运行,所有文件都将在你当前的目录 ~/project 中创建。

首先,生成 CA 的私钥。这个密钥是 PKI 中最关键的秘密;它用于签署 CA 颁发的所有证书。

openssl genpkey -algorithm RSA -out ca.key

接下来,你将创建一个自签名根证书。根证书是自签名的,因为它代表了信任的最终锚点;没有更高的权威机构可以对其进行签名。

执行以下命令生成证书。我们使用 -subj 参数来非交互式地提供证书的主题信息。

openssl req -x509 -new -nodes -key ca.key -sha256 -days 365 -out ca.pem -subj "/C=US/ST=California/L=MountainView/O=MyLab/CN=MyLabRootCA"

我们来分解一下这个命令:

  • req: 证书签名请求(CSR)和证书生成工具。
  • -x509: 输出一个自签名证书而不是 CSR。
  • -new: 创建一个新证书。
  • -nodes: “No DES”,意味着私钥不会用密码短语(passphrase)加密。这在我们的实验中是为了简化操作。
  • -key ca.key: 指定用于签名的私钥。
  • -sha256: 使用 SHA-256 散列算法进行签名。
  • -days 365: 将证书的有效期设置为 365 天。
  • -out ca.pem: 指定新证书的输出文件。
  • -subj "/C=.../CN=...": 提供主题详细信息。CN(通用名,Common Name)是主要身份,对于 CA 来说就是它的名称。

你现在拥有了一个 CA 私钥 (ca.key) 和一个根证书 (ca.pem)。你可以检查新 CA 证书的内容:

openssl x509 -in ca.pem -text -noout

滚动查看输出,注意 Issuer(颁发者)和 Subject(主体)字段是相同的,这证实了它是自签名的。

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            ...
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = US, ST = California, L = MountainView, O = MyLab, CN = MyLabRootCA
        Validity
            Not Before: ...
            Not After : ...
        Subject: C = US, ST = California, L = MountainView, O = MyLab, CN = MyLabRootCA
        Subject Public Key Info:
            ...

颁发服务器证书

在这一步中,你将模拟一个服务器所有者请求证书的过程。你将为服务器生成一个私钥和一个证书签名请求(CSR),然后使用你在上一步中创建的 CA 来签署 CSR 并颁发一个有效的证书。

首先,为服务器生成一个私钥。这个密钥必须在服务器本身上保持机密。

openssl genpkey -algorithm RSA -out server.key

接下来,创建一个证书签名请求(CSR)。CSR 是一段编码文本块,包含公钥以及将包含在证书中的其他信息,例如组织名称和域名。CSR 会被发送给 CA 进行签名。

openssl req -new -key server.key -out server.csr -subj "/C=US/ST=California/L=MountainView/O=MyWebServer/CN=example.com"

请注意,对于服务器证书,CN(通用名,Common Name)必须与服务器的域名匹配,在本例中是 example.com

现在,作为 CA,你将使用你的 CA 私钥 (ca.key) 来签署服务器的 CSR (server.csr)。此操作将创建最终的服务器证书 (server.crt)。

openssl x509 -req -in server.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out server.crt -days 300 -sha256

我们来回顾一下新的选项:

  • x509 -req: 这告诉 OpenSSL 处理一个 CSR。
  • -in server.csr: 输入的 CSR 文件。
  • -CA ca.pem: 用作颁发者的 CA 证书。
  • -CAkey ca.key: 用于签名的 CA 私钥。
  • -CAcreateserial: 这会创建并管理一个序列号文件 (ca.srl),这是确保 CA 颁发的每个证书都具有唯一序列号所必需的。
  • -days 300: 服务器证书的有效期。这个时间应该短于 CA 证书的有效期。

最后,检查新创建的服务器证书。

openssl x509 -in server.crt -text -noout

在输出中,观察 Issuer(颁发者)和 Subject(主体)字段。Issuer 应该是你的 CA (MyLabRootCA),而 Subject 应该是你的服务器 (example.com)。这确认了证书已由你的 CA 正确颁发。

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: ...
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = US, ST = California, L = MountainView, O = MyLab, CN = MyLabRootCA
        Validity
            Not Before: ...
            Not After : ...
        Subject: C = US, ST = California, L = MountainView, O = MyWebServer, CN = example.com
        ...
    Signature Algorithm: sha256WithRSAEncryption
         ...

验证证书链

在这一步中,你将学习如何验证证书链。这是客户端(如网页浏览器)为确定服务器证书是否可信而执行的过程。客户端会检查证书是否由它所信任的 CA 签名。

你可以使用 openssl verify 命令来执行此检查。你需要通过提供根证书来告知 OpenSSL 你信任哪些 CA。

运行以下命令,使用你的根证书 ca.pem 来验证 server.crt

openssl verify -CAfile ca.pem server.crt

输出应该如下所示:

server.crt: OK

这个 OK 状态确认了:

  1. server.crt 证书确实是由与 ca.pem 中公钥对应的私钥签名的。
  2. 证书尚未过期。

现在,让我们看看如果验证者(verifier)的信任 CA 列表中没有我们的 CA 会发生什么。你可以通过不带 -CAfile 选项运行 verify 命令来模拟这种情况。

openssl verify server.crt

这次,命令将失败并显示类似以下的错误:

C = US, ST = California, L = MountainView, O = MyWebServer, CN = example.com
error 20 at 0 depth lookup: unable to get local issuer certificate
error server.crt: verification failed

错误 "unable to get local issuer certificate" 意味着系统无法在其默认信任存储(trust store)中找到颁发者(MyLabRootCA)的证书。这说明了为什么客户端必须拥有根 CA 证书才能建立信任链是至关重要的。

模拟证书吊销

在这一步中,你将学习如何吊销(revoke)一个证书。当证书的私钥泄露,或者证书在自然到期前不再需要时,吊销是一个关键流程。这通过证书吊销列表(CRL,Certificate Revocation List)来管理。

CRL 是由 CA 颁发的一个数字签名列表,其中包含该 CA 吊销的所有证书的序列号。客户端可以下载 CRL 来检查收到的证书是否仍然有效。

为了管理吊销,openssl 需要一个小的配置文件来知道在哪里可以找到 CA 的数据库文件(index.txtserial)。本实验的设置脚本已经创建了必要的目录(my-ca)和文件。现在,创建配置文件。

使用 cat 命令创建 my-ca.conf

cat << EOF > my-ca.conf
[ ca ]
default_ca = CA_default

[ CA_default ]
dir = ./my-ca
database = \$dir/index.txt
serial = \$dir/serial
private_key = ca.key
certificate = ca.pem
default_md = sha256
policy = policy_anything
crl_extensions = crl_ext
default_crl_days = 30

[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional

[ crl_ext ]
authorityKeyIdentifier=keyid:always
EOF

这个配置文件告诉 OpenSSL 如何作为一个证书颁发机构(CA)进行操作。每个部分的作用如下:

  • default_ca = CA_default: 指向主要的 CA 配置部分。
  • dir = ./my-ca: CA 的工作目录,用于存放数据库文件。
  • database = $dir/index.txt: 证书数据库(跟踪已颁发/已吊销的证书)。
  • serial = $dir/serial: 序列号文件,用于唯一的证书 ID。
  • private_key = ca.key: 用于签署证书的 CA 私钥。
  • certificate = ca.pem: CA 自身的证书文件。
  • default_md = sha256: 签名的哈希算法(SHA-256)。
  • policy = policy_anything: 证书验证规则。
  • crl_extensions = crl_ext: CRL 格式化选项。
  • default_crl_days = 30: CRL 的有效期(30 天)。
  • countryName = optional: 国家代码。
  • stateOrProvinceName = optional: 州/省。
  • localityName = optional: 城市/地点。
  • organizationName = optional: 组织名称。
  • organizationalUnitName = optional: 部门。
  • commonName = supplied: 域名/服务器名称(必需)。
  • emailAddress = optional: 电子邮件地址。
  • authorityKeyIdentifier=keyid:always: 在 CRL 中包含 CA 标识符,用于验证。

这个配置文件是你的 CA 的“操作手册”。它告诉 OpenSSL 在哪里查找密钥、如何存储证书,以及在颁发和吊销证书时应遵循哪些规则。

现在,吊销服务器证书(server.crt)。此命令将查找证书的序列号,并在 index.txt 数据库文件中将其标记为已吊销。

openssl ca -config my-ca.conf -revoke server.crt

你将看到确认吊销的输出。

吊销后,你必须生成并发布一个更新后的 CRL。

openssl ca -config my-ca.conf -gencrl -out my-ca.crl

这会创建文件 my-ca.crl,其中包含已吊销证书的列表。

最后,我们再次尝试验证服务器证书,但这次,我们还将提供 CRL。正确的验证过程必须检查吊销状态。

openssl verify -CAfile ca.pem -CRLfile my-ca.crl -crl_check server.crt

该命令现在会失败并显示明确的消息:

C = US, ST = California, L = MountainView, O = MyWebServer, CN = example.com
error 23 at 0 depth lookup: certificate revoked
error server.crt: verification failed

"certificate revoked"(证书已吊销)错误确认了我们的吊销过程是成功的。客户端在检查 CRL 时,正确识别出 example.com 的证书不再可信。

总结

恭喜你!你已成功完成了关于公钥基础设施(PKI)基础知识的本次实验。你获得了关于保护数字通信所需基本操作的实践经验。

在本实验中,你学习了如何:

  • 理解 PKI、证书颁发机构(CA)和信任链的核心概念。
  • 通过生成私钥和自签名证书来创建你自己的简单根 CA。
  • 通过使用你的 CA 密钥签署证书签名请求(CSR,Certificate Signing Request)来颁发服务器证书。
  • 使用 openssl verify 命令验证证书的信任链。
  • 吊销证书,并通过生成和使用证书吊销列表(CRL,Certificate Revocation List)来确认其被吊销的状态。

这些技能是管理安全系统和理解互联网上如何建立信任的基石。