OpenSSL

密码学和 SSL/TLS 工具包

openssl-verification-options

名称

openssl-verification-options - 通用 X.509 证书验证选项

概要

openssl 命令 [ 选项 ... ] [ 参数 ... ]

描述

在 OpenSSL 库和各种 OpenSSL 命令中,存在许多需要验证 X.509 证书的情况。

证书验证由 X509_verify_cert(3) 实现。这是一个复杂的过程,包括多个步骤,并且取决于众多选项。以下部分将详细介绍其中最重要的选项。

简而言之,需要建立并验证一个有效的证书链,从要验证的目标证书开始,以由于某些策略而被信任的证书结束。验证是相对于给定的用途进行的,该用途是目标证书的预期用途,例如 SSL 服务器,或者默认情况下是任何用途。

每个 OpenSSL 命令如何处理错误的详细信息在特定命令页面上进行了记录。

DANE 支持在 openssl-s_client(1)SSL_CTX_dane_enable(3)SSL_set1_host(3)X509_VERIFY_PARAM_set_flags(3)X509_check_host(3) 中有记录。

信任锚点

一般来说,根据 RFC 4158 和 RFC 5280,信任锚点是任何出于某种原因被视为可信的公钥及其相关的主题区分名称 (DN),因此可以接受作为证书链的根。

在实践中,信任锚点以证书的形式给出,其中它们的必要字段是公钥和主题 DN。除了 RFC 5280 中的要求外,OpenSSL 还检查此类证书的有效期,并使用一些其他字段。特别是,如果存在,主题密钥标识符扩展用于在链构建过程中匹配信任锚点。

在最简单和最常见的情况下,信任锚点默认情况下是放置在信任存储中的所有自签名“根”CA 证书,信任存储是为某些用途而被信任的证书集合。这类似于 Mozilla Firefox 的信任存储,或者 Apple 和 Microsoft 的证书存储……

从 OpenSSL 的角度来看,信任锚点是一个证书,应该为其可以作为目标证书信任锚点的用途进行明确指定。在 PEM 编码中,这由TRUSTED CERTIFICATE 字符串表示。这种指定提供了一组积极的信任属性,明确地声明对列出的目的的信任,或者一组消极的信任属性,明确地拒绝对列出的目的的使用。目的使用为扩展密钥用途 (EKU) 定义的值进行编码,这些值可能在最终实体证书的 X.509 扩展中给出。另见下面的 "扩展密钥用途" 部分。

当前识别的用途是clientAuth(SSL 客户端使用)、serverAuth(SSL 服务器使用)、emailProtection(S/MIME 电子邮件使用)、codeSigning(对象签名者使用)、OCSPSigning(OCSP 响应者使用)、OCSP(OCSP 请求使用)、timeStamping(TSA 服务器使用)和anyExtendedKeyUsage。从 OpenSSL 1.1.0 开始,最后一个阻止了所有用途被拒绝或启用所有用途被信任。

如果且仅当以下所有条件都满足时,证书(可以是 CA 证书或最终实体证书)才被视为给定用途的信任锚点

  • 它是信任存储的元素。

  • 它没有拒绝给定用途的负面信任属性。

  • 它具有接受给定用途的正面信任属性,或者(默认情况下)以下兼容性条件之一适用:它是自签名的,或者给出了-partial_chain 选项(对应于设置了X509_V_FLAG_PARTIAL_CHAIN 标志)。

证书路径构建

首先,从目标证书开始,以信任锚点结束,构建一个证书链。

该链是通过迭代构建的,依次查找具有适合密钥用途的证书,该证书与当前“主题”证书的颁发者匹配,如下所述。如果有这样的证书,则采用当前有效的第一个找到的证书,否则采用最近过期的所有此类证书。为了提高效率,不执行回溯,因此忽略任何其他与之匹配的候选颁发者证书。

当添加了一个自签名证书时,证书链构建停止。在这种情况下,它必须完全匹配一个信任锚点,否则证书链构建将失败。

如果以下所有条件都满足,则候选颁发者证书与主题证书匹配

  • 它的主题名称与主题证书的颁发者名称匹配。

  • 如果主题证书具有授权密钥标识符扩展,则其每个子字段等于候选颁发者证书的对应主题密钥标识符、序列号和颁发者字段,只要这两个证书中都存在相应的字段。

  • 用于签署主题证书的证书签名算法受支持,并且等于候选颁发者证书的公钥算法。

