OpenSSL 生成 SSL/TLS 证书步骤详解 – wiki基地


OpenSSL 生成 SSL/TLS 证书步骤详解:从零到精通

在互联网日益普及的今天,数据安全和用户信任变得前所未有的重要。SSL/TLS 证书是实现这一目标的核心技术之一,它为网站和服务器提供了加密通信的能力,并验证了服务器的身份。OpenSSL 是一个强大、开源的命令行工具集,广泛用于生成、管理和处理 SSL/TLS 证书、密钥以及加密相关的各种操作。

本文将深入浅出地详细讲解如何使用 OpenSSL 生成 SSL/TLS 证书。我们将涵盖从基础概念到生成不同类型证书(自签名证书、由自定义 CA 签名的证书、为商业 CA 生成 CSR)的全过程,并解释每个步骤背后的原理和重要参数。

一、 前置知识:SSL/TLS 证书与密钥基础

在开始实践之前,理解构成 SSL/TLS 证书体系的关键组件至关重要:

  1. 私钥 (Private Key):

    • 这是一段保密的加密数据,只有服务器拥有。
    • 用于对发送给客户端的数据进行数字签名(确保数据完整性和来源),以及解密客户端使用公钥加密的数据。
    • 绝对不能泄露。通常存储在服务器上,并设置严格的访问权限。
    • OpenSSL 生成的私钥文件通常以 .key.pem 为后缀。
  2. 公钥 (Public Key):

    • 从私钥派生而来,可以公开。
    • 用于客户端加密发送给服务器的数据,以及验证服务器的数字签名。
    • 公钥包含在证书中。
  3. 证书签名请求 (Certificate Signing Request, CSR):

    • 一个包含您的公钥、组织信息(如 Common Name, Organization, Locality, State, Country 等)的文件。
    • 这是您提交给证书颁发机构 (Certificate Authority, CA) 的文件,请求其为您颁发证书。
    • CSR 不包含私钥,因此可以安全地提交给 CA。
    • OpenSSL 生成的 CSR 文件通常以 .csr 为后缀。
  4. 证书 (Certificate):

    • 由一个受信任的 CA 签名的文件。
    • 包含您的公钥、您的身份信息,以及 CA 的数字签名。
    • 证明了某个公钥确实属于某个特定的实体(如网站域名)。
    • 客户端(如浏览器)收到证书后,会使用预置的 CA 根证书来验证您证书的签名,从而建立信任。
    • OpenSSL 生成的证书文件通常以 .crt.pem 为后缀。
  5. 证书颁发机构 (Certificate Authority, CA):

    • 一个受信任的第三方机构,负责验证申请者的身份并签署其 CSR,从而颁发证书。
    • 操作系统和浏览器内置了全球主要的 CA 的根证书,作为信任链的起点。
    • 证书形成一个信任链:用户信任 CA 根证书 -> CA 根证书签发中间证书 -> 中间证书签发您的服务器证书。
  6. 信任链 (Certificate Chain):

    • 由您的服务器证书、所有必要的中间 CA 证书以及根 CA 证书组成的序列。
    • 服务器在 TLS 握手时通常需要将服务器证书和中间 CA 证书发送给客户端,以便客户端验证证书的有效性直至信任的根证书。

二、 准备工作:安装 OpenSSL

大多数 Linux 和 macOS 系统都预装了 OpenSSL。您可以在终端中输入以下命令来检查是否已安装以及版本信息:

bash
openssl version

