OpenSSL 自签名证书:安全测试与开发环境配置 – wiki词典

OpenSSL 自签名证书:安全测试与开发环境配置

在现代软件开发中,安全是不可或缺的一环。无论是进行安全测试、本地开发还是构建原型,我们常常需要使用 SSL/TLS 加密来模拟生产环境的行为。然而,每次都从可信的证书颁发机构(CA)获取真实证书既耗时又昂贵。这时,OpenSSL 自签名证书就成为了一个理想的解决方案。

本文将详细介绍如何使用 OpenSSL 创建自签名证书,并将其应用于安全测试和开发环境,确保你的本地环境能够安全、高效地模拟真实世界的加密通信。

什么是自签名证书?

自签名证书是一种由其创建者自己签名的数字证书,而不是由外部受信任的证书颁发机构(如 Let’s Encrypt、DigiCert 等)签发。由于没有第三方信任链,浏览器和操作系统通常会默认不信任自签名证书,并发出安全警告。

尽管如此,自签名证书在以下场景中非常有用:

  1. 本地开发环境:在 localhost 上运行 HTTPS 服务,模拟生产环境。
  2. 安全测试:测试应用程序在 HTTPS 下的行为,验证 SSL/TLS 配置。
  3. 内部工具/服务:在受控的内部网络中使用 HTTPS,而无需购买商业证书。
  4. API Mocking:为本地测试的 API 端点提供 HTTPS 加密。

准备工作:安装 OpenSSL

OpenSSL 是一个强大的开源命令行工具包,用于处理 SSL/TLS 协议和密码学功能。

  • Linux/macOS:通常预装了 OpenSSL。如果未安装,可以使用包管理器进行安装(例如,sudo apt install opensslbrew install openssl)。
  • Windows:推荐下载并安装 OpenSSL for Windows 的预编译版本。可以在 https://wiki.openssl.org/index.php/Binaries 找到下载链接,或者使用 Scoop、Chocolatey 等包管理器安装。安装后,请确保 OpenSSL 可执行文件路径已添加到系统 PATH 环境变量中。

第一步:创建根证书颁发机构 (Root CA)

为了模拟一个真实的证书颁发链,我们将首先创建一个自签名的根证书颁发机构(Root CA)。这个 CA 将用于签发我们自己的服务器证书。

1. 生成根 CA 的私钥:

bash
openssl genrsa -aes256 -out rootCA.key 2048

  • genrsa:生成 RSA 私钥。
  • -aes256:使用 AES 256 位加密私钥(推荐,会提示你设置一个密码)。
  • -out rootCA.key:输出私钥文件名为 rootCA.key
  • 2048:私钥的位数。

2. 生成根 CA 证书:

bash
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 3650 -out rootCA.crt

  • req:用于生成 CSR 或自签名证书。
  • -x509:输出自签名的证书而不是 CSR。
  • -new:创建一个新请求。
  • -nodes:不加密私钥(即不使用密码),这在自动化脚本中可能很有用,但在生产 CA 中不推荐。如果之前加密了 rootCA.key,这里会提示你输入密码。
  • -key rootCA.key:指定用于签名的私钥。
  • -sha256:使用 SHA256 算法进行签名。
  • -days 3650:证书有效期为 3650 天(约 10 年)。
  • -out rootCA.crt:输出证书文件名为 rootCA.crt

在执行此命令时,你需要填写一些证书信息,例如国家(C)、省份(ST)、城市(L)、组织(O)和通用名称(CN)。对于 Root CA,通用名称可以设置为 My Development Root CA 或类似名称。

第二步:为服务器生成证书

现在我们有了 Root CA,可以利用它来签发我们的服务器证书。假设我们想为 localhostdev.example.com 生成证书。

1. 生成服务器的私钥:

bash
openssl genrsa -out server.key 2048

这里我们通常不加密服务器私钥,以便 web 服务器能够直接读取。

2. 生成证书签名请求 (CSR):

bash
openssl req -new -key server.key -out server.csr

  • -new:创建一个新请求。
  • -key server.key:指定服务器的私钥。
  • -out server.csr:输出 CSR 文件名为 server.csr