查找首先在信任存储中搜索颁发者证书。如果在那里没有找到匹配项,则会查询提供的不可信(“中间”CA)证书列表。

证书路径验证

当证书链构建过程成功时,会彻底检查链组件及其链接。

第一步是检查每个证书是否格式正确。只有在给出了-x509_strict 选项时,才会启用这些检查的一部分。

第二步是检查每个不可信证书的扩展名,以确保它们与提供的用途一致。如果没有给出-purpose 选项,则不会进行此类检查,除非是 SSL/TLS 连接设置,在这种情况下,默认情况下会检查sslserversslclient。目标或“叶”证书以及任何其他不可信证书必须具有与指定用途兼容的扩展。除目标或“叶”证书之外的所有证书还必须是有效的 CA 证书。"openssl-x509(1) 中的证书扩展" 中更详细地描述了所需的确切扩展。

第三步是检查最后一个证书(通常是自签名根 CA 证书)上的信任设置。它必须对给定用途被信任。为了与以前版本的 OpenSSL 兼容,没有信任属性的自签名证书被认为对所有用途都是有效的。

第四步也是最后一步是检查证书链的有效性。对于链中的每个元素,包括根 CA 证书,都会检查由notBeforenotAfter 字段指定的有效期是否与当前系统时间一致。-attime 标志可用于使用除“现在”之外的参考时间。证书签名也已检查(除通常自签名的根 CA 证书的签名外,只有在给出了-check_ss_sig 选项时才验证此签名)。在验证证书签名时,会检查候选颁发者证书的 keyUsage 扩展名(如果存在),以允许 digitalSignature 用于签署代理证书,或允许 keyCertSign 用于签署其他证书。如果所有操作都成功完成,则证书被视为有效。如果任何操作失败,则证书无效。

选项

受信任证书选项

以下选项指定如何提供可以作为某些用途的信任锚点的证书。如前所述,此类证书的集合称为信任存储

请注意,OpenSSL 不会提供一组默认的信任锚点。许多 Linux 发行版都包含一个系统默认值,并配置 OpenSSL 指向该默认值。Mozilla 维护了一个有影响力的信任存储,可以在 https://www.mozilla.org/en-US/about/governance/policies/security-group/certs/ 中找到。

要添加到信任存储的证书可以使用以下选项指定。

-CAfile 文件

加载指定的文件,该文件包含 DER 格式的受信任证书,或者在输入为 PEM 格式的情况下可能包含多个受信任证书。PEM 编码的证书也可以设置信任属性。

-no-CAfile

不要加载受信任证书的默认文件。

-CApath 目录

将指定的目录用作受信任证书的集合,即信任存储。文件应以每个证书的 X.509 SubjectName 的哈希值命名。这样,库就可以提取 IssuerName,对其进行哈希处理,并直接查找文件以获取颁发者证书。有关创建此类目录的信息,请参见 openssl-rehash(1)

-no-CApath

不要使用受信任证书的默认目录。

-CAstore uri

uri 用作 CA 证书存储。URI 可以表示单个证书,也可以表示多个证书的集合。对于file: 方案中的 URI,这将充当-CAfile-CApath,具体取决于 URI 是否表示单个文件或目录。有关file: 方案的更多信息,请参见 ossl_store-file(7)

这些证书也用于构建服务器证书链(例如使用 openssl-s_server(1))或客户端证书链(例如使用 openssl-s_time(1))。

-no-CAstore

不要使用受信任 CA 证书的默认存储。

验证选项

可以使用以下标志微调证书验证。

-verbose

打印有关正在执行的操作的额外信息。

-attime 时间戳

使用时间戳指定的时间执行验证检查,而不是使用当前系统时间。时间戳是自 1970 年 1 月 1 日(即 Unix 纪元)以来的秒数。

-no_check_time

此选项将抑制检查证书和 CRL 的有效期是否与当前时间一致。如果使用-attime 选项指定验证时间,则不会抑制检查。

-x509_strict

这将禁用对损坏证书的非兼容解决方法。因此,对于不符合 RFC 5280 的证书,会抛出错误。

