OpenSSL 安装与配置

作者:金步国


版权声明

本文作者是一位开源理念的坚定支持者,所以本文虽然不是软件,但是遵照开源的精神发布。

其他作品

本文作者十分愿意与他人分享劳动成果,如果你对我的其他翻译作品或者技术文章有兴趣,可以在如下位置查看现有的作品集:

联系方式

由于作者水平有限,因此不能保证作品内容准确无误。如果你发现了作品中的错误(哪怕是错别字也好),请来信指出,任何提高作品质量的建议我都将虚心接纳。


系统需求

OpenSSL可以在多种操作系统上安装,但本文只讨论 OpenSSL-4.0 在Linux或BSD系统上的安装。

安装OpenSSL的系统需求很低,只要有 ANSI C-99 编译器(推荐GCC)、Perl 、make 即可。

配置

将下载回来的压缩包解压,进入解压后的目录,即可使用 Configure 脚本进行配置。OpenSSL的配置脚本与大多数典型的软件包不同,它不是基于 Autoconf+Automake 的shell脚本,而是一个Perl脚本,因此,它有自己的一套规则。详细的安装信息位于源码树下的 INSTALL.mdConfigure 文件中。安装后的使用与配置信息位于 doc 目录中(由该目录派生的OpenSSL官方文档网站是最权威的参考资料)。

可在 Configure 命令行上使用的配置选项分为两类:一类是以"-"开头的非功能选项,另一类是成对出现的功能选项[ enable-xxxx | no-xxxx ](有些选项可以省略"enable-"),分别表示开启和关闭。有些功能默认开启、有些功能默认关闭(具体可以到 Configure 脚本中搜索 "@disablables", "%deprecated_disablables", "%disabled" 关键字),以下列表中出现的配置选项都是非默认状态。由于选项众多,此处仅介绍对Linux/BSD生产环境有实际意义的选项。

