OpenSSL 证书扩展字段全解与实战示例

本文档旨在提供一份最全、最易懂的 X.509 v3 证书扩展字段说明。我们将晦涩的专业术语翻译成大白话,并为每一个扩展字段都提供了命令行 (-addext)配置文件 (openssl.cnf) 两种实战写法。


目录

  1. 基础限制类 (Basic Constraints, Key Usage...)
  2. 身份标识类 (SAN, SKI, AKI...)
  3. 信息与管理类 (CRL, AIA, Policies...)
  4. 高级与特殊类 (Name Constraints, TLS Feature...)
  5. 完整的配置文件模板

1. 基础限制类

这些字段决定了证书“能干什么”以及“能不能传给别人”。

1.1 Basic Constraints (基本约束)

  • 一句话解释:标记这张证书是“大老板” (CA) 还是“普通员工” (终端实体)。
  • 通俗理解:如果是 CA,它就能给别人发证;如果是普通员工,只能自己用。
  • 关键参数
    • CA: TRUE (老板) 或 FALSE (员工)。
    • pathlen: (可选) 只有老板才有。限制下面能有几层“小老板”。0 表示只能直管员工,不能有下级经理。

实战示例

场景 A:普通服务器证书 (员工)

  • 命令行: -addext "basicConstraints = critical, CA:FALSE"
  • 配置文件:
    basicConstraints = critical, CA:FALSE
    

场景 B:根证书 (大老板)

  • 命令行: -addext "basicConstraints = critical, CA:TRUE"
  • 配置文件:
    basicConstraints = critical, CA:TRUE
    

1.2 Key Usage (密钥用法)

  • 一句话解释:限制这把钥匙具体能开哪扇门。
  • 通俗理解:这把钥匙是用来签合同的(签名),还是用来加密保险箱的(加密),还是用来发证的(签发证书)。
  • 关键参数
    • digitalSignature: 数字签名 (验证身份)。
    • keyEncipherment: 密钥加密 (HTTPS 握手用)。
    • keyCertSign: 签发证书 (CA 必备)。
    • cRLSign: 签发吊销列表 (CA 必备)。

实战示例

场景 A:HTTPS 网站证书

  • 命令行: -addext "keyUsage = critical, digitalSignature, keyEncipherment"
  • 配置文件:
    keyUsage = critical, digitalSignature, keyEncipherment
    

场景 B:CA 根证书

  • 命令行: -addext "keyUsage = critical, keyCertSign, cRLSign"
  • 配置文件:
    keyUsage = critical, keyCertSign, cRLSign
    

1.3 Extended Key Usage (增强密钥用法 - EKU)

  • 一句话解释:指定证书的具体应用场景。
  • 通俗理解:这虽然是张身份证,但我想明确它只能用于“开服务器”或者“写代码”。
  • 关键参数
    • serverAuth: 网站服务器 (HTTPS)。
    • clientAuth: 客户端身份验证 (双向认证)。
    • codeSigning: 代码签名。
    • emailProtection: 邮件加密。

实战示例

场景:既做服务器又做客户端

  • 命令行: -addext "extendedKeyUsage = serverAuth, clientAuth"
  • 配置文件:
    extendedKeyUsage = serverAuth, clientAuth
    

2. 身份标识类

这些字段告诉别人“我是谁”,“我的备用名是什么”,“我的上级是谁”。

2.1 Subject Alternative Name (SAN - 主体备用名称)

  • 一句话解释最重要字段。列出证书适用的所有域名、IP 或邮箱。
  • 通俗理解:证书的“真名”是 CN,但浏览器现在只看 SAN。这里可以写“大名”、“小名”、“英文名”和“家庭住址”。
  • 关键参数DNS, IP, email, URI

实战示例

场景:多域名和 IP

  • 命令行: -addext "subjectAltName = DNS:example.com, DNS:*.example.com, IP:192.168.1.1"
  • 配置文件:
    subjectAltName = @alt_names
    
    [ alt_names ]
    DNS.1 = example.com
    DNS.2 = *.example.com
    IP.1 = 192.168.1.1
    

2.2 Subject Key Identifier (SKI - 主体密钥标识符)

  • 一句话解释:给你的公钥打个指纹。
  • 通俗理解:为了防止同名同姓搞混,给这把钥匙算一个唯一的 ID。
  • 关键参数hash (自动计算,推荐)。

实战示例

  • 命令行: -addext "subjectKeyIdentifier = hash"
  • 配置文件:
    subjectKeyIdentifier = hash
    

2.3 Authority Key Identifier (AKI - 授权密钥标识符)

  • 一句话解释:指明是谁(哪把钥匙)签发了这张证书。
  • 通俗理解:这上面写着“我爸是李刚(的ID)”,方便浏览器顺藤摸瓜找到上级证书。
  • 关键参数keyid:always (总是包含密钥ID), issuer (包含颁发者名称,可选)。

实战示例

  • 命令行: -addext "authorityKeyIdentifier = keyid:always, issuer"
  • 配置文件:
    authorityKeyIdentifier = keyid:always, issuer
    

2.4 Issuer Alternative Name (IAN - 颁发者备用名称)

  • 一句话解释:颁发者(CA)的备用联系方式。
  • 通俗理解:如果你找不到发证机构的正式地址,可以试试这些备用地址。
  • 现状极少使用,通常直接看颁发者信息就够了。