当设置此选项时,除其他外,还会检查以下证书格式正确性条件

  • CA 证书的 basicConstraints 必须标记为关键。

  • CA 证书必须明确包含 keyUsage 扩展。

  • 如果给出了 pathlenConstraint,则必须允许 keyUsage keyCertSign。

  • 对于非 CA 证书,不能给出 pathlenConstraint。

  • 任何证书的颁发者名称不能为空。

  • CA 证书、具有 keyUsage crlSign 的证书以及没有 subjectAlternativeName 的证书的主题名称不能为空。

  • 如果给出了 subjectAlternativeName 扩展,则它不能为空。

  • signatureAlgorithm 字段和证书签名必须一致。

  • 任何给定的 authorityKeyIdentifier 和任何给定的 subjectKeyIdentifier 不能标记为关键。

  • 对于 X.509v3 证书,除非它们是自签名的,否则必须给出 authorityKeyIdentifier。

  • 对于所有 X.509v3 CA 证书,必须给出 subjectKeyIdentifier。

-ignore_critical

通常,如果存在 OpenSSL 不支持的未处理关键扩展,则会拒绝证书(如 RFC5280 所要求)。如果设置了此选项,则会忽略关键扩展。

-issuer_checks

忽略。

-crl_check

通过尝试查找有效的 CRL 来检查最终实体证书的有效性。如果找不到有效的 CRL,则会发生错误。

-crl_check_all

通过尝试查找有效的 CRL 来检查链中所有证书的有效性。

-use_deltas

启用对增量 CRL 的支持。

-extended_crl

启用扩展 CRL 功能,例如间接 CRL 和备用 CRL 签名密钥。

-suiteB_128_only, -suiteB_128, -suiteB_192

分别启用 Suite B 模式在 128 位安全级别、128 位或 192 位,或仅 192 位安全级别下运行。有关详细信息,请参阅 RFC6460。特别是,支持的签名算法被简化为仅支持 ECDSA 和 SHA256 或 SHA384,以及仅支持椭圆曲线 P-256 和 P-384。

-auth_level 级别

将证书链身份验证安全级别设置为 级别。身份验证安全级别确定验证证书链时可接受的签名和公钥强度。要使证书链验证成功,所有证书的公钥必须满足指定的安全 级别。签名算法安全级别对链中的所有证书强制执行,但链的 信任锚 除外,信任锚要么是直接受信任的,要么是通过除其签名以外的其他方式验证的。有关可用级别的定义,请参阅 SSL_CTX_set_security_level(3)。默认安全级别为 -1 或“未设置”。在安全级别 0 或更低级别,所有算法都是可接受的。安全级别 1 要求至少 80 位等效安全级别,并且具有广泛的互操作性,但它将拒绝 MD5 签名或短于 1024 位的 RSA 密钥。

-partial_chain

允许验证成功,即使可以构建不完整的链。也就是说,链以通常不受信任的证书结束(因为它没有匹配的正信任属性,并且不是自签名的),但它是信任存储的元素。此证书可以是自签发的,也可以属于中间 CA。

-check_ss_sig

如果证书据说是自签名的,则验证链中最后一个证书的签名。如果它是非符合的 CA 证书,其密钥使用限制不包括 keyCertSign 位,则这是禁止的,会导致错误。此验证默认情况下被禁用,因为它不会增加任何安全性。

-allow_proxy_certs

允许验证代理证书。

-trusted_first

从 OpenSSL 1.1.0 开始,此选项默认情况下已启用,无法禁用。

在构建证书链时,通过 -CAfile-CApath-CAstore-trusted 指定的受信任证书始终在通过 -untrusted 指定的任何证书之前使用。

-no_alt_chains

从 OpenSSL 1.1.0 开始,由于 -trusted_first 始终启用,因此此选项无效。

-trusted 文件

文件 解析为一组一个或多个证书。如果具有合适的正信任属性,或者它是自签名的,或者指定了 -partial_chain 选项,则每个证书都符合受信任条件。此选项意味着 -no-CAfile-no-CApath-no-CAstore 选项,并且不能与 -CAfile-CApath-CAstore 选项一起使用,因此仅使用 -trusted 选项指定的证书才是信任锚。此选项可以使用多次。