--prefix=PREFIX
安装目录(默认=/usr/local),其中包含 bin, lib, include, share/man, share/doc/openssl 等子目录。
--openssldir=DIR
数据目录(默认=PREFIX/ssl),其中包含配置文件(openssl.cnf)、证书、密钥。
--libdir=DIR
库文件目录(默认=PREFIX/lib),其中包含 libcrypto.so 与 libssl.so 文件。
no-deprecated
取消对已废弃老旧API的支持
no-comp
取消对压缩库的支持(无法交换压缩证书)。
enable-brotli-dynamic
启用 Brotli 压缩/解压缩支持(动态连接)
zlib-dynamic
启用 zlib 压缩/解压缩支持(动态连接)
enable-zstd-dynamic
启用 Zstd 压缩/解压缩支持(动态连接)
enable-ktls
使用内核TLS提升性能,并允许在TLS套接字上使用 sendfile 和 splice 系统调用。
no-autoload-config
禁止自动加载默认的 openssl.cnf 配置文件
no-cmp
取消对证书管理协议(RFC 9810, Certificate Management Protocol)和证书请求消息格式(RFC 9045, Certificate Request Message Format)的支持。也就是删除 openssl-cmp 命令的相关功能。
no-cms
取消对加密消息语法(RFC 5652, Cryptographic Message Syntax)的支持。也就是删除 openssl-cms 命令的相关功能。
no-ct
取消对证书透明度(RFC 9162, Certificate Transparency)的支持。
no-dgram
取消对 UDP BIO 的支持。此选项还会强制取消对 DTLS 的支持。
no-docs
不安装各种形式的文档(手册页)。
no-http
取消对 HTTP 的支持。
no-legacy
取消对老旧 provider 的支持。
no-nextprotoneg
取消对TLS扩展 NPN (Next Protocol Negotiation) 的支持。NPN 已经被 ALPN (RFC 7301, Application-Layer Protocol Negotiation) 取代。
no-ocsp
取消对在线证书状态协议(OCSP, Online Certificate Status Protocol)的支持。
enable-pie
编译内存位置无关的可执行文件(Position Independent Execution)
no-psk
取消对基于预共享密钥(Pre-Shared Key)的密码套件的支持。
no-rfc3779
取消对 RFC3779 (X.509 IP地址和AS标识符的扩展) 的支持。
sctp
添加对流控制传输协议(RFC 9260, Stream Control Transmission Protocol)的支持。
no-sock
取消对 socket BIO 的支持。
no-srp
取消对安全远程密码协议(Secure Remote Password protocol)及相关密码套件的支持。目前普遍认为SRP安全性不佳,已是过时的协议。
no-srtp
取消对安全实时传输协议(RFC 3711, Secure Real-Time Transport Protocol)的支持。
no-ssl-trace
从 libssl 库中移除 SSL_trace() 函数,以减小二进制文件的体积。这也将同时从 s_client 与 s_server 命令中移除 -trace 功能。
enable-tfo
添加对TCP扩展"快速打开"(RFC7413, TCP Fast Open)的支持。此扩展可以有效提高TCP连接的建立速度。
no-quic
取消对 QUIC (HTTP/3) 的支持。
enable-sslkeylog
添加对 SSLKEYLOGFILE 环境变量的支持。将此环境变量设置为一个文件路径,用于记录 TLS 握手期间交换的密钥,供 Wireshark 等分析工具使用。因为使用此机制允许使用密钥日志文件中的密钥解密捕获数据包中的应用程序有效负载,所以会带来严重的安全隐患。
no-ts
取消对时间戳权威服务(RFC 3161, Time Stamping Authority)的支持。"TSA"是指颁发可信时间戳的第三方机构。可信时间戳可以证明特定数据在特定时间点之前已经存在,且数据所有者也无法篡改时间戳。
enable-unstable-qlog
添加对对 QUIC 协议 qlog 输出的支持。此功能尚不稳定(规范的草案版本),未来可能会发生不兼容的变化。
no-{tls|tls1|tls1_1|tls1_2|tls1_3|dtls|dtls1|dtls1_2}
取消对指定 TLS/DTLS 协议的支持。"no-tls"表示禁用所有TLS协议,"no-dtls"表示禁用所有DTLS协议。[提示]所有SSL协议已经被彻底移除。
no-integrity-only-ciphers
取消对仅能用于完整性验证的算法的支持。
no-{tls1|tls1_1|tls1_2|dtls1|dtls1_2}-method
取消对显式选择特定协议版本的支持。[提示]所有SSL协议已经被彻底移除。
no-{aria|bf|blake2|camellia|cast|chacha|cmac|des|dh|dsa|ec|ec2m|ecdh|ecdsa|hmac-drbg-kdf|idea|kbkdf|krb5kdf|md4|mdc2|ml-dsa|ml-kem|ocb|poly1305|pvkkdf|rc2|rc4|rmd160|scrypt|seed|siphash|siv|slh-dsa|sm2|sm3|sm4|snmpkdf|srtpkdf|sshkdf|sskdf|x942kdf|x963kdf|whirlpool}
取消对指定算法的支持。
-Dxxx, -Ixxx, -Wp, -lxxx, -Lxxx, -Wl, -rpath, -R, -framework, -static
这些是传递给编译器的选项,用于定义预处理器符号、指定其他库、库目录或其他编译器选项。

编译、测试、安装

然后使用 make 命令编译。如果编译成功,那么最好使用 make test 进行一下测试。

如果测试也通过了,那么接下来就是安装和配置了。安装很简单,一条 make install 命令即可。你还可以使用 make install DESTDIR=/other/dir 来将 /other/dir 当作"根"进行安装,这通常用于打包。

配置

安装完毕之后,接下来就是配置。OpenSSL的配置文件 openssl.cnf 位于 --openssldir 指定的目录下,下面是一个我本人实际使用的 openssl.cnf 文件,仅供参考。

#############################################################################
# OpenSSL-4.0 配置文件示范(亦兼容v3.5) [注意]这个示范配置的内容并不是默认值 #
#############################################################################
# 默认位置 (RedHat系)/etc/pki/tls/openssl.cnf (Debian系)/etc/ssl/openssl.cnf
# 可以使用环境变量 OPENSSL_CONF 或命令行选项 -config 指定一个非默认位置的 openssl.cnf