实战示例

  • 命令行: -addext "issuerAltName = DNS:ca.example.org"
  • 配置文件:
    issuerAltName = issuer_alt_section
    
    [ issuer_alt_section ]
    DNS.1 = ca.example.org
    

3. 信息与管理类

这些字段告诉别人“去哪查我的状态”或者“我有什么政策”。

3.1 CRL Distribution Points (CRL 分发点)

  • 一句话解释:去哪里下载“黑名单”(证书吊销列表)。
  • 通俗理解:如果我犯事了被吊销了,你可以去这个网址查到我的名字。
  • 关键参数URI

实战示例

  • 命令行: -addext "crlDistributionPoints = URI:http://crl.example.com/ca.crl"
  • 配置文件:
    crlDistributionPoints = crl_section
    
    [ crl_section ]
    fullname = URI:http://crl.example.com/ca.crl
    

3.2 Authority Info Access (AIA - 授权信息访问)

  • 一句话解释:去哪里在线验证证书状态 (OCSP),或者去哪里下载上级证书。
  • 通俗理解
    1. OCSP: “打电话问问警察局(CA),这人现在是不是好人”。
    2. caIssuers: “如果你没见过我爸(上级CA),去这下载他的照片(证书)”。

实战示例

  • 命令行: -addext "authorityInfoAccess = OCSP;URI:http://ocsp.example.com, caIssuers;URI:http://crt.example.com/ca.crt"
  • 配置文件:
    authorityInfoAccess = @aia_section
    
    [ aia_section ]
    OCSP;URI.0 = http://ocsp.example.com
    caIssuers;URI.0 = http://crt.example.com/ca.crt
    

3.3 Certificate Policies (证书策略)

  • 一句话解释:证书的使用条款和法律声明。
  • 通俗理解:就像软件的“用户协议”,通常给一个链接 (CPS) 让你去读。

实战示例

  • 命令行: 较复杂,建议用配置文件。
  • 配置文件:
    certificatePolicies = @pol_section
    
    [ pol_section ]
    policyIdentifier = 1.3.6.1.4.1.12345.1.1
    CPS.1 = "http://cps.example.com/legal.html"
    

4. 高级与特殊类

这些字段通常用于非常具体的场景。

4.1 Name Constraints (名称约束)

  • 一句话解释CA 专用。限制这个 CA 只能签发特定后缀的域名。
  • 通俗理解:给了你盖章的权力,但规定你“只能批 .com 的地皮,不能批 .cn 的”。
  • 关键参数permitted (允许), excluded (禁止)。

实战示例

场景:只允许签发 example.com 下的证书

  • 命令行: -addext "nameConstraints = permitted;DNS:example.com"
  • 配置文件:
    nameConstraints = @name_constraints
    
    [ name_constraints ]
    permitted;DNS.0 = example.com
    excluded;IP.0 = 0.0.0.0/0.0.0.0  # 禁止签发任何 IP 证书
    

4.2 TLS Feature (TLS 功能扩展)

  • 一句话解释:强制浏览器检查特定 TLS 功能。最常用的是 OCSP Must Staple
  • 通俗理解:强制要求:“我不光要出示身份证,我还得同时出示今天的‘无犯罪记录证明’(OCSP Stapling),否则别信我”。
  • 关键参数status_request (即 OCSP Must Staple)。

实战示例

  • 命令行: -addext "tlsfeature = status_request"
  • 配置文件:
    tlsfeature = status_request
    

4.3 Netscape Comment (NS 注释)

  • 一句话解释已过时。以前 Netscape 浏览器用的,现在仅用于给人看个备注。
  • 通俗理解:在证书里写一句“到此一游”。

实战示例

  • 命令行: -addext "nsComment = This is a generated cert"
  • 配置文件:
    nsComment = "This is a generated cert"
    

5. 完整的配置文件模板

复制以下内容保存为 my_cert.cnf,根据需要修改 [ v3_req ] 下的内容。

# =============================================================
# OpenSSL 证书生成配置文件模板
# =============================================================

[ req ]
default_bits        = 2048
distinguished_name  = req_distinguished_name
req_extensions      = v3_req     # 生成 CSR 时读取此段
x509_extensions     = v3_req     # 生成自签名证书时读取此段
string_mask         = utf8only
prompt              = no         # 不交互,直接读取下方 DN

[ req_distinguished_name ]
C  = CN
ST = Beijing
L  = Beijing
O  = MyCompany
OU = Tech Dept
CN = my.example.com

[ v3_req ]
# -------------------------------------------------------------
# 1. 基础限制
# -------------------------------------------------------------
basicConstraints = critical, CA:FALSE
keyUsage         = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth, clientAuth

# -------------------------------------------------------------
# 2. 身份标识 (最重要的部分)
# -------------------------------------------------------------
subjectAltName       = @alt_names
subjectKeyIdentifier = hash

# -------------------------------------------------------------
# 3. 信息与管理 (可选)
# -------------------------------------------------------------
# authorityKeyIdentifier = keyid:always, issuer
# crlDistributionPoints  = URI:http://crl.example.com/ca.crl
# authorityInfoAccess    = OCSP;URI:http://ocsp.example.com

[ alt_names ]
DNS.1 = my.example.com
DNS.2 = www.example.com
DNS.3 = localhost
IP.1  = 127.0.0.1
IP.2  = 192.168.0.100

四下皆无人