openssl-selfsigned-cert

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

OpenSSL Self-Signed Certificate Creation

使用OpenSSL创建自签名SSL/TLS证书

This skill provides guidance for creating self-signed SSL/TLS certificates using OpenSSL command-line tools, including proper verification and scripting approaches.
本技能将指导你使用OpenSSL命令行工具创建自签名SSL/TLS证书,包括正确的验证方法和脚本编写方案。

Core Workflow

核心流程

Step 1: Create Directory Structure

步骤1:创建目录结构

Establish the output directory before generating any files:
bash
mkdir -p /path/to/certs
在生成任何文件之前,先创建输出目录:
bash
mkdir -p /path/to/certs

Step 2: Generate Private Key

步骤2:生成私钥

Generate an RSA private key (2048-bit minimum, 4096-bit recommended for production):
bash
openssl genrsa -out /path/to/certs/server.key 2048
生成RSA私钥(最小2048位,生产环境建议使用4096位):
bash
openssl genrsa -out /path/to/certs/server.key 2048

Step 3: Create Self-Signed Certificate

步骤3:创建自签名证书

Generate the certificate using the private key:
bash
openssl req -new -x509 -key /path/to/certs/server.key -out /path/to/certs/server.crt -days 365 -subj "/CN=localhost"
Adjust the
-subj
parameter as needed for the use case. Common fields:
  • /CN=
    - Common Name (domain or hostname)
  • /O=
    - Organization
  • /OU=
    - Organizational Unit
  • /C=
    - Country (2-letter code)
  • /ST=
    - State/Province
  • /L=
    - Locality/City
使用私钥生成证书:
bash
openssl req -new -x509 -key /path/to/certs/server.key -out /path/to/certs/server.crt -days 365 -subj "/CN=localhost"
可根据使用场景调整
-subj
参数。常见字段说明:
  • /CN=
    - 通用名称(域名或主机名)
  • /O=
    - 组织
  • /OU=
    - 组织单元
  • /C=
    - 国家(两位代码)
  • /ST=
    - 州/省
  • /L=
    - 地区/城市

Step 4: Create Combined PEM File (if required)

步骤4:创建合并PEM文件(如有需要)

Combine the key and certificate into a single PEM file:
bash
cat /path/to/certs/server.key /path/to/certs/server.crt > /path/to/certs/combined.pem
将密钥和证书合并为单个PEM文件:
bash
cat /path/to/certs/server.key /path/to/certs/server.crt > /path/to/certs/combined.pem

Step 5: Verify Generated Files

步骤5:验证生成的文件

Verify the certificate and key are valid and matching:
bash
undefined
验证证书和密钥是否有效且匹配:
bash
undefined

Verify certificate

验证证书

openssl x509 -in /path/to/certs/server.crt -text -noout
openssl x509 -in /path/to/certs/server.crt -text -noout

Verify key

验证密钥

openssl rsa -in /path/to/certs/server.key -check -noout
openssl rsa -in /path/to/certs/server.key -check -noout

Verify key matches certificate (modulus should match)

验证密钥与证书是否匹配(模数需一致)

openssl x509 -noout -modulus -in /path/to/certs/server.crt | openssl md5 openssl rsa -noout -modulus -in /path/to/certs/server.key | openssl md5
undefined
openssl x509 -noout -modulus -in /path/to/certs/server.crt | openssl md5 openssl rsa -noout -modulus -in /path/to/certs/server.key | openssl md5
undefined

Writing Verification Scripts

编写验证脚本

When creating Python scripts for certificate verification, follow these critical guidelines:
编写Python证书验证脚本时,请遵循以下关键准则:

Prefer Standard Library Over External Dependencies

优先使用标准库而非外部依赖

Avoid external dependencies like
cryptography
unless absolutely necessary. The script must work in the target execution environment without relying on virtual environments or pip-installed packages.
Recommended approaches (in order of preference):
  1. Use
    subprocess
    to call OpenSSL commands
    - Most reliable, no dependencies:
python
import subprocess

def verify_certificate(cert_path):
    """Verify certificate using OpenSSL subprocess calls."""
    result = subprocess.run(
        ["openssl", "x509", "-in", cert_path, "-text", "-noout"],
        capture_output=True,
        text=True
    )
    return result.returncode == 0, result.stdout
  1. Use Python's built-in
    ssl
    module
    - Standard library, always available:
python
import ssl

def load_certificate(cert_path):
    """Load and parse certificate using ssl module."""
    context = ssl.create_default_context()
    context.load_cert_chain(certfile=cert_path)
    return True
  1. If external libraries are required, install system-wide (not in virtual environment):