-untrusted 文件

文件 解析为一组一个或多个证书。所有证书(通常为中间 CA)都被认为是不可信的,可用于从目标证书构建到信任锚的证书链。此选项可以使用多次。

-policy 参数

启用策略处理并将 参数 添加到用户初始策略集(请参阅 RFC5280)。策略 参数 可以是对象名称,也可以是数字形式的 OID。此参数可以出现多次。

-explicit_policy

设置策略变量 require-explicit-policy(请参阅 RFC5280)。

-policy_check

启用证书策略处理。

-policy_print

打印与策略处理相关的诊断信息。

-inhibit_any

设置策略变量 inhibit-any-policy(请参阅 RFC5280)。

-inhibit_map

设置策略变量 inhibit-policy-mapping(请参阅 RFC5280)。

-purpose 用途

证书的预期用途。当前定义的用途是 sslclientsslservernssslserversmimesignsmimeencryptcrlsignocsphelpertimestampsigncodesignany。如果启用了对等证书验证,则默认情况下,TLS 实现以及命令 s_clients_server 会分别检查与 TLS 服务器或 TLS 客户端使用的兼容性。

虽然 IETF RFC 5280 指出 id-kp-serverAuthid-kp-clientAuth 仅用于 WWW 使用,但实际上它们被用于所有类型的 TLS 客户端和服务器,这就是 OpenSSL 所假设的情况。

-verify_depth 数字

将证书链限制为 数字 个中间 CA 证书。最大深度链最多可以包含 数字 + 2 个证书,因为最终实体证书和信任锚证书都不计入 -verify_depth 限制。

-verify_email 电子邮件

验证 电子邮件 是否与主题备用名称中的电子邮件地址或主题区分名称中的电子邮件匹配。

-verify_hostname 主机名

验证 主机名 是否与主题备用名称中的 DNS 名称或主题证书中的通用名称匹配。

-verify_ip IP

验证 IP 是否与主题证书的主题备用名称中的 IP 地址匹配。

-verify_name 名称

使用默认验证策略,如由 名称 标识的信任模型和所需的证书策略。信任模型决定哪些辅助信任或拒绝 OID 适用于验证给定的证书链。它们可以使用 openssl-x509(1)-addtrust-addreject 选项给出。支持的策略名称包括:defaultpkcs7smime_signssl_clientssl_server。这些模拟 SSL、CMS 和 S/MIME 中使用的用途和信任设置的组合。从 OpenSSL 1.1.0 开始,信任模型是从未指定时推断出的用途,因此 -verify_name 选项在功能上等效于相应的 -purpose 设置。

扩展验证选项

有时可能存在多个通向最终实体证书的证书链。这通常发生在根 CA 或中间 CA 为其他组织的 CA 签署证书时。另一个原因是 CA 可能具有使用两种不同签名格式的中间证书,例如 SHA-1 和 SHA-256 摘要。

以下选项可用于提供数据,使 OpenSSL 命令能够生成备用链。

-xkey 输入文件-xcert 输入文件-xchain

指定额外的证书、私钥和证书链。这些选项的行为方式与 -cert-key-cert_chain 选项相同。指定后,返回第一个有效链的回调将被客户端使用。

-xchain_build

指定应用程序是否应该构建要通过 -xkey-xcert-xchain 选项提供给服务器的额外证书的证书链。

-xcertform DER|PEM|P12

额外证书的输入格式。此选项无效,仅保留用于向后兼容性。

-xkeyform DER|PEM|P12

额外密钥的输入格式。此选项无效,仅保留用于向后兼容性。

证书扩展

-purpose 这样的选项会导致检查证书扩展,这些扩展决定了目标证书和中间 CA 证书的使用方式。

基本约束

basicConstraints 扩展 CA 标志用于确定证书是否可以作为 CA 使用。如果 CA 标志为真,则它是 CA;如果 CA 标志为假,则它不是 CA。所有 CA 都应该将 CA 标志设置为真。

如果 basicConstraints 扩展不存在(包括它是 X.509v1 证书的情况),则该证书被认为是“可能的 CA”,并且根据证书的预期用途检查其他扩展。目前支持将没有 basicConstraints 的证书作为 CA 处理,但这可能会在将来发生变化。

