Java 中的 CRL 验证

CRL Verification in Java

我有一个 CRL 和一个用作 CA 证书的自签名证书。我需要验证同一个 CA 在 Java 中同时颁发了 CRL 和根证书。我的想法是这样的:

X500Principal rootCertIssuer = rootCertificate.getIssuerX500Principal();
X500Principal crlIssuer = crl.getIssuerX500Principal();
    if(rootCertIssuer.getName().equals(crlIssuer.getName()))
    System.out.println("Issuer same!");
else
    System.out.println("Issuer different!");

这似乎不对,因为如果 Country/State 信息在 CRL 或根证书之一中丢失,equals() 将 return 一个 false .我该如何进行?或者,与我的想法相反,这种做法对吗?

谢谢!

如果 CA 证书和 CRL 上的 Issuer Distinguished Names 不同,则它们必须被视为由不同的颁发者颁发。如果在生成 CRL 或任何其他签名对象时 Issuer DN "go missing" 的位,那么,这违反了 X.509 和错误。

请注意,CA 可以委托 CRL 签名给从属的 CRL 颁发者,因此 general CRL 验证函数必须处理这种情况,以及直接 CRL 颁发。

正如@frasertweedale 所提到的,证书颁发者和 CRL 颁发者不一定需要相同。但是,没有太多理由将 CRL 颁发委托给另一个机构,而且并非所有系统都支持。例如,Windows 链验证代码仅支持由颁发 CRL 涵盖的证书的同一 CA 颁发(签署)的 CRL。

一般来说,验证逻辑由两部分组成,如下所示:

  1. 读取证书(非根)的 CDP(CRL 分发点)扩展并循环 CRLDistributionPoints 序列。如果存在具有呈现 cRLIssuer 结构的条目,则此分发点引用的 CRL 由 cRLIssuer 字段中指定的实体签名。如果未显示 cRLIssuer 字段,则证书和 CRL 由同一 CA 签名,并且 CRL 位置在 distributionPointName 字段中指定。
  2. 下载(或使用其他方式下载 CRL)CRL(和 CRL 颁发者证书,如有必要)并启动 CRL 验证例程。

针对颁发者的 CRL 验证分两步执行:

  1. 首先,您需要对 CRL 中的 Issuer 字段和 CRL 颁发者证书的 Subject 字段进行二进制(非字符串)比较。如果比较失败,则CRL无效。
  2. 使用 CRL 颁发者证书的 public 密钥来验证 CRL 签名。如果签名验证失败,则CRL无效。

有关 CRL 分发点扩展组成和处理规则的更多信息:RFC 5280 §4.2.1.13

请注意,由于 Java8 有一种验证证书链的方法,包括 CRL 检查,请参见此处:

如果您使用 self-signed 证书,您确实需要确保相关方的 key/trust 商店已正确填充(默认 cacerts)。

我认为,问题名称的字符串比较是一种非常薄弱的​​方法。