########
# 语法 #
########
#
# [ 小节 ]
# 变量 = 值
#
# 语法很简单(man 5 config),一看就懂,但是有几点需要说明:
# 1. 左右方括号内的空格是可以省略的,等号两边的空格也是可以省略的。
# 2. 可以通过 .include = 绝对路径 语法引入其他配置文件或配置目录(*.cnf 与 *.conf)。
# 3. 同一小节内的多个同名变量,仅以最后一个为准。为了在同一小节中多次配置同一个变量,可以使用"prefix.变量"形式。
# 4. 可以在字符串值中使用 ${变量} 的形式引用同一小节中的变量,使用 ${小节::变量} 的形式引用其它小节中的变量。
# 4. 可以在字符串值中使用 ${ENV::变量} 的形式引用操作系统中的环境变量(高优先级)与"默认小节"中的变量(低优先级)。
# 5. 变量必须定义在前、引用在后。
# 6. 可以在字符串值两边使用引号界定(一对单引号或一对双引号),从而允许在字符串首尾包含空格。
# 7. 可以在字符串值中使用 \ 转义某些特殊字符( \\, \n, \r, \b, \t )。

############
# 默认小节 #
############
# 默认小节比较特殊,必须放在所有小节之前且没有小节头。
# 默认小节的优先级最低,仅当其它小节中的变量不存在时,才会使用默认小节中的作为替补。

# 操作系统环境变量的替补值,防止操作系统中不存在所需的变量。仅供配置文件内部使用,不会反向影响操作系统环境。
HOME = /var/tmp

# 任何配置错误都将完全阻止对服务的访问(方便诊断配置错误,生产环境慎用)
config_diagnostics = 1

# 配置 OpenSSL 库(libcrypto.so, libssl.so)初始化的索引小节的名称
openssl_conf = openssl_init

###############################################################
# (第一部分)  OpenSSL 库(libcrypto.so, libssl.so)的初始化配置 #
###############################################################
# 初始化 OpenSSL 库(libcrypto.so, libssl.so)各功能模块所对应的小节名称(索引)
[ openssl_init ]
providers = algorithm_provider  # libcrypto.so
ssl_conf = ssl_configuration  # libssl.so
#(添加自定义的X.509v3 证书扩展对象) oid_section = new_oids
#(不懂别乱动)(EVP API 属性) alg_section = evp_properties
#(不懂别乱动,乱动埋大坑)(确定性随机比特生成器) random = random_generator

# 提供程序(provider)是指算法实现库。如果没有显式激活任何提供程序,则会隐式激活OpenSSL内置的默认提供程序。
# 如果显式激活了非默认提供程序(通常是一个第三方 .os 文件),那么必须显式激活OpenSSL内置的默认提供程序。
[ algorithm_provider ]
default = default_provider
legacy = legacy_provider
[ default_provider ]
activate = yes
[ legacy_provider ]
activate=no  # 仅需在 openssl pkcs12 使用 -legacy 选项时临时改为 yes

# 全局强制 TLS 属性(会覆盖应用程序设置)(兼容Win7)(man 3 SSL_CONF_cmd)
[ ssl_configuration ]
system_default = tls_system_default
[ tls_system_default ]
# 限定协议版本
TLS.MinProtocol = TLSv1.3
TLS.MaxProtocol = TLSv1.3
DTLS.MinProtocol = DTLSv1.2
DTLS.MaxProtocol = DTLSv1.2
# 混淆流量特征以隐藏真实数据长度(对抗流量分析、增强隐私保护)(建议600-640,过大的填充会增加带宽消耗和被动分片风险)
RecordPadding = 600
# 密码套件(v1.2/v1.3)(按优先级降序排列)(man 1 openssl-ciphers)(2020年后的移动设备都有AES-256硬件加速)
CipherString = TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
Ciphersuites = TLS_AES_256_GCM_SHA384
# 服务器证书签名方案(按优先级降序排列)(TLS SignatureScheme)(免费CA最高P-384)
SignatureAlgorithms = ecdsa_secp384r1_sha384:ecdsa_secp256r1_sha256:rsa_pkcs1_sha384:rsa_pkcs1_sha256
# 客户端证书签名方案(按优先级降序排列)(TLS SignatureScheme)(Chrome与Safari都不支持ed448,ed25519)
ClientSignatureAlgorithms = ecdsa_secp384r1_sha384
# 密钥协商算法(按优先级降序排列)(man 3 SSL_CTX_set1_curves)(Chrome不支持x448,secp521r1)
Groups = *secp384r1:*x25519
# 控制SSL库的行为(man 3 SSL_CTX_set_options)
# 禁止压缩应用层数据[CRIME攻击],禁止重新协商[中间人攻击],关闭中间盒兼容,支持内核TLS,支持零拷贝发送模式,支持发送压缩证书,支持接收压缩证书
Options = -Compression,NoRenegotiation,-MiddleboxCompat,KTLS,KTLSTxZerocopySendfile,TxCertificateCompression,RxCertificateCompression
# 客户端证书验证模式(Require=必须在握手前提供证书[更安全],RequiresPostHandshake=允许在握手后按需提供证书[安全性稍差])
#(切勿取消注释,除非你真的知道自己在做什么)(此设置仅用于严格受控的内部私有网络)VerifyMode = Peer,Require