bash
pip install cryptography  # Not: uv add, pip install in venv
除非绝对必要,否则避免使用
cryptography
等外部依赖
。脚本必须能在目标执行环境中运行,无需依赖虚拟环境或pip安装的包。
推荐方案(按优先级排序):
  1. 使用
    subprocess
    调用OpenSSL命令
    - 最可靠,无依赖:
python
import subprocess

def verify_certificate(cert_path):
    """Verify certificate using OpenSSL subprocess calls."""
    result = subprocess.run(
        ["openssl", "x509", "-in", cert_path, "-text", "-noout"],
        capture_output=True,
        text=True
    )
    return result.returncode == 0, result.stdout
  1. 使用Python内置的
    ssl
    模块
    - 标准库,始终可用:
python
import ssl

def load_certificate(cert_path):
    """Load and parse certificate using ssl module."""
    context = ssl.create_default_context()
    context.load_cert_chain(certfile=cert_path)
    return True
  1. 若必须使用外部库,请在系统全局安装(而非虚拟环境中):
bash
pip install cryptography  # 不要使用:uv add、虚拟环境内的pip install

Script Execution Environment

脚本执行环境

Critical consideration: Test scripts the same way they will be executed in the final environment.
  • If the test runs
    python /path/to/script.py
    , verify with exactly that command
  • Do NOT rely on
    uv run python
    or virtual environment activation
  • System Python must have access to all required modules
关键注意事项: 测试脚本时,需采用与最终环境完全相同的执行方式。
  • 如果测试时运行
    python /path/to/script.py
    ,则必须用完全相同的命令验证
  • 不要依赖
    uv run python
    或虚拟环境激活
  • 系统Python必须能访问所有所需模块

Complete Python Script Template

完整Python脚本模板

python
#!/usr/bin/env python3
"""Certificate verification script using only standard library."""

import subprocess
import sys
import os

def verify_certificate(cert_path):
    """Verify a certificate file exists and is valid."""
    if not os.path.exists(cert_path):
        return False, f"Certificate file not found: {cert_path}"

    result = subprocess.run(
        ["openssl", "x509", "-in", cert_path, "-text", "-noout"],
        capture_output=True,
        text=True
    )

    if result.returncode != 0:
        return False, f"Invalid certificate: {result.stderr}"

    return True, result.stdout

def verify_key(key_path):
    """Verify a private key file exists and is valid."""
    if not os.path.exists(key_path):
        return False, f"Key file not found: {key_path}"

    result = subprocess.run(
        ["openssl", "rsa", "-in", key_path, "-check", "-noout"],
        capture_output=True,
        text=True
    )

    if result.returncode != 0:
        return False, f"Invalid key: {result.stderr}"

    return True, "Key is valid"

def verify_key_cert_match(key_path, cert_path):
    """Verify that a key and certificate match."""
    key_modulus = subprocess.run(
        ["openssl", "rsa", "-noout", "-modulus", "-in", key_path],
        capture_output=True,
        text=True
    )

    cert_modulus = subprocess.run(
        ["openssl", "x509", "-noout", "-modulus", "-in", cert_path],
        capture_output=True,
        text=True
    )

    if key_modulus.stdout == cert_modulus.stdout:
        return True, "Key and certificate match"
    return False, "Key and certificate do not match"

if __name__ == "__main__":
    # Example usage - adjust paths as needed
    cert_path = "/path/to/server.crt"
    key_path = "/path/to/server.key"

    success, msg = verify_certificate(cert_path)
    print(f"Certificate: {'PASS' if success else 'FAIL'} - {msg[:100] if success else msg}")

    success, msg = verify_key(key_path)
    print(f"Key: {'PASS' if success else 'FAIL'} - {msg}")

    success, msg = verify_key_cert_match(key_path, cert_path)
    print(f"Match: {'PASS' if success else 'FAIL'} - {msg}")
python
#!/usr/bin/env python3
"""Certificate verification script using only standard library."""

import subprocess
import sys
import os

def verify_certificate(cert_path):
    """Verify a certificate file exists and is valid."""
    if not os.path.exists(cert_path):
        return False, f"Certificate file not found: {cert_path}"

    result = subprocess.run(
        ["openssl", "x509", "-in", cert_path, "-text", "-noout"],
        capture_output=True,
        text=True
    )

    if result.returncode != 0:
        return False, f"Invalid certificate: {result.stderr}"

    return True, result.stdout