密钥使用

如果存在 keyUsage 扩展,则会对证书的使用进行额外的限制。如果存在 keyUsage 扩展,则 CA 证书必须设置 keyCertSign 位。

扩展密钥使用

extKeyUsage (EKU) 扩展对证书用途施加了额外的限制。如果存在此扩展(无论是关键的还是非关键的),则密钥只能用于指定的目的。

下面给出了每个检查的完整描述。关于 basicConstraints 和 keyUsage 以及 X.509v1 证书的上述评论适用于所有 CA 证书。

SSL 客户端

扩展密钥使用扩展必须不存在,或者包含“Web 客户端身份验证”OID。keyUsage 扩展必须不存在,或者它必须设置 digitalSignature 位。Netscape 证书类型必须不存在,或者它必须设置 SSL 客户端位。

SSL 客户端 CA

扩展密钥使用扩展必须不存在,或者包含“Web 客户端身份验证”OID。Netscape 证书类型必须不存在,或者它必须设置 SSL CA 位。这用作基本约束扩展不存在时的解决方法。

SSL 服务器

扩展密钥使用扩展必须不存在,或者包含“Web 服务器身份验证”和/或 SGC OID 之一。keyUsage 扩展必须不存在,或者它必须设置 digitalSignature、keyEncipherment 或两个位。Netscape 证书类型必须不存在,或者设置 SSL 服务器位。

SSL 服务器 CA

扩展密钥使用扩展必须不存在,或者包含“Web 服务器身份验证”和/或 SGC OID 之一。Netscape 证书类型必须不存在,或者设置 SSL CA 位。这用作基本约束扩展不存在时的解决方法。

Netscape SSL 服务器

要使 Netscape SSL 客户端连接到 SSL 服务器,如果存在 keyUsage 扩展,则它必须设置 keyEncipherment 位。这并不总是有效的,因为一些密码套件使用密钥进行数字签名。否则,它与普通的 SSL 服务器相同。

常见的 S/MIME 客户端测试

扩展密钥使用扩展必须不存在,或者包含“电子邮件保护”OID。Netscape 证书类型必须不存在,或者应设置 S/MIME 位。如果 Netscape 证书类型中未设置 S/MIME 位,则 SSL 客户端位会被容忍作为替代方案,但会显示警告。这是因为某些 Verisign 证书没有设置 S/MIME 位。

S/MIME 签名

除了常见的 S/MIME 客户端测试之外,如果存在 keyUsage 扩展,则必须设置 digitalSignature 位或 nonRepudiation 位。

S/MIME 加密

除了常见的 S/MIME 测试之外,如果存在 keyUsage 扩展,则必须设置 keyEncipherment 位。

S/MIME CA

扩展密钥使用扩展必须不存在,或者包含“电子邮件保护”OID。Netscape 证书类型必须不存在,或者必须设置 S/MIME CA 位。这用作基本约束扩展不存在时的解决方法。

CRL 签名

keyUsage 扩展必须不存在,或者它必须设置 CRL 签名位。

CRL 签名 CA

适用于正常的 CA 测试。但在此情况下,basicConstraints 扩展必须存在。

错误

颁发者检查仍然存在于底层 X509_LOOKUP API 中的局限性。这会导致一个结果,即具有匹配主题名称的受信任证书必须出现在文件中(由 -CAfile 选项指定)、目录中(由 -CApath 选项指定)或存储中(由 -CAstore 选项指定)。如果存在多个这样的匹配项(可能位于多个位置),则仅识别第一个匹配项(按上述位置顺序)。

另请参阅

X509_verify_cert(3)openssl-verify(1)openssl-ocsp(1)openssl-ts(1)openssl-s_client(1)openssl-s_server(1)openssl-smime(1)openssl-cmp(1)openssl-cms(1)

历史

OpenSSL 3.0 中扩展了 -x509_strict 启用的检查。

版权所有 2000-2023 OpenSSL 项目作者。保留所有权利。

根据 Apache 许可证 2.0(“许可证”)授权。除符合许可证外,您不得使用本文件。您可以在源代码分发中的 LICENSE 文件或 https://www.openssl.org/source/license.html 中获取一份副本。