6. Certification Path Validation (证书路径验证)
互联网PKI的证书路径验证过程基于 [X.509] 中提供的算法. 证书路径处理验证主体可辨别名称和/或主体备用名称与主体公钥之间的绑定. 绑定受组成路径的证书中指定的约束以及依赖方指定的输入的限制. 基本约束和策略约束扩展允许证书路径处理逻辑自动化决策过程.
本节描述了验证证书路径的算法. 此规范的符合实现不要求 (not required) 实现此算法, 但必须 (MUST) 提供与此过程产生的外部行为等效的功能. 特定实现可以使用任何算法, 只要它得出正确的结果.
在第6.1节中, 文本描述基本路径验证. 有效路径以信任锚 (trust anchor) 颁发的证书开始. 该算法需要CA的公钥、CA的名称以及可以使用此密钥验证的路径集的任何约束.
信任锚的选择是策略问题: 它可以是分层PKI中的顶级CA、颁发验证者自己证书的CA或网络PKI中的任何其他CA. 无论选择哪个信任锚, 路径验证过程都是相同的. 此外, 不同的应用程序可能依赖不同的信任锚, 或可能接受以一组信任锚中的任何一个开始的路径.
第6.2节描述在特定实现中使用路径验证算法的方法.
第6.3节描述当CRL是证书颁发者使用的撤销机制时确定证书是否已被撤销所需的步骤.
6.1. Basic Path Validation (基本路径验证)
本文描述X.509路径处理算法. 符合标准的实现必须 (MUST) 包含在功能上等效于此算法的外部行为的X.509路径处理过程. 但是, 对此算法中处理的某些证书扩展的支持对于符合标准的实现是可选的 (OPTIONAL). 不支持这些扩展的客户端可以 (MAY) 省略路径验证算法中的相应步骤.
例如, 不要求客户端支持策略映射扩展. 不支持此扩展的客户端可以 (MAY) 省略处理策略映射的路径验证步骤. 请注意, 如果证书包含不受支持的关键扩展, 则客户端必须 (MUST) 拒绝该证书.
虽然本文档第4节和第5节中指定的证书和CRL配置文件指定了被认为适合互联网PKI的证书和CRL字段和扩展的值, 但本节中介绍的算法并不限于接受符合这些配置文件的证书和CRL. 因此, 该算法仅包括验证证书路径根据X.509有效的检查, 不包括验证证书和CRL是否符合此配置文件的检查. 虽然可以扩展算法以包括对第4节和第5节中配置文件的符合性检查, 但此配置文件建议 (RECOMMENDS) 不要包括此类检查.
本节中介绍的算法相对于当前日期和时间验证证书. 符合标准的实现也可以 (MAY) 支持相对于过去某个时间点的验证. 请注意, 没有可用的机制来验证相对于证书有效期之外时间的证书.
信任锚是算法的输入. 不要求使用相同的信任锚来验证所有证书路径. 可以 (MAY) 使用不同的信任锚来验证不同的路径, 如第6.2节中进一步讨论的.
路径验证的主要目标是验证主体可辨别名称或主体备用名称与主体公钥之间的绑定, 如目标证书中表示的, 基于信任锚的公钥. 在大多数情况下, 目标证书将是终端实体证书, 但只要主体公钥用于除验证公钥证书上的签名之外的目的, 目标证书也可以是CA证书. 验证名称和主体公钥之间的绑定需要获取支持该绑定的证书序列. 获取此证书序列所执行的过程超出此规范的范围.
为了满足此目标, 路径验证过程验证, 除其他事项外, 预期证书路径 (n个证书的序列) 满足以下条件:
(a) 对于 {1, ..., n-1} 中的所有x, 证书x的主体是证书x+1的颁发者;
(b) 证书1由信任锚颁发;
(c) 证书n是要验证的证书 (即, 目标证书); 以及
(d) 对于 {1, ..., n} 中的所有x, 证书在相关时间有效.
证书禁止 (MUST NOT) 在预期证书路径中出现多次.
当信任锚以自签名证书的形式提供时, 此自签名证书不包括作为预期证书路径的一部分. 有关信任锚的信息作为证书路径验证算法的输入提供 (第6.1.1节).
但是, 特定证书路径可能不适合所有应用程序. 因此, 应用程序可以 (MAY) 扩展此算法以进一步限制有效路径集. 路径验证过程还根据证书策略扩展、策略映射扩展、策略约束扩展和禁止anyPolicy扩展确定对此路径有效的证书策略集. 为实现此目的, 路径验证算法构造有效策略树 (valid policy tree). 如果对此路径有效的证书策略集不为空, 则结果将是深度为n的有效策略树, 否则结果将是空有效策略树.
如果相同的DN出现在主体和颁发者字段中 (如果根据第7.1节中指定的规则匹配, 则两个DN相同), 则证书是自签发的 (self-issued). 通常, 组成路径的证书的颁发者和主体对于每个证书都是不同的. 但是, CA可能向自己颁发证书以支持密钥转换或证书策略的更改. 在评估路径长度或名称约束时, 不计算这些自签发证书.
本节以四个基本步骤介绍算法: (1) 初始化, (2) 基本证书处理, (3) 为下一个证书准备, 以及 (4) 收尾. 步骤 (1) 和 (4) 恰好执行一次. 步骤 (2) 对路径中的所有证书执行. 步骤 (3) 对路径中除最后一个证书之外的所有证书执行. 图2提供了此算法的高级流程图.
+-------+
| START |
+-------+
|
V
+----------------+
| Initialization |
+----------------+
|
+<--------------------+
| |
V |
+----------------+ |
| Process Cert | |
+----------------+ |
| |
V |
+================+ |
| IF Last Cert | |
| in Path | |
+================+ |
| | |
THEN | | ELSE |
V V |
+----------------+ +----------------+ |
| Wrap up | | Prepare for | |
+----------------+ | Next Cert | |
| +----------------+ |
V | |
+-------+ +--------------+
| STOP |
+-------+
Figure 2. Certification Path Processing Flowchart
图2. 证书路径处理流程图
6.1.1. Inputs (输入)
此算法假设向路径处理逻辑提供以下九个输入:
(a) 长度为n的预期证书路径.
(b) 当前日期/时间.
(c) user-initial-policy-set (用户初始策略集): 命名对证书用户可接受的策略的证书策略标识符集. 如果用户不关心证书策略, 则user-initial-policy-set包含特殊值any-policy.
(d) 信任锚信息 (trust anchor information), 描述用作证书路径信任锚的CA. 信任锚信息包括:
(1) 受信任颁发者名称 (trusted issuer name),
(2) 受信任公钥算法 (trusted public key algorithm),
(3) 受信任公钥 (trusted public key), 以及
(4) 可选地, 与公钥关联的受信任公钥参数 (trusted public key parameters).
信任锚信息可以以自签名证书的形式提供给路径处理过程. 当信任锚信息以证书形式提供时, subject字段中的名称用作受信任颁发者名称, subjectPublicKeyInfo字段的内容用作受信任公钥算法和受信任公钥的来源. 信任锚信息是可信的, 因为它是通过某种值得信赖的带外过程传递给路径处理过程的. 如果受信任公钥算法需要参数, 则参数与受信任公钥一起提供.
(e) initial-policy-mapping-inhibit (初始策略映射禁止), 指示是否允许在证书路径中进行策略映射.
(f) initial-explicit-policy (初始明确策略), 指示路径是否必须对user-initial-policy-set中的至少一个证书策略有效.
(g) initial-any-policy-inhibit (初始anyPolicy禁止), 指示如果anyPolicy OID包含在证书中, 是否应处理它.
(h) initial-permitted-subtrees (初始允许子树), 对于每种名称类型 (例如, X.500可辨别名称、电子邮件地址或IP地址), 指示证书路径中每个证书中的所有主体名称必须 (MUST) 位于其中的子树集. initial-permitted-subtrees输入包括每种名称类型的集合. 对于每种名称类型, 该集合可以由包含该名称类型的所有名称的单个子树或指定该名称类型的名称子集的一个或多个子树组成, 或者该集合可以为空. 如果名称类型的集合为空, 则如果证书路径中的任何证书包含该名称类型的名称, 则证书路径将被视为无效.
(i) initial-excluded-subtrees (初始排除子树), 对于每种名称类型 (例如, X.500可辨别名称、电子邮件地址或IP地址), 指示证书路径中任何证书中的主体名称可能不位于其中的子树集. initial-excluded-subtrees输入包括每种名称类型的集合. 对于每种名称类型, 该集合可以为空, 或可以由指定该名称类型的名称子集的一个或多个子树组成. 如果名称类型的集合为空, 则不排除该名称类型的名称.
符合标准的实现不要求 (not required) 支持所有这些输入的设置. 例如, 符合标准的实现可以设计为使用initial-any-policy-inhibit的FALSE值验证所有证书路径.
6.1.2. Initialization (初始化)
此初始化阶段基于九个输入建立十一个状态变量:
(a) valid_policy_tree (有效策略树): 具有其可选限定符的证书策略树; 树的每个叶子表示在证书路径验证的此阶段的有效策略. 如果在证书路径验证的此阶段存在有效策略, 则树的深度等于已处理的链中的证书数量. 如果在证书路径验证的此阶段不存在有效策略, 则树设置为NULL. 一旦树设置为NULL, 策略处理停止.
valid_policy_tree中的每个节点包括三个数据对象: 有效策略 (valid policy)、一组相关策略限定符 (associated policy qualifiers) 和一组一个或多个预期策略值 (expected policy values). 如果节点位于深度x, 则节点的组件具有以下语义:
(1) valid_policy是表示长度为x的路径的有效策略的单个策略OID.
(2) qualifier_set是与证书x中的有效策略关联的策略限定符集.
(3) expected_policy_set包含一个或多个策略OID, 这些OID将在证书x+1中满足此策略.
valid_policy_tree的初始值是具有valid_policy anyPolicy、空qualifier_set和具有单个值anyPolicy的expected_policy_set的单个节点. 此节点被认为位于深度零.
图3是valid_policy_tree初始状态的图形表示. 其他图形将使用此格式来描述路径处理期间valid_policy_tree中的更改.
+----------------+
| anyPolicy | <---- valid_policy
+----------------+
| {} | <---- qualifier_set
+----------------+
| {anyPolicy} | <---- expected_policy_set
+----------------+
Figure 3. Initial Value of the valid_policy_tree State Variable
图3. valid_policy_tree状态变量的初始值
(b) permitted_subtrees (允许子树): 对于每种名称类型 (例如, X.500可辨别名称、电子邮件地址或IP地址) 的根名称集, 定义证书路径中后续证书中的所有主体名称必须 (MUST) 位于其中的子树集. 此变量包括每种名称类型的集合, 初始值为initial-permitted-subtrees.
(c) excluded_subtrees (排除子树): 对于每种名称类型 (例如, X.500可辨别名称、电子邮件地址或IP地址) 的根名称集, 定义证书路径中后续证书中的主体名称可能不位于其中的子树集. 此变量包括每种名称类型的集合, 初始值为initial-excluded-subtrees.
(d) explicit_policy (明确策略): 指示是否需要非NULL valid_policy_tree的整数. 该整数指示在施加此要求之前要处理的非自签发证书的数量. 一旦设置, 此变量可以减少, 但不能增加. 也就是说, 如果路径中的证书需要非NULL valid_policy_tree, 则较晚的证书不能删除此要求. 如果设置了initial-explicit-policy, 则初始值为0, 否则初始值为n+1.
(e) inhibit_anyPolicy (禁止anyPolicy): 指示是否将anyPolicy策略标识符视为匹配的整数. 该整数指示在忽略anyPolicy OID (如果在中间自签发证书以外的证书中声明) 之前要处理的非自签发证书的数量. 一旦设置, 此变量可以减少, 但不能增加. 也就是说, 如果路径中的证书禁止处理anyPolicy, 则较晚的证书不能允许它. 如果设置了initial-any-policy-inhibit, 则初始值为0, 否则初始值为n+1.
(f) policy_mapping (策略映射): 指示是否允许策略映射的整数. 该整数指示在禁止策略映射之前要处理的非自签发证书的数量. 一旦设置, 此变量可以减少, 但不能增加. 也就是说, 如果路径中的证书指定不允许策略映射, 则较晚的证书不能覆盖它. 如果设置了initial-policy-mapping-inhibit, 则初始值为0, 否则初始值为n+1.
(g) working_public_key_algorithm (工作公钥算法): 用于验证证书签名的数字签名算法. working_public_key_algorithm从信任锚信息中提供的受信任公钥算法初始化.
(h) working_public_key (工作公钥): 用于验证证书签名的公钥. working_public_key从信任锚信息中提供的受信任公钥初始化.
(i) working_public_key_parameters (工作公钥参数): 与当前公钥关联的参数, 可能需要验证签名 (取决于算法). working_public_key_parameters变量从信任锚信息中提供的受信任公钥参数初始化.
(j) working_issuer_name (工作颁发者名称): 链中下一个证书中预期的颁发者可辨别名称. working_issuer_name初始化为信任锚信息中提供的受信任颁发者名称.
(k) max_path_length (最大路径长度): 此整数初始化为n, 对于路径中的每个非自签发证书递减, 并可能减少到CA证书的基本约束扩展内的路径长度约束字段中的值.
完成初始化步骤后, 执行第6.1.3节中指定的基本证书处理步骤.
6.1.3. Basic Certificate Processing (基本证书处理)
要为证书i (对于[1..n]中的所有i) 执行的基本路径处理操作如下所列.
(a) 验证基本证书信息 (Verify the basic certificate information). 证书必须 (MUST) 满足以下每一项:
(1) 可以使用working_public_key_algorithm、working_public_key和working_public_key_parameters验证证书上的签名.
(2) 证书有效期包括当前时间.
(3) 在当前时间, 证书未被撤销. 这可以通过获取适当的CRL (第6.3节)、通过状态信息或通过带外机制来确定.
(4) 证书颁发者名称是working_issuer_name.
(b) 如果证书i是自签发的并且它不是路径中的最终证书, 则对证书i跳过此步骤. 否则, 验证主体名称位于X.500可辨别名称的permitted_subtrees之一内, 并验证subjectAltName扩展 (关键或非关键) 中的每个备用名称位于该名称类型的permitted_subtrees之一内.
(c) 如果证书i是自签发的并且它不是路径中的最终证书, 则对证书i跳过此步骤. 否则, 验证主体名称不在X.500可辨别名称的任何excluded_subtrees内, 并验证subjectAltName扩展 (关键或非关键) 中的每个备用名称不在该名称类型的任何excluded_subtrees内.
(d) 如果证书策略扩展存在于证书中并且valid_policy_tree不为NULL, 则通过按顺序执行以下步骤来处理策略信息:
(1) 对于证书策略扩展中不等于anyPolicy的每个策略P, 令P-OID表示策略P的OID, P-Q表示策略P的限定符集. 按顺序执行以下步骤:
(i) 对于valid_policy_tree中P-OID在expected_policy_set中的深度i-1的每个节点, 按如下方式创建子节点: 将valid_policy设置为P-OID, 将qualifier_set设置为P-Q, 并将expected_policy_set设置为{P-OID}.
例如, 考虑具有深度i-1节点的valid_policy_tree, 其中expected_policy_set为{Gold, White}. 假设证书i的证书策略扩展中出现Gold和Silver证书策略. Gold策略匹配, 但Silver策略不匹配. 此规则将为Gold策略生成深度i的子节点. 结果如图4所示.
+-----------------+
| Red |
+-----------------+
| {} |
+-----------------+ 深度i-1的节点
| {Gold, White} |
+-----------------+
|
|
|
V
+-----------------+
| Gold |
+-----------------+
| {} |
+-----------------+ 深度i的节点
| {Gold} |
+-----------------+
Figure 4. Processing an Exact Match
图4. 处理完全匹配
(ii) 如果在步骤(i)中没有匹配, 并且valid_policy_tree包含深度i-1的valid_policy为anyPolicy的节点, 则生成具有以下值的子节点: 将valid_policy设置为P-OID, 将qualifier_set设置为P-Q, 并将expected_policy_set设置为{P-OID}.
例如, 考虑具有深度i-1节点的valid_policy_tree, 其中valid_policy为anyPolicy. 假设证书i的证书策略扩展中出现Gold和Silver证书策略. Gold策略没有限定符, 但Silver策略具有限定符Q-Silver. 如果Gold和Silver在上面的(i)中未匹配, 则此规则将生成两个深度i的子节点, 每个策略一个. 结果如图5所示.
+-----------------+
| anyPolicy |
+-----------------+
| {} |
+-----------------+ 深度i-1的节点
| {anyPolicy} |
+-----------------+
/ \
/ \
/ \
/ \
+-----------------+ +-----------------+
| Gold | | Silver |
+-----------------+ +-----------------+
| {} | | {Q-Silver} |
+-----------------+ 深度i的 +-----------------+
| {Gold} | 节点 | {Silver} |
+-----------------+ +-----------------+
Figure 5. Processing Unmatched Policies when a
Leaf Node Specifies anyPolicy
图5. 当叶节点指定anyPolicy时处理未匹配的策略
(2) 如果证书策略扩展包括具有限定符集AP-Q的策略anyPolicy, 并且(a) inhibit_anyPolicy大于0或(b) i<n并且证书是自签发的, 则:
对于深度i-1的valid_policy_tree中的每个节点, 对于expected_policy_set中未出现在子节点中的每个值 (包括anyPolicy), 使用以下值创建子节点: 将valid_policy设置为父节点中expected_policy_set的值, 将qualifier_set设置为AP-Q, 并将expected_policy_set设置为此节点中valid_policy的值.
例如, 考虑具有深度i-1节点的valid_policy_tree, 其中expected_policy_set为{Gold, Silver}. 假设证书i的证书策略扩展中出现anyPolicy, 没有策略限定符, 但Gold和Silver不出现. 此规则将生成两个深度i的子节点, 每个策略一个. 结果如下图6所示.
+-----------------+
| Red |
+-----------------+
| {} |
+-----------------+ 深度i-1的节点
| {Gold, Silver} |
+-----------------+
/ \
/ \
/ \
/ \
+-----------------+ +-----------------+
| Gold | | Silver |
+-----------------+ +-----------------+
| {} | | {} |
+-----------------+ 深度i的 +-----------------+
| {Gold} | 节点 | {Silver} |
+-----------------+ +-----------------+
Figure 6. Processing Unmatched Policies When the
Certificate Policies Extension Specifies anyPolicy
图6. 当证书策略扩展指定anyPolicy时处理未匹配的策略
(3) 如果在valid_policy_tree中存在深度i-1或更小且没有任何子节点的节点, 则删除该节点. 重复此步骤, 直到没有深度i-1或更小且没有子节点的节点.
例如, 考虑下图7所示的valid_policy_tree. 深度i-1处标记为'X'的两个节点没有子节点, 它们被删除. 将此规则应用于结果树将导致删除标记为'Y'的深度i-2处的节点. 在结果树中, 没有深度i-1或更小且没有子节点的节点, 此步骤完成.
+-----------+
| | 深度i-3的节点
+-----------+
/ | \
/ | \
/ | \
+-----------+ +-----------+ +-----------+
| | | | | Y | 深度i-2
+-----------+ +-----------+ +-----------+ 的节点
/ \ | |
/ \ | |
/ \ | |
+-----------+ +-----------+ +-----------+ +-----------+ 深度i-1
| | | X | | | | X | 的节点
+-----------+ +-----------+ +-----------+ +-----------+
| / | \
| / | \
| / | \
+-----------+ +-----------+ +-----------+ +-----------+ 深度i
| | | | | | | | 的节点
+-----------+ +-----------+ +-----------+ +-----------+
Figure 7. Pruning the valid_policy_tree
图7. 修剪valid_policy_tree
(e) 如果证书策略扩展不存在, 则将valid_policy_tree设置为NULL.
(f) 验证explicit_policy大于0或valid_policy_tree不等于NULL;
如果步骤(a)、(b)、(c)或(f)中的任何一个失败, 则过程终止, 返回失败指示和适当的原因.
如果i不等于n, 则通过执行第6.1.4节中列出的准备步骤继续. 如果i等于n, 则执行第6.1.5节中列出的收尾步骤.
6.1.4. Preparation for Certificate i+1 (为证书i+1准备)
要为证书i+1的处理做准备, 对证书i执行以下步骤:
(a) 如果存在策略映射扩展, 则验证特殊值anyPolicy不作为issuerDomainPolicy或subjectDomainPolicy出现.
(b) 如果存在策略映射扩展, 则对于策略映射扩展中的每个issuerDomainPolicy ID-P:
(1) 如果policy_mapping变量大于0, 对于valid_policy_tree中深度i的每个节点, 其中ID-P是valid_policy, 将expected_policy_set设置为由策略映射扩展指定为等效于ID-P的subjectDomainPolicy值集.
如果valid_policy_tree中深度i的节点没有ID-P的valid_policy, 但存在具有anyPolicy的valid_policy的深度i的节点, 则按如下方式生成具有anyPolicy的valid_policy的深度i-1的节点的子节点:
(i) 将valid_policy设置为ID-P;
(ii) 将qualifier_set设置为证书i的证书策略扩展中策略anyPolicy的限定符集; 以及
(iii) 将expected_policy_set设置为由策略映射扩展指定为等效于ID-P的subjectDomainPolicy值集.
(2) 如果policy_mapping变量等于0:
(i) 删除valid_policy_tree中深度i的每个节点, 其中ID-P是valid_policy.
(ii) 如果在valid_policy_tree中存在深度i-1或更小且没有任何子节点的节点, 则删除该节点. 重复此步骤, 直到没有深度i-1或更小且没有子节点的节点.
(c) 将证书主体名称分配给working_issuer_name.
(d) 将证书subjectPublicKey分配给working_public_key.
(e) 如果证书的subjectPublicKeyInfo字段包含具有非空参数的算法字段, 则将参数分配给working_public_key_parameters变量.
如果证书的subjectPublicKeyInfo字段包含具有空参数的算法字段或省略参数, 则将证书subjectPublicKey算法与working_public_key_algorithm进行比较. 如果证书subjectPublicKey算法和working_public_key_algorithm不同, 则将working_public_key_parameters设置为null.
(f) 将证书subjectPublicKey算法分配给working_public_key_algorithm变量.
(g) 如果证书中包含名称约束扩展, 则按如下方式修改permitted_subtrees和excluded_subtrees状态变量:
(1) 如果证书中存在permittedSubtrees, 则将permitted_subtrees状态变量设置为其先前值与扩展字段中指示的值的交集. 如果permittedSubtrees不包括特定名称类型, 则该名称类型的permitted_subtrees状态变量不变. 例如, example.com和foo.example.com的交集是foo.example.com. 而example.com和example.net的交集是空集.
(2) 如果证书中存在excludedSubtrees, 则将excluded_subtrees状态变量设置为其先前值与扩展字段中指示的值的并集. 如果excludedSubtrees不包括特定名称类型, 则该名称类型的excluded_subtrees状态变量不变. 例如, 名称空间example.com和foo.example.com的并集是example.com. 而example.com和example.net的并集是两个名称空间.
(h) 如果证书i不是自签发的:
(1) 如果explicit_policy不为0, 则将explicit_policy减1.
(2) 如果policy_mapping不为0, 则将policy_mapping减1.
(3) 如果inhibit_anyPolicy不为0, 则将inhibit_anyPolicy减1.
(i) 如果证书中包含策略约束扩展, 则按如下方式修改explicit_policy和policy_mapping状态变量:
(1) 如果存在requireExplicitPolicy并且小于explicit_policy, 则将explicit_policy设置为requireExplicitPolicy的值.
(2) 如果存在inhibitPolicyMapping并且小于policy_mapping, 则将policy_mapping设置为inhibitPolicyMapping的值.
(j) 如果证书中包含inhibitAnyPolicy扩展并且小于inhibit_anyPolicy, 则将inhibit_anyPolicy设置为inhibitAnyPolicy的值.
(k) 如果证书i是版本3证书, 则验证basicConstraints扩展存在并且cA设置为TRUE. (如果证书i是版本1或版本2证书, 则应用程序必须 (MUST) 通过带外方式验证证书i是CA证书或拒绝证书. 符合标准的实现可以 (MAY) 选择拒绝所有版本1和版本2中间证书.)
(l) 如果证书不是自签发的, 则验证max_path_length大于零, 并将max_path_length减1.
(m) 如果证书中存在pathLenConstraint并且小于max_path_length, 则将max_path_length设置为pathLenConstraint的值.
(n) 如果存在密钥用途扩展, 则验证keyCertSign位已设置.
(o) 识别并处理证书中存在的任何其他关键扩展. 处理证书中存在的与路径处理相关的任何其他已识别的非关键扩展.
如果检查(a)、(k)、(l)、(n)或(o)失败, 则过程终止, 返回失败指示和适当的原因.
如果(a)、(k)、(l)、(n)和(o)已成功完成, 则增加i并执行第6.1.3节中指定的基本证书处理.
6.1.5. Wrap-Up Procedure (收尾过程)
要完成目标证书的处理, 对证书n执行以下步骤:
(a) 如果explicit_policy不为0, 则将explicit_policy减1.
(b) 如果证书中包含策略约束扩展并且存在requireExplicitPolicy并且值为0, 则将explicit_policy状态变量设置为0.
(c) 将证书subjectPublicKey分配给working_public_key.
(d) 如果证书的subjectPublicKeyInfo字段包含具有非空参数的算法字段, 则将参数分配给working_public_key_parameters变量.
如果证书的subjectPublicKeyInfo字段包含具有空参数的算法字段或省略参数, 则将证书subjectPublicKey算法与working_public_key_algorithm进行比较. 如果证书subjectPublicKey算法和working_public_key_algorithm不同, 则将working_public_key_parameters设置为null.
(e) 将证书subjectPublicKey算法分配给working_public_key_algorithm变量.
(f) 识别并处理证书n中存在的任何其他关键扩展. 处理证书n中存在的与路径处理相关的任何其他已识别的非关键扩展.
(g) 计算valid_policy_tree和user-initial-policy-set的交集, 如下所示:
(i) 如果valid_policy_tree为NULL, 则交集为NULL.
(ii) 如果valid_policy_tree不为NULL并且user-initial-policy-set为any-policy, 则交集是整个valid_policy_tree.
(iii) 如果valid_policy_tree不为NULL并且user-initial-policy-set不是any-policy, 则按如下方式计算valid_policy_tree和user-initial-policy-set的交集:
-
确定其父节点具有anyPolicy的valid_policy的策略节点集. 这是valid_policy_node_set.
-
如果valid_policy_node_set中任何节点的valid_policy不在user-initial-policy-set中并且不是anyPolicy, 则删除此节点及其所有子节点.
-
如果valid_policy_tree包括深度n的节点, 其valid_policy为anyPolicy, 并且user-initial-policy-set不是any-policy, 则执行以下步骤:
a. 将P-Q设置为深度n的节点中的qualifier_set, 其valid_policy为anyPolicy.
b. 对于user-initial-policy-set中不是valid_policy_node_set中节点的valid_policy的每个P-OID, 创建一个子节点, 其父节点是深度n-1的节点, 其valid_policy为anyPolicy. 在子节点中设置值如下: 将valid_policy设置为P-OID, 将qualifier_set设置为P-Q, 并将expected_policy_set设置为
{P-OID}.c. 删除深度n的节点, 其valid_policy为anyPolicy.
-
如果在valid_policy_tree中存在深度n-1或更小且没有任何子节点的节点, 则删除该节点. 重复此步骤, 直到没有深度n-1或更小且没有子节点的节点.
如果(1) explicit_policy变量的值大于零或(2) valid_policy_tree不为NULL, 则路径处理已成功.
6.1.6. Outputs (输出)
如果路径处理成功, 则过程终止, 返回成功指示以及valid_policy_tree、working_public_key、working_public_key_algorithm和working_public_key_parameters的最终值.
6.2. Using the Path Validation Algorithm (使用路径验证算法)
路径验证算法描述验证单个证书路径的过程. 虽然每个证书路径以特定信任锚开始, 但不要求特定系统验证的所有证书路径共享单个信任锚. 选择一个或多个受信任CA是本地决策. 系统可以提供其任何受信任CA作为特定路径的信任锚. 对于每个路径, 路径验证算法的输入可能不同. 用于处理路径的输入可能反映应用程序特定的要求或对特定信任锚授予的信任的限制. 例如, 受信任CA可能仅对特定证书策略受信任. 此限制可以通过路径验证过程的输入来表达.
实现可以 (MAY) 扩展第6.1节中介绍的算法以进一步限制以特定信任锚开始的有效证书路径集. 例如, 实现可以 (MAY) 修改算法以在初始化阶段对特定信任锚应用路径长度约束, 或应用程序可以 (MAY) 要求目标证书中存在特定备用名称形式, 或应用程序可以 (MAY) 对应用程序特定扩展施加要求. 因此, 第6.1节中介绍的路径验证算法定义了将路径视为有效的最低条件.
当CA分发自签名证书以指定信任锚信息时, 可以使用证书扩展来指定路径验证的推荐输入. 例如, 可以在自签名证书中包含策略约束扩展, 以指示以此信任锚开始的路径应仅对指定策略受信任. 类似地, 可以包含名称约束扩展, 以指示以此信任锚开始的路径应仅对指定名称空间受信任. 第6.1节中介绍的路径验证算法不假设信任锚信息以自签名证书的形式提供, 也不为此类证书中包含的附加信息指定处理规则. 使用自签名证书指定信任锚信息的实现可以自由处理或忽略此类信息.
6.3. CRL Validation (CRL验证)
本节描述当CRL是证书颁发者使用的撤销机制时确定证书是否已被撤销所需的步骤. 支持CRL的符合标准实现不要求 (not required) 实现此算法, 但在处理符合此配置文件颁发的CRL时, 它们必须 (MUST) 在功能上等效于此过程产生的外部行为. 特定实现可以使用任何算法, 只要它得出正确的结果.
此算法假设所有需要的CRL都在本地缓存中可用. 此外, 如果CRL的下次更新时间已过, 则算法假设一种机制来获取当前CRL并将其放入本地CRL缓存.
此算法定义了一组输入、一组状态变量以及对路径中的每个证书执行的处理步骤. 算法输出是证书的撤销状态.
6.3.1. Revocation Inputs (撤销输入)
为了支持撤销处理, 算法需要两个输入:
(a) certificate (证书): 算法需要证书序列号和颁发者名称来确定证书是否在特定CRL上. basicConstraints扩展用于确定提供的证书是与CA还是终端实体关联. 如果存在, 算法使用cRLDistributionPoints和freshestCRL扩展来确定撤销状态.
(b) use-deltas (使用增量): 此布尔输入确定是否将增量CRL应用于CRL.
6.3.2. Initialization and Revocation State Variables (初始化和撤销状态变量)
为了支持CRL处理, 算法需要以下状态变量:
(a) reasons_mask (原因掩码): 此变量包含迄今处理的CRL和增量CRL支持的撤销原因集. 集合的合法成员是可能的撤销原因值减去unspecified: keyCompromise、cACompromise、affiliationChanged、superseded、cessationOfOperation、certificateHold、privilegeWithdrawn和aACompromise. 特殊值all-reasons用于表示所有合法成员的集合. 此变量初始化为空集.
(b) cert_status (证书状态): 此变量包含证书的状态. 此变量可以分配以下值之一: unspecified、keyCompromise、cACompromise、affiliationChanged、superseded、cessationOfOperation、certificateHold、removeFromCRL、privilegeWithdrawn、aACompromise、特殊值UNREVOKED或特殊值UNDETERMINED. 此变量初始化为特殊值UNREVOKED.
(c) interim_reasons_mask (中间原因掩码): 包含当前正在处理的CRL或增量CRL支持的撤销原因集.
注意: 在某些环境中, 不需要检查所有原因码. 例如, 某些环境仅关注CA证书的cACompromise和keyCompromise. 此算法检查所有原因码. 可能需要额外的处理和状态变量来将检查限制为原因码的子集.
6.3.3. CRL Processing (CRL处理)
此算法首先假设证书未被撤销. 算法检查一个或多个CRL, 直到证书状态确定为已撤销或已检查足够的CRL以涵盖所有原因码.
对于证书的CRL分发点扩展中的每个分发点 (DP), 对于本地CRL缓存中的每个对应CRL, 在((reasons_mask不是all-reasons) 和 (cert_status是UNREVOKED)) 时执行以下操作:
(a) 通过根据需要获取完整CRL、增量CRL或两者来更新本地CRL缓存:
(1) 如果当前时间在CRL的next update字段的值之后, 则执行以下操作之一:
(i) 如果设置了use-deltas, 并且证书或CRL包含最新CRL扩展, 则获取next update值在当前时间之后的增量CRL, 并可以用于更新本地缓存的CRL, 如第5.2.4节所述.
(ii) 使用当前完整CRL更新本地CRL缓存, 验证当前时间在新CRL中next update值之前, 并继续使用新CRL处理. 如果设置了use-deltas, 并且证书或CRL包含最新CRL扩展, 则获取可以用于更新新本地缓存的完整CRL的当前增量CRL, 如第5.2.4节所述.
(2) 如果当前时间在next update字段的值之前, 设置了use-deltas, 并且证书或CRL包含最新CRL扩展, 则获取可以用于更新本地缓存的完整CRL的当前增量CRL, 如第5.2.4节所述.
(b) 按如下方式验证完整CRL的颁发者和范围:
(1) 如果DP包括cRLIssuer, 则验证完整CRL中的issuer字段与DP中的cRLIssuer匹配, 并且完整CRL包含断言indirectCRL布尔值的颁发分发点扩展. 否则, 验证CRL颁发者与证书颁发者匹配.
(2) 如果完整CRL包括颁发分发点 (IDP) CRL扩展, 则检查以下内容:
(i) 如果IDP CRL扩展中存在分发点名称并且DP中存在分发字段, 则验证IDP中的一个名称与DP中的一个名称匹配. 如果IDP CRL扩展中存在分发点名称并且DP中省略了分发字段, 则验证IDP中的一个名称与DP的cRLIssuer字段中的一个名称匹配.
(ii) 如果在IDP CRL扩展中断言onlyContainsUserCerts布尔值, 则验证证书不包括断言cA布尔值的基本约束扩展.
(iii) 如果在IDP CRL扩展中断言onlyContainsCACerts布尔值, 则验证证书包括断言cA布尔值的基本约束扩展.
(iv) 验证未断言onlyContainsAttributeCerts布尔值.
(c) 如果设置了use-deltas, 则按如下方式验证增量CRL的颁发者和范围:
(1) 验证增量CRL颁发者与完整CRL颁发者匹配.
(2) 如果完整CRL包括颁发分发点 (IDP) CRL扩展, 则验证增量CRL包含匹配的IDP CRL扩展. 如果完整CRL省略IDP CRL扩展, 则验证增量CRL也省略IDP CRL扩展.
(3) 验证增量CRL授权密钥标识符扩展与完整CRL授权密钥标识符扩展匹配.
(d) 按如下方式计算此CRL的interim_reasons_mask:
(1) 如果存在颁发分发点 (IDP) CRL扩展并包括onlySomeReasons, 并且DP包括reasons, 则将interim_reasons_mask设置为DP中的reasons和IDP CRL扩展中的onlySomeReasons的交集.
(2) 如果IDP CRL扩展包括onlySomeReasons但DP省略reasons, 则将interim_reasons_mask设置为IDP CRL扩展中的onlySomeReasons值.
(3) 如果IDP CRL扩展不存在或省略onlySomeReasons但DP包括reasons, 则将interim_reasons_mask设置为DP reasons的值.
(4) 如果IDP CRL扩展不存在或省略onlySomeReasons并且DP省略reasons, 则将interim_reasons_mask设置为特殊值all-reasons.
(e) 验证interim_reasons_mask包括一个或多个reasons_mask中未包括的原因.
(f) 获取并验证完整CRL颁发者的证书路径. 证书路径的信任锚必须 (MUST) 与用于验证目标证书的信任锚相同. 如果CRL颁发者证书中存在密钥用途扩展, 则验证cRLSign位已设置.
(g) 使用步骤(f)中验证的公钥验证完整CRL上的签名.
(h) 如果设置了use-deltas, 则使用步骤(f)中验证的公钥验证增量CRL上的签名.
(i) 如果设置了use-deltas, 则在增量CRL上搜索证书. 如果找到与第5.3.3节中描述的证书颁发者和序列号匹配的条目, 则将cert_status变量设置为如下指示的原因:
(1) 如果存在原因码CRL条目扩展, 则将cert_status变量设置为原因码CRL条目扩展的值.
(2) 如果不存在原因码CRL条目扩展, 则将cert_status变量设置为值unspecified.
(j) 如果(cert_status为UNREVOKED), 则在完整CRL上搜索证书. 如果找到与第5.3.3节中描述的证书颁发者和序列号匹配的条目, 则按步骤(i)中描述的方式将cert_status变量设置为指示的原因.
(k) 如果(cert_status为removeFromCRL), 则将cert_status设置为UNREVOKED.
(l) 将reasons_mask状态变量设置为其先前值与interim_reasons_mask状态变量值的并集.
如果((reasons_mask为all-reasons) 或 (cert_status不为UNREVOKED)), 则已确定撤销状态, 因此返回cert_status.
如果尚未确定撤销状态, 则使用未在分发点中指定但由证书颁发者颁发的任何可用CRL重复上述过程. 对于此类CRL的处理, 假设一个DP, 其中reasons和cRLIssuer字段都省略, 分发点名称为证书颁发者. 也就是说, fullName中的名称序列从证书颁发者字段以及证书issuerAltName扩展生成. 在处理此类CRL之后, 如果仍未确定撤销状态, 则返回cert_status UNDETERMINED.