####################################
# (第二部分)  与证书请求有关的配置 #
####################################
#### 这部分配置包含一个主配置小节(req)和三个附属小节(DN_fields, v3_req, v3_ca) ####
# 在向 CA 申请证书之前,需要首先创建 PKCS#10 格式的 X.509v3 证书签发请求(Certificate Signing Request)。
# (示例)首先生成P-384(secp384r1)密钥并明文(-noenc)保存到key文件,然后再为泛域名"*.example.com"创建SHA384证书签发请求并保存到csr文件
# openssl req -newkey ec -pkeyopt ec_paramgen_curve:secp384r1 -noenc -keyout example.com.key -subj '/C=CN/CN=*.example.com' -addext 'subjectAltName=DNS:*.example.com,DNS:example.com' -sha384 -out example.com.csr
# 如果要自建 CA 来签发证书(通常用于测试或企业内网环境),那么还需要首先创建一个自签名的根CA证书。
# (示例)首先生成P-384(secp384r1)密钥并明文(-noenc)保存到key文件,然后再为"RootCA"创建10年有效的SHA384自签名根CA证书并保存到crt文件
# openssl req -newkey ec -pkeyopt ec_paramgen_curve:P-384 -noenc -keyout RootCA.key -subj '/C=CN/CN=RootCA' -days 3650 -sha384 -x509 -addext 'basicConstraints=critical,CA:TRUE' -out RootCA.crt
# 上述两个 openssl req 命令,都可以根据实际需求作如下变化:
# 1.(推荐)在保存密钥(.key)时添加保护口令:将 -noenc 替换为 -cipher AES-256-CBC
# 1.(无交互)在保存密钥(.key)时添加保护口令:先将口令字符串保存为 keypw.txt 文件,再将 -noenc 替换为 -batch -cipher AES-256-CBC -passout file:keypw.txt
# 2.(强迫症)为密钥(.key)添加保护口令并指定加密参数(原地替换): openssl pkcs8 -topk8 -in private.key -out private.key -v2 aes-256-cbc -scrypt -saltlen 32
# 3.使用非 ASCII 字符:在命令行上添加 -utf8 以允许使用UTF-8字符(某些CA仅支持ASCII字符)
# 4.添加更多 X.509v3 证书扩展项:在命令行上添加更多 -addext (参考下面的 v3_req 与 v3_ca 小节)
# 5.对于某些签名算法(PQC,RSA-PSS,SM2),可能需要额外在命令行上使用 -sigopt 设置签名算法参数
# 6.显示详细的命令执行过程:在命令行上添加 -verbose

##### 这是主配置小节,其它附属小节都以它为索引 #####
[ req ]
# RSA密钥的默认长度(会被 -newkey rsa:长度 覆盖),必须是2的整数次方(建议不小于3072)
default_bits = 4096
# 保存密钥的默认文件名(会被 -keyout 覆盖)
default_keyfile = private.key
# 保存密钥文件时,默认是否使用口令保护(yes 等价于在命令行上使用 -cipher AES-256-CBC )(no 等价于在命令行上使用 -nodes )
encrypt_key = yes
# 读取/保存密钥文件所需口令的默认来源(会被 -passin/-passout 覆盖),语法参见 man 1 openssl-passphrase-options 手册
input_password = stdin
output_password = stdin
# 证书签名的默认摘要算法( sha384 等价于在命令行上使用 -sha384 )(可用算法参见 openssl dgst -list 命令)
default_md = sha384
# 是否将所有字符串都使用UTF-8编码(yes 等价于在命令行上使用 -utf8 )(默认值 no 表示仅使用ASCII编码)(某些CA仅支持ASCII编码)
utf8 = no
# 证书标识字段值(例如城市名称或组织名称)的默认编码类型( utf8only 是首选推荐值)( nombstr 仅用于尝试解决某些CA签名故障)
string_mask = utf8only
# 是否提示输入证书标识各字段的值(默认值=yes=从证书标识小节读取字段提示+以交互方式读取字段值)(no=无提示+直接从证书标识小节读取字段值)
prompt = yes
# 证书标识小节的名称(注意:证书标识小节的语法取决于 prompt 的值)
distinguished_name = DN_fields
# 用于定义加入证书请求中的一系列 X.509v3 扩展项的小节名称
req_extensions = v3_req
# 用于定义加入自签名根证书中的一系列 X.509v3 扩展项的小节名称
x509_extensions = v3_ca

##### "证书标识"小节定义了要在证书中包含哪些标识字段(会被 -subj 覆盖) #####
# 此小节有两种不同的语法(取决于 prompt 的值),这里仅展示当 prompt = yes 时的语法
# (当 prompt = no 时,语法更简单,就是按 key = value 格式依次列出全部标识字段即可)
[ DN_fields ]
countryName = (C)请输入两字母国家代码(输入 . 删除此字段) #提示信息
countryName_default = CN  #默认值
stateOrProvinceName = (ST)请输入省份或直辖市名称(输入 . 删除此字段) #提示信息
stateOrProvinceName_default = Guang Dong  #默认值
localityName = (L)清输入城市或区县名称(输入 . 删除此字段) #提示信息
localityName_default = Guang Zhou  #默认值
organizationName = (O)请输入组织名称或公司名称(输入 . 删除此字段) #提示信息
organizationName_default = XXX Company Ltd  #默认值
organizationalUnitName = (OU)请输入部门名称(输入 . 删除此字段) #提示信息
commonName = (CN)请输入公用名称(例如域名/个人姓名/公司名)(必填) #提示信息(这个字段通常是必需的)
emailAddress = 请输入Email地址(输入 . 删除此字段) #提示信息

##### 要加入证书请求中的一系列 X.509v3 证书扩展项(对应 -addext 命令行选项) #####
# 值带有"critical"前缀的表示该扩展项是关键扩展项,当应用程序无法识别该扩展项时,必须直接拒绝此证书。
[ v3_req ]
# 基本约束(该证书是否为CA证书)。"CA:FALSE"表示非CA证书(不能签发其他证书的"叶子证书")。
basicConstraints = critical,CA:FALSE
# 密钥用途(已删除无效及罕见用途):数字签名(digitalSignature)(必需)、防否认(nonRepudiation)(可选)、密钥加密(keyEncipherment)(仅RSA+EFS必需)
keyUsage = critical,digitalSignature
# 扩展密钥用途(按需选择):服务端验证(serverAuth)、客户端验证(clientAuth)、代码签名(codeSigning)、可信时间戳(timeStamping)、OCSP签名(OCSPSigning)、IPsec密钥交换(ipsecIKE)、微软EFS(msEFS)
extendedKeyUsage = serverAuth,clientAuth
# 主题备用名称(email, URI, DNS, RID, IP, dirName)(DNS常用于实现泛域名证书、"copy"表示直接从 DN_fields 复制)
#subjectAltName = DNS:example.com, DNS:*.example.net, IP:192.168.7.1, IP:13::17, email:copy
# TLS状态请求扩展(Apache/IIS/Nginx必需配合开启"OCSP Stapling"功能)("Let's Encrypt"等CA已抛弃OCSP并转向 Firefox CRLite / Chrome CRLSet 方案)(所有浏览器都不支持 status_request_v2 )
#tlsfeature = status_request