如果未安装,或者您使用的是 Windows 系统,可以从 OpenSSL 官方网站(https://www.openssl.org/)下载对应的安装包进行安装。在 Windows 上安装后,可能需要将 OpenSSL 的 bin 目录添加到系统的 PATH 环境变量中,以便在任何位置都能调用 openssl 命令。

三、 OpenSSL 生成证书的三种常见场景及步骤

我们将详细介绍以下三种使用 OpenSSL 生成证书的场景:

  1. 生成自签名证书 (Self-Signed Certificate): 适用于开发、测试或内部非关键应用。
  2. 生成由自定义 CA 签名的证书 (Private CA Signed Certificate): 适用于企业内部网络,需要建立自己的信任体系。
  3. 生成用于提交给商业 CA 的 CSR: 适用于需要公共信任的生产环境网站。

场景一:生成自签名证书

自签名证书是由证书本身签名的证书。它没有经过任何外部 CA 的验证和签名。虽然生成简单方便,但由于浏览器和客户端不信任一个未知来源的证书,访问时通常会显示安全警告。

步骤详解:

这一过程通常一步到位,同时生成私钥和自签名证书。

bash
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout server.key -out server.crt -subj "/C=CN/ST=Beijing/L=Beijing/O=MyOrg/OU=MyDept/CN=localhost"

让我们详细分解这个命令及其参数:

  • openssl: 调用 OpenSSL 工具。
  • req: 指定执行“证书请求及管理”相关的操作。
  • -x509: 这个重要的选项告诉 OpenSSL 输出一个自签名的 X.509 格式证书,而不是一个 CSR。通常 req 命令是用来生成 CSR 的,加上 -x509 就变成了自签名证书生成模式。
  • -nodes: no DES. 表示私钥不使用加密(不设置密码)。如果去掉此选项,生成私钥时会提示输入一个密码(passphrase)。在服务器启动时需要输入此密码才能加载私钥。对于自动化部署或无人值守的服务器,通常使用 -nodes。但在某些对安全性要求极高的场景,会选择设置密码并采取措施安全管理密码。
  • -days 365: 设置证书的有效期为 365 天。您可以根据需要调整这个数字。
  • -newkey rsa:2048: 生成一个新的私钥。
    • rsa:2048: 指定密钥类型为 RSA,长度为 2048 位。RSA 是目前广泛使用的非对称加密算法。2048 位是当前推荐的最小安全长度,更高位数的如 4096 位更安全但性能开销更大。您也可以选择 ECDSA 等其他算法。
  • -keyout server.key: 指定生成的私钥文件的输出路径和名称。在这里是当前目录下的 server.key
  • -out server.crt: 指定生成的自签名证书文件的输出路径和名称。在这里是当前目录下的 server.crt
  • -subj "/C=CN/ST=Beijing/L=Beijing/O=MyOrg/OU=MyDept/CN=localhost": subject. 自动化填写证书的主体信息,避免交互式输入。subj 参数后面的字符串遵循特定的格式 /key=value/key=value/...。常用的字段包括:
    • C: Country Name (2 letter code) – 国家代码 (如 CN)
    • ST: State or Province Name (Full name) – 省份名称 (如 Beijing)
    • L: Locality Name (eg, city) – 城市名称 (如 Beijing)
    • O: Organization Name (eg, company) – 组织/公司名称 (如 MyOrg)
    • OU: Organizational Unit Name (eg, section) – 组织单位名称/部门 (如 MyDept)
    • CN: Common Name (e.g. server FQDN or YOUR name) – 常用名称。对于服务器证书,这通常是服务器的完全限定域名 (FQDN),例如 www.example.commyserver.internal注意:对于自签名证书,您可以填 localhost 或任何您想测试的域名。 在较新的 TLS 标准中,CN 字段的重要性正在降低,推荐使用 Subject Alternative Name (SAN) 字段来指定域名,但自签名证书的简单生成通常省略 SAN。

执行命令后:

您将在当前目录下看到两个文件:
* server.key: 您的私钥文件。
* server.crt: 您的自签名证书文件。

验证生成的证书和私钥:

您可以使用 OpenSSL 命令查看生成的文件信息:

  • 查看证书内容:
    bash
    openssl x509 -in server.crt -text -noout

    这将显示证书的详细信息,包括颁发者 (Issuer) 和主体 (Subject) 信息(对于自签名证书,这两者是相同的)、有效期、公钥信息等。
  • 查看私钥内容:
    bash
    openssl rsa -in server.key -text -noout

    这将显示私钥的详细信息。
  • 验证私钥和证书是否匹配:
    bash
    openssl x509 -in server.crt -pubkey -noout | openssl rsa -pubin -modulus -noout | openssl md5
    openssl rsa -in server.key -pubout -noout | openssl rsa -pubin -modulus -noout | openssl md5

    如果输出的 MD5 值相同,则表示私钥和证书是匹配的。

场景二:生成由自定义 CA 签名的证书

在企业内部网络或测试环境中,如果不想每次都看到浏览器警告,并且需要模拟真实的 CA 体系,可以搭建自己的私有 CA,并用这个 CA 来签发服务器证书。所有客户端只需要信任这个私有 CA 的根证书即可。

步骤详解:

这个过程相对复杂,需要创建 CA 的密钥和证书,然后使用 CA 来签发服务器的 CSR。

第一阶段:搭建私有 CA

  1. 创建 CA 的私钥:
    bash
    openssl genpkey -algorithm RSA -out ca.key -aes-256-cbc -pkeyopt rsa_keygen_bits:4096
    # 或者使用旧的命令方式 (更常用):
    # openssl genrsa -aes256 -out ca.key 4096

    • genpkeygenrsa: 生成私钥。
    • -algorithm RSA / -genrsa: 指定 RSA 算法。
    • -out ca.key: 输出 CA 私钥文件。
    • -aes-256-cbc / -aes256: 使用 AES-256-CBC 算法加密私钥。系统会提示您输入一个密码。请务必记住并妥善保管此密码! 这是 CA 私钥的保护伞。
    • rsa_keygen_bits:4096 / 4096: 指定 RSA 密钥长度为 4096 位,对于 CA 根证书,建议使用更长的密钥。
  2. 创建 CA 的自签名证书 (CA 根证书):
    使用刚刚生成的私钥来创建 CA 的根证书。这个证书是自签名的,将作为信任链的起点。
    bash
    openssl req -x509 -new -nodes -days 3650 -key ca.key -out ca.crt -subj "/C=CN/ST=Beijing/L=Beijing/O=MyPrivateCA/CN=MyPrivateCARoot" -config /etc/ssl/openssl.cnf

    • req: 证书请求工具。
    • -x509: 生成自签名证书(这里的自签名是 CA 自身签自己)。
    • -new: 创建新的请求。
    • -nodes: 这里通常使用 -nodes,因为 ca.key 是加密的。如果您在步骤1使用了 -aes-256-cbc,这里运行时会提示输入 CA 私钥的密码。
    • -days 3650: CA 根证书通常有效期很长,例如 10 年 (3650 天)。
    • -key ca.key: 指定用于签名的私钥,即 CA 的私钥。
    • -out ca.crt: 输出 CA 的根证书文件。
    • -subj "/C=CN/ST=Beijing/L=Beijing/O=MyPrivateCA/CN=MyPrivateCARoot": 填写 CA 证书的主体信息。CN 应该是 CA 的名称。
    • -config /etc/ssl/openssl.cnf: 重要! 指定 OpenSSL 配置文件。这个文件通常包含 X.509 扩展的相关配置,特别是标记这个证书是 CA 证书的扩展 (basicConstraints=CA:TRUE)。虽然不指定 -config 有时也能生成简单的 CA 证书,但为了包含正确的 CA 扩展并进行后续签发,建议指定配置文件。您可能需要编辑此文件,找到 [ v3_ca ] 或类似的段落,确保 basicConstraints = CA:TRUE 被启用。
  3. 准备 CA 工作目录和索引文件 (可选但强烈推荐):
    为了方便 CA 进行签发管理(追踪已签发的证书序列号、主题等),OpenSSL CA 工具需要特定的目录结构和文件。
    bash
    mkdir ca
    cd ca
    mkdir newcerts private certs crl
    touch index.txt
    echo 1000 > serial # 初始化证书序列号,从1000开始
    cp ../ca.crt ./
    cp ../ca.key ./private/ # 移动CA私钥到private目录并确保权限安全
    chmod 600 private/ca.key # 确保只有所有者可读写
    # 可能需要编辑 openssl.cnf 文件,指向这些目录和文件,
    # 例如设置 dir = ./ca 等

    实际使用 openssl ca 命令签发时,会依赖 index.txt (记录签发历史)、serial (下一个证书的序列号) 等文件。

第二阶段:为服务器生成密钥和 CSR

  1. 创建服务器的私钥:
    bash
    openssl genpkey -algorithm RSA -out server.key -pkeyopt rsa_keygen_bits:2048
    # 或者
    # openssl genrsa -out server.key 2048

    这里通常加密服务器私钥 (-nodes 是默认行为或不指定加密算法),以便服务器软件(如 Nginx, Apache)启动时无需输入密码。

  2. 创建服务器的 CSR:
    这个 CSR 将提交给您的私有 CA 进行签名。重点是如何包含 Subject Alternative Name (SAN)。 现代浏览器强制要求证书包含 SAN 来匹配域名,否则会显示警告,即使 CN 匹配。SAN 配置通常在 openssl.cnf 文件中完成。

    首先,创建一个临时的 OpenSSL 配置文件或者修改主配置文件,在 [ req ] 段落中添加 req_extensions = v3_req。然后在文件末尾添加一个 [ v3_req ] 段落,并定义 SAN。

    例如,创建一个名为 server.cnf 的文件:
    “`ini
    [ req ]
    default_bits = 2048
    prompt = no
    default_md = sha256
    req_extensions = v3_req # 启用请求扩展,指向 v3_req 段落
    distinguished_name = req_distinguished_name

    [ req_distinguished_name ]
    C = CN
    ST = Beijing
    L = Beijing
    O = MyOrg
    OU = MyDept
    CN = myserver.internal # 这里写主域名或服务名

    [ v3_req ]
    keyUsage = nonRepudiation, digitalSignature, keyEncipherment
    extendedKeyUsage = serverAuth
    subjectAltName = @alt_names # 指向 alt_names 段落

    [ alt_names ]
    DNS.1 = myserver.internal # 主要域名
    DNS.2 = anothername.internal # 其他需要包含的域名
    IP.1 = 192.168.1.100 # 如果需要包含 IP 地址
    “`

    然后使用这个配置文件生成 CSR:
    bash
    openssl req -new -key server.key -out server.csr -config server.cnf

    * req: 证书请求工具。
    * -new: 创建新的请求。
    * -key server.key: 指定用于生成 CSR 的私钥。
    * -out server.csr: 输出生成的 CSR 文件。
    * -config server.cnf: 指定包含 SAN 配置的配置文件。

第三阶段:使用自定义 CA 签署服务器 CSR

现在我们有了 CA 的密钥 (ca/private/ca.key) 和证书 (ca/ca.crt),以及服务器的 CSR (server.csr)。我们可以使用 CA 来签署这个 CSR。

“`bash

确保你在 CA 工作目录下 (cd ca)

openssl ca -in ../server.csr -out ../server.crt -days 365 -extensions server_cert -md sha256 -config openssl.cnf -batch
``
*
ca: 调用 OpenSSL 的 CA 工具。这个命令非常依赖openssl.cnf配置中关于 CA 目录、文件和签发策略的设置。
*
-in ../server.csr: 指定要签名的 CSR 文件路径。../是因为我们假设在ca目录下执行,CSR 在上一级目录。
*
-out ../server.crt: 指定签名后生成的服务器证书的输出路径和名称。
*
-days 365: 设置签发证书的有效期。
*
-extensions server_cert: **重要!** 指定在签发证书时应用的 X.509 扩展配置段落。这个段落通常定义了服务器证书应有的扩展,例如basicConstraints=CA:FALSE(非CA证书)、keyUsage,extendedKeyUsage(如serverAuth), 以及最重要的subjectAltName(从 CSR 中复制)。这个段落在openssl.cnf中定义,例如[ server_cert ]。您需要确保openssl.cnf中的相关配置正确,特别是指示 CA 将 CSR 中的 SAN 复制到最终证书中 (copy_extensions = copyallcopy_extensions = subjectAltName)。
*
-md sha256: 指定签名使用的哈希算法。SHA-256 是当前推荐的标准。
*
-config openssl.cnf: 指定 CA 工具使用的配置文件。通常是您在 CA 目录中准备好的那个,其中包含dir,index,serial, 签发策略,以及扩展定义。
*
-batch: 非交互模式。如果您的openssl.cnf中的策略设置允许自动签发,可以使用此选项避免确认提示。否则需要手动输入y` 确认签发。

执行命令后:

  • 如果在 ca 目录下执行,并且配置正确,将在上一级目录生成 server.crt 文件。
  • ca/index.txt 文件会被更新,记录这次签发的信息。
  • ca/serial 文件会被更新,序列号递增。
  • 生成的证书文件 server.crt 便是由您的私有 CA 签发的服务器证书。

验证签发的证书:

  • 查看服务器证书内容:
    bash
    openssl x509 -in ../server.crt -text -noout

    检查 Issuer (应是您的 CA) 和 Subject (应是您的服务器信息)。特别要检查是否有 Subject Alternative Name 字段且内容正确。
  • 验证信任链:
    bash
    openssl verify -CAfile ca.crt ../server.crt

    这个命令检查 server.crt 是否能被 ca.crt 信任。如果输出 ../server.crt: OK 则表示验证成功。

部署:

server.keyserver.crt 文件部署到您的服务器软件(如 Nginx, Apache, Docker 容器等)配置中。在需要访问此服务的客户端机器上,导入 ca.crt 文件到系统的信任存储区,这样客户端就能信任您的私有 CA 签发的证书了。

场景三:生成用于提交给商业 CA 的 CSR

这是为公共网站申请 SSL 证书的标准流程。您只需要生成私钥和 CSR,然后将 CSR 提交给您选择的商业 CA(如 Let’s Encrypt, Sectigo, DigiCert, Cloudflare 等)。CA 会验证您的身份和域名所有权,然后用他们的 CA 根证书或中间证书签发您的服务器证书。

步骤详解:

  1. 创建服务器的私钥:
    与场景二类似,为服务器生成私钥。
    bash
    openssl genpkey -algorithm RSA -out your_domain.key -pkeyopt rsa_keygen_bits:2048
    # 或者
    # openssl genrsa -out your_domain.key 2048

    密钥文件名建议包含域名,以便区分。同样通常不设置密码。

  2. 创建用于提交的 CSR:
    生成 CSR 的核心在于准确填写证书的主体信息和 Subject Alternative Name (SAN)。对于商业证书,CN 字段通常填写主域名,而所有需要保护的域名(包括 www 和非 www 版本,以及可能的子域名)都必须列在 SAN 中。

    同样,建议使用配置文件来定义 SAN。使用与场景二类似的 server.cnf 文件,但请务必将 CNalt_names 中的域名修改为您的实际域名。

    例如,修改 server.cnf 中的相关行:
    “`ini
    [ req_distinguished_name ]
    C = CN
    ST = Beijing
    L = Beijing
    O = Your Company Name
    OU = Web Security
    CN = your_primary_domain.com # 主域名

    [ v3_req ]

    … 其他保持不变

    subjectAltName = @alt_names

    [ alt_names ]
    DNS.1 = your_primary_domain.com
    DNS.2 = www.your_primary_domain.com
    DNS.3 = blog.your_primary_domain.com # 其他子域名
    “`
    填写组织信息时,请确保与您向 CA 注册或提供的信息一致,特别是组织名称 (O) 和组织单位 (OU),这对于组织验证型 (OV) 或扩展验证型 (EV) 证书很重要。对于域名验证型 (DV) 证书,这些信息不太关键,主要依赖 SAN。

    使用配置文件生成 CSR:
    bash
    openssl req -new -key your_domain.key -out your_domain.csr -config server.cnf

    * req: 证书请求工具。
    * -new: 创建新的请求。
    * -key your_domain.key: 指定私钥文件。
    * -out your_domain.csr: 输出 CSR 文件。
    * -config server.cnf: 指定包含 SAN 和主体信息的配置文件。

执行命令后:

您将得到 your_domain.key (私钥) 和 your_domain.csr (CSR) 文件。

验证 CSR:

在提交给 CA 之前,务必验证 CSR 的内容,特别是主体信息和 SAN 是否正确。
bash
openssl req -in your_domain.csr -text -noout -verify

* req: 证书请求工具。
* -in your_domain.csr: 指定输入的 CSR 文件。
* -text: 显示 CSR 的文本内容。
* -noout: 不输出编码后的 CSR 文件本身。
* -verify: 验证 CSR 的签名。

检查输出中的 “Subject” 和 “Subject Alternative Name” 字段,确保所有域名都已包含且拼写正确。

提交 CSR:

your_domain.csr 文件的内容(通常是 PEM 编码的文本,以 -----BEGIN CERTIFICATE REQUEST----- 开头,以 -----END CERTIFICATE REQUEST----- 结尾)复制或上传到商业 CA 网站的相应界面。

接收和安装证书:

完成 CA 的验证流程后,CA 会颁发您的服务器证书 (your_domain.crt) 以及可能需要的中间 CA 证书链文件 (ca-chain.crt 或类似名称)。

您需要将 your_domain.key (私钥)、your_domain.crt (您的证书) 以及 CA 提供的中间证书链文件一起部署到您的服务器软件中。具体的配置方法取决于您使用的服务器软件(如 Nginx, Apache, IIS 等)。

四、 重要的注意事项和最佳实践

  • 私钥安全: 私钥是证书安全的核心。务必妥善保管您的私钥文件 (.key),设置严格的文件权限(例如只有运行服务器进程的用户可以读取)。如果私钥泄露,您的证书就失去了安全可信性,需要立即吊销并重新申请。
  • SAN 的重要性: 对于现代网站,总是使用 Subject Alternative Name (SAN) 来指定域名。仅依赖 Common Name (CN) 是不够的,并且许多浏览器会显示警告。
  • 密钥算法和长度: 当前推荐使用 RSA 2048 位或 4096 位密钥,或 ECC 算法的密钥。ECC 密钥通常更短但提供同等或更高的安全性,且性能更好。生成 ECC 密钥和 CSR 的命令略有不同,例如 openssl ecparam -genkey -name prime256v1 -out server.key 然后用这个 key 生成 CSR。
  • 证书有效期: 根据需求设置证书的有效期。短有效期(如 Let’s Encrypt 的 90 天)可以提高安全性(私钥泄露的窗口期更短),但也需要更频繁的续期操作。
  • 证书链: 部署证书时,除了您的服务器证书,通常还需要安装由 CA 提供的一系列中间证书。这构成了从您的证书到受浏览器信任的根证书之间的信任链。如果缺少中间证书,客户端可能无法验证您的证书。
  • Passphrase (密码): 生成私钥时可以选择加密(设置密码)。这提供了额外的安全性,但如前所述,可能会影响服务器的自动化启动。权衡利弊后选择是否使用。
  • 备份: 务必备份您的私钥、证书和 CA 根证书(如果是私有 CA)。

五、 常见问题与故障排除

  • 权限问题: OpenSSL 命令需要写入文件,请确保您运行命令的用户有足够的权限在指定目录创建文件。
  • 文件不存在: 如果命令中引用的私钥、CSR 或配置文件路径不正确,OpenSSL 会报错文件找不到。仔细检查路径。
  • Passphrase 错误: 如果私钥是加密的,在读取时需要输入正确的密码。如果忘记密码,通常无法恢复,只能重新生成密钥和证书。
  • req 命令交互式输入问题: 如果您没有使用 -subj 选项或配置文件,OpenSSL 会逐个提示您输入证书主体信息。请按提示输入或留空(有些字段可以留空)。
  • CA 签发失败: 使用 openssl ca 命令时,失败的原因可能包括:index.txtserial 文件不存在或权限问题;openssl.cnf 配置错误(特别是 dir, 签发策略,扩展定义);CSR 文件有问题或已被 CA 拒绝签发过(检查 index.txt 中的记录)。

六、 总结

OpenSSL 是一个功能强大的工具,掌握其基本用法对于理解和管理 SSL/TLS 证书至关重要。本文详细介绍了使用 OpenSSL 生成自签名证书、由自定义 CA 签名的证书以及为商业 CA 生成 CSR 的步骤。无论您是进行内部测试、构建企业信任体系还是为公共网站申请证书,OpenSSL 都能提供所需的命令行支持。

理解私钥、CSR、证书和 CA 之间的关系,以及掌握 OpenSSL 命令的常用参数,将使您能够更自信地处理各种证书相关的任务,确保您的网络通信安全可靠。请始终注意保护好您的私钥,这是 SSL/TLS 安全的基石。


发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部