在填写信息时,通用名称(CN至关重要,它必须与你的域名(例如 localhostdev.example.com)匹配。如果通用名称不匹配,浏览器将发出警告。

3. 创建 OpenSSL 配置文件以添加 SAN (Subject Alternative Name) 扩展:

现代浏览器要求证书包含 Subject Alternative Name (SAN) 扩展,以便支持多个域名或 IP 地址,并确保安全性。创建一个名为 server.ext 的文件,内容如下:

“`ini
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = localhost
DNS.2 = dev.example.com
IP.1 = 127.0.0.1
“`

根据你的需求修改 DNSIP 条目。

4. 使用 Root CA 签发服务器证书:

bash
openssl x509 -req -in server.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out server.crt -days 365 -sha256 -extfile server.ext

  • x509:用于证书操作。
  • -req:表示输入是 CSR。
  • -in server.csr:指定输入的 CSR 文件。
  • -CA rootCA.crt:指定用于签名的 Root CA 证书。
  • -CAkey rootCA.key:指定用于签名的 Root CA 私钥。
  • -CAcreateserial:自动创建或更新一个用于记录已签发证书序列号的文件(通常名为 rootCA.srl)。
  • -out server.crt:输出签发后的服务器证书文件名为 server.crt
  • -days 365:服务器证书有效期为 365 天。
  • -sha256:使用 SHA256 算法。
  • -extfile server.ext:指定用于添加扩展的配置文件。

现在你已经有了三个文件:
* rootCA.crt:你的根 CA 证书。
* server.key:你的服务器私钥。
* server.crt:由你的 Root CA 签发的服务器证书。

第三步:在开发环境中使用证书

要让浏览器或客户端信任你的自签名证书,你需要将 rootCA.crt 导入到你的操作系统或浏览器的信任存储中。

1. 信任 Root CA 证书:

  • Windows:双击 rootCA.crt 文件,选择 “安装证书”,然后选择 “将所有证书放入下列存储”,点击 “浏览” 选择 “受信任的根证书颁发机构”,然后完成安装。
  • macOS:双击 rootCA.crt 文件, keychain access 会打开,将其添加到 “登录” 或 “系统” 钥匙串中。然后,在证书详情中,展开 “信任” 部分,选择 “始终信任”。
  • Linux (Firefox/Chrome)
    • Firefox:在 “设置” -> “隐私与安全” -> “证书” -> “查看证书” -> “证书机构” 中导入 rootCA.crt,并选择 “信任此 CA 以标识网站”。
    • Chrome/Chromium:通常会读取操作系统的信任存储。如果不行,你可能需要手动导入到 NSS 数据库或通过系统设置。

一旦你的 Root CA 被信任,所有由它签发的证书(包括 server.crt)都将被你的系统和浏览器视为有效。

2. 配置 Web 服务器:

以下是配置常见 Web 服务器的示例:

  • Nginx (nginx.conf 示例):

    “`nginx
    server {
    listen 443 ssl;
    server_name localhost dev.example.com; # 对应证书的 CN 和 SAN

    ssl_certificate /path/to/server.crt;
    ssl_certificate_key /path/to/server.key;
    
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    
    location / {
        proxy_pass http://localhost:8000; # 你的后端服务
        # ... 其他配置
    }
    

    }
    “`

  • Apache (httpd-ssl.conf 或虚拟主机配置示例):

    apache
    <VirtualHost *:443>
    ServerName localhost
    SSLEngine on
    SSLCertificateFile "/path/to/server.crt"
    SSLCertificateKeyFile "/path/to/server.key"
    # SSLCipherSuite HIGH:!aNULL
    # SSLProtocol all -SSLv2 -SSLv3
    # ... 其他配置
    </VirtualHost>

  • Node.js (Express 示例):

    “`javascript
    const express = require(‘express’);
    const https = require(‘https’);
    const fs = require(‘fs’);

    const app = express();

    const options = {
    key: fs.readFileSync(‘/path/to/server.key’),
    cert: fs.readFileSync(‘/path/to/server.crt’)
    };

    app.get(‘/’, (req, res) => {
    res.send(‘Hello HTTPS!’);
    });

    https.createServer(options, app).listen(3000, () => {
    console.log(‘HTTPS Server running on port 3000’);
    });
    “`

/path/to/server.crt/path/to/server.key 替换为你的证书和私钥的实际路径。

常见问题与故障排除

  • “您的连接不是私密连接” 或 “NET::ERR_CERT_COMMON_NAME_INVALID”

    • 检查服务器证书的通用名称(CN)或 SAN 字段是否与你访问的域名匹配。
    • 确认已将 rootCA.crt 正确导入到操作系统的信任存储中。
  • “无法建立安全连接”

    • 检查 Web 服务器是否已正确配置 SSL/TLS。
    • 确保服务器私钥(server.key)没有被密码加密,或者 Web 服务器在启动时能够访问密码。
    • 确认证书和私钥文件的权限设置正确,Web 服务器进程有读取权限。
  • 证书过期

    • 自签名证书的有效期有限。如果证书过期,需要重新生成并重新导入信任。在开发环境中,可以设置较长的有效期(例如 3650 天)。

总结

通过遵循本文的步骤,你已经成功创建了一个自签名的 Root CA,并用它签发了服务器证书。将 Root CA 导入你的信任存储后,你就可以在本地开发和安全测试环境中使用 HTTPS,模拟真实的生产环境。

这种方法不仅免费且灵活,还让你完全控制证书的生命周期,是开发和测试阶段进行安全实践的强大工具。在生产环境中,请务必使用由受信任 CA 签发的有效证书。

滚动至顶部