#### 生成自签名证书(-x509)时使用的 X.509v3 证书扩展项(对应 -addext 命令行选项) #####
# 值带有"critical"前缀的表示该扩展项是关键扩展项,当应用程序无法识别该扩展项时,必须直接拒绝此证书。
[ v3_ca ]
# 基本约束(该证书是否为CA证书)。"CA:TRUE"表示真CA证书(可签发其他证书)。"pathlen:0"表示禁止签发下级CA证书(仅能签发"叶子证书")。
basicConstraints = critical,CA:TRUE,pathlen:0
# 密钥用途(已删除无效及罕见用途):证书签发(keyCertSign)(必需)、证书撤销列表签名(cRLSign)(可选)、数字签名(digitalSignature)(可选)、防否认(nonRepudiation)(可选)、密钥加密(keyEncipherment)(仅RSA+EFS可选)
keyUsage = critical,keyCertSign
# 限制可签发的证书用途(按需选择):服务端验证(serverAuth)、客户端验证(clientAuth)、代码签名(codeSigning)、可信时间戳(timeStamping)、OCSP签名(OCSPSigning)、IPsec密钥交换(ipsecIKE)、微软EFS(msEFS)
#extendedKeyUsage = (默认无限制,仅在必须限制时,才需要取消注释并逐一列出允许的用途)
#(不懂别乱动)给证书自身生成"密钥标识符/密钥ID"的方法
subjectKeyIdentifier = hash
#(不懂别乱动)如何记录密钥标识符(帮助精确构建证书链)
authorityKeyIdentifier = keyid:always,issuer
# 主题备用名称(email, URI, DNS, RID, IP, dirName)(DNS常用于实现泛域名证书、"copy"表示直接从 DN_fields 复制)
#subjectAltName = DNS:example.com, DNS:*.example.net, IP:192.168.7.1, IP:13::17, email:copy

####################################
# (第三部分)  与证书签发有关的配置 #
####################################
#### 这部分配置包含两个主体小节(ca, CA_default)和两个个附属小节(usr_cert, policy_match) ####
# openssl x509openssl ca 都可用于签发X.509v3证书,
# 差别在于 x509 专注于处理证书(显示证书信息/转换证书格式/编辑证书信任设置/生成自签名证书/签发证书)且无须使用配置文件,
# 而 ca 专注于实现完整的CA功能(签发证书/管理吊销列表/管理证书数据库/批量签发证书)且必须使用配置文件。
# (示例)下面两个命令都是RootCA使用SHA384摘要算法为"example.com"签发了一张有效期为10年的证书
# openssl x509 -CA RootCA.crt -CAkey RootCA.key -sha384 -req -in example.com.csr -days 3650 -out example.com.crt -copy_extensions copyall
# openssl ca -cert RootCA.crt -keyfile RootCA.key -md sha384 -in example.com.csr -days 3650 -out example.com.crt -rand_serial -notext -batch
# 上述两个命令,都可以根据实际需求作如下变化:
# 1.使用无交互方式输入CA密钥(.key)的保护口令(若有):先将口令字符串保存为 keypw.txt 文件,再在命令行上添加 -passin file:keypw.txt
# 2.对于某些签名算法(PQC,RSA-PSS,SM2),可能需要额外在命令行上使用 -sigopt 设置签名算法参数
# 对于 ca 命令,还可根据实际需求作更多变化:
# 3.使用非 ASCII 字符:在命令行上添加 -utf8 以允许使用UTF-8字符
# 4.显示详细的命令执行过程:在命令行上添加 -verbose
# 若要将"example.com"证书用于客户端认证,则必须将"密钥+证书+友好名称"打包成一个PKCS#12格式的".p12"加密文件,才能导入Windows证书管理器
# openssl pkcs12 -inkey example.com.key -in example.com.crt -name "ExampleClient" -export -out example_client.p12 -no-CAfile -no-CApath -no-CAstore -keysig -pbmac1_pbkdf2 -iter 87456 -macsaltlen 20
# 此命令可以根据实际需求作如下变化:
# 1.使用无交互方式输入客户端密钥(.key)的保护口令(若有):先将口令字符串保存为 keypw.txt 文件,再在命令行上添加 -passin file:keypw.txt
# 2.使用无交互方式输入".p12"文件的保护口令(必需):先将口令字符串保存为 p12pw.txt 文件,再在命令行上添加 -passout file:p12pw.txt
# 3.如果需要导入Win7证书管理器:将命令行上的 -pbmac1_pbkdf2 替换为 -legacy -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES
# 4.如果希望导入私钥后,存储在Windows系统级的"本地计算机"存储区(HKEY_LOCAL_MACHINE),而非默认的"当前用户"存储区(HKEY_CURRENT_USER):在命令行上添加 -LMK

##### 默认CA配置小节,(★)标记表示该配置项必须存在 #####
[ ca ]
# 默认CA配置小节的名称
default_ca = CA_default
[ CA_default ]
#(★)CA自身证书文件的默认路径。对应 -cert 命令行选项。
certificate = RootCA.crt
#(★)CA自身私钥文件的默认路径。对应 -keyfile 命令行选项。
private_key = RootCA.key
#(★)新签发证书的默认有效天数。对应 -days 命令行选项。
default_days = 3650
#(★)签名使用的默认摘要算法。对应 -md 命令行选项。(可用算法参见 openssl dgst -list 命令)
default_md = sha384
#(★)存档已签发证书的默认目录(文件名=证书序列号.pem)。对应 -outdir 命令行选项。
new_certs_dir = /var/tmp
#(★)存档已签发证书简要信息的文本数据库。此文件必须预先存在(初始内容必须为空)。
database = /var/tmp/certs_index.txt
#(★)签发证书时是否使用随机序列号(强烈建议设为 yes)。对应 -rand_serial 命令行选项。(这是一个取代了"serial"的未文档化配置)
rand_serial = yes
# 同一个"subject"是否只能签发一个证书。强烈建议设为 no (默认值 yes 仅为兼容老旧的 0.9.8 版本)
unique_subject = no
# 显示证书详细信息的格式(不要去研究一堆没意义的显示格式,选择"ca_default"格式就是最明智的做法)
name_opt = ca_default
cert_opt  = ca_default
# 定义添加到新证书中的X.509v3扩展项的小节名称。对应 -extensions 命令行选项。
x509_extensions = usr_cert
# 如何处理证书签发请求中的扩展项。取值范围以及解释:
# none: 删除证书签发请求中的全部扩展项(默认值)
# copy: 仅将未出现在 usr_cert 小节中的扩展项复制到最终证书中
# copyall: 将证书签发请求中的全部扩展项都复制到最终证书中,并覆盖 usr_cert 小节中的同名扩展项。
# 此选项的主要用途是允许在证书签发请求中提供例如 subjectAltName 之类的扩展项。
copy_extensions = copy
# 是否保留证书签发请求中标识字段的顺序(yes=保留,对应于 -preserveDN 命令行选项)(no=使用证书策略小节中的顺序)
preserve = no
# 是否保留证书标识中的 EMAIL 字段(默认值=yes=保留)(no=删除,对应 -noemailDN 命令行选项)
email_in_dn = yes
#(★)定义证书标识字段匹配策略的小节名称。对应 -policy 命令行选项。
policy  = policy_match

##### 为签发的新证书添加X.509v3扩展项 #####
[ usr_cert ]
# 基本约束(该证书是否为CA证书)。"CA:FALSE"表示非CA证书(不能签发其他证书的"叶子证书")。
basicConstraints = critical,CA:FALSE
# 密钥用途(已删除无效及罕见用途):数字签名(digitalSignature)(必需)、防否认(nonRepudiation)(可选)、密钥加密(keyEncipherment)(仅RSA+EFS必需)
keyUsage = critical,digitalSignature
#(不懂别乱动) RFC5280推荐将使用者与颁发机构的密钥标识符同时包含在证书中(帮助精确构建证书链)
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always

##### 证书签发请求中标识字段的匹配策略(未在本小节中列出的字段将会被删除) #####
# match: 该字段在证书签发请求中的值必须与CA证书的同名字段值完全相同,否则拒签。
# supplied: 该字段在证书签发请求中必须存在(值可以不同),否则拒签。
# optional: 该字段在证书签发请求中可以存在也可以不存在(相当于没有要求)。
[ policy_match ]
countryName  = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName  = supplied
emailAddress  = optional