def verify_key(key_path):
    """Verify a private key file exists and is valid."""
    if not os.path.exists(key_path):
        return False, f"Key file not found: {key_path}"

    result = subprocess.run(
        ["openssl", "rsa", "-in", key_path, "-check", "-noout"],
        capture_output=True,
        text=True
    )

    if result.returncode != 0:
        return False, f"Invalid key: {result.stderr}"

    return True, "Key is valid"

def verify_key_cert_match(key_path, cert_path):
    """Verify that a key and certificate match."""
    key_modulus = subprocess.run(
        ["openssl", "rsa", "-noout", "-modulus", "-in", key_path],
        capture_output=True,
        text=True
    )

    cert_modulus = subprocess.run(
        ["openssl", "x509", "-noout", "-modulus", "-in", cert_path],
        capture_output=True,
        text=True
    )

    if key_modulus.stdout == cert_modulus.stdout:
        return True, "Key and certificate match"
    return False, "Key and certificate do not match"

if __name__ == "__main__":
    # Example usage - adjust paths as needed
    cert_path = "/path/to/server.crt"
    key_path = "/path/to/server.key"

    success, msg = verify_certificate(cert_path)
    print(f"Certificate: {'PASS' if success else 'FAIL'} - {msg[:100] if success else msg}")

    success, msg = verify_key(key_path)
    print(f"Key: {'PASS' if success else 'FAIL'} - {msg}")

    success, msg = verify_key_cert_match(key_path, cert_path)
    print(f"Match: {'PASS' if success else 'FAIL'} - {msg}")

Common Pitfalls

常见陷阱

1. Virtual Environment Isolation

1. 虚拟环境隔离问题

Problem: Installing dependencies in a virtual environment (venv, uv) that won't be available when the script runs in the test/production environment.
Solution: Either use standard library only, or install dependencies system-wide with
pip install
(not
uv add
or
pip install
inside an activated venv).
问题: 在虚拟环境(venv、uv)中安装的依赖,在脚本运行的测试/生产环境中不可用。
解决方案: 要么仅使用标准库,要么用
pip install
在系统全局安装依赖(而非
uv add
或虚拟环境内的pip install)。

2. Incomplete File Writes

2. 文件写入不完整

Problem: File write operations may be truncated or incomplete.
Solution: Always verify file contents after writing critical files:
bash
cat /path/to/file  # Verify contents
wc -l /path/to/file  # Verify line count
问题: 文件写入操作可能被截断或不完整。
解决方案: 写入关键文件后,务必验证文件内容:
bash
cat /path/to/file  # 验证内容
wc -l /path/to/file  # 验证行数

3. Testing in Wrong Environment

3. 错误环境测试

Problem: Running
uv run python script.py
succeeds but
python script.py
fails.
Solution: Always test with the exact command that will be used in production/testing. If tests run
python /app/script.py
, verify with exactly that command.
问题:
uv run python script.py
运行成功,但
python script.py
运行失败。
解决方案: 始终使用生产/测试环境中实际会用到的命令进行测试。如果测试时运行
python /app/script.py
,则必须用完全相同的命令验证。

4. Assuming OpenSSL Availability

4. 假设OpenSSL已安装

Problem: Script assumes OpenSSL is installed and in PATH.
Solution: Check for OpenSSL availability at script start:
python
import shutil
if not shutil.which("openssl"):
    sys.exit("Error: OpenSSL not found in PATH")
问题: 脚本假设OpenSSL已安装且在PATH中。
解决方案: 在脚本启动时检查OpenSSL是否可用:
python
import shutil
if not shutil.which("openssl"):
    sys.exit("Error: OpenSSL not found in PATH")

Verification Checklist

验证检查清单

Before declaring the task complete:
  1. All required files exist and have correct content
  2. Certificate is valid:
    openssl x509 -in cert.crt -text -noout
    succeeds
  3. Key is valid:
    openssl rsa -in key.key -check -noout
    succeeds
  4. Key and certificate modulus match
  5. Combined PEM contains both key and certificate (if required)
  6. Python script runs successfully with system Python (not venv)
  7. All file paths in scripts match actual file locations
在任务完成前,请确认:
  1. 所有所需文件均存在且内容正确
  2. 证书有效:
    openssl x509 -in cert.crt -text -noout
    执行成功
  3. 密钥有效:
    openssl rsa -in key.key -check -noout
    执行成功
  4. 密钥与证书模数匹配
  5. 合并PEM文件包含密钥和证书(如有需要)
  6. Python脚本可通过系统Python成功运行(非虚拟环境)
  7. 脚本中的所有文件路径与实际文